From 67ecf8a33ef5c09eb7713865c2dd088bd8c2d8f7 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Wed, 26 Nov 2025 16:29:23 +0100 Subject: [PATCH 1/3] pin_data: Use function for attribute retaining decision This way any future modification into what attributes should be kept can be made in one place rather than chasing all the places where attributes are being filtered. Signed-off-by: Martin Kletzander --- internal/src/pin_data.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/internal/src/pin_data.rs b/internal/src/pin_data.rs index 83785cb..04799aa 100644 --- a/internal/src/pin_data.rs +++ b/internal/src/pin_data.rs @@ -162,7 +162,7 @@ fn generate_unpin_impl( .cloned() .collect::>(); for field in &mut pinned_fields { - field.attrs.retain(|a| !a.path().is_ident("pin")); + field.attrs.retain(keep_attr); } quote! { // This struct will be used for the unpin analysis. It is needed, because only structurally @@ -267,7 +267,7 @@ fn generate_projections( .. }| { let mut attrs = attrs.clone(); - attrs.retain(|a| !a.path().is_ident("pin")); + attrs.retain(keep_attr); let mut no_doc_attrs = attrs.clone(); no_doc_attrs.retain(|a| !a.path().is_ident("doc")); let ident = ident @@ -348,6 +348,16 @@ fn generate_projections( } } +fn keep_attr(attr: &syn::Attribute) -> bool { + let path = attr.path(); + + if path.is_ident("pin") { + return false; + } + + true +} + fn generate_the_pin_data( ItemStruct { generics, @@ -376,7 +386,7 @@ fn generate_the_pin_data( pinned: bool, ) -> TokenStream { let mut attrs = attrs.clone(); - attrs.retain(|a| !a.path().is_ident("pin")); + attrs.retain(keep_attr); let ident = ident .as_ref() .expect("only structs with named fields are supported"); From 12b8371ce3202ac3b20760d552de3dc0a6cee9bf Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Wed, 26 Nov 2025 16:32:26 +0100 Subject: [PATCH 2/3] tests: Add dummy crate for testing attributes This allows the usage of dummy attributes in tests. Signed-off-by: Martin Kletzander --- Cargo.lock | 5 +++++ Cargo.toml | 1 + test_dummy_only/Cargo.lock | 7 +++++++ test_dummy_only/Cargo.toml | 13 +++++++++++++ test_dummy_only/src/lib.rs | 4 ++++ 5 files changed, 30 insertions(+) create mode 100644 test_dummy_only/Cargo.lock create mode 100644 test_dummy_only/Cargo.toml create mode 100644 test_dummy_only/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a99484b..1245d3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -93,6 +93,7 @@ dependencies = [ "pin-init-internal", "prettyplease", "rustc_version", + "test_dummy_only", "trybuild", ] @@ -221,6 +222,10 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test_dummy_only" +version = "0.0.1" + [[package]] name = "toml" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index bf53ab2..2b5e37d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ trybuild = { version = "1.0", features = ["diff"] } macrotest = "1.0" # needed for macrotest, have to enable verbatim feature to be able to format `&raw` expressions. prettyplease = { version = "0.2", features = ["verbatim"] } +test_dummy_only = { path = "./test_dummy_only" } [lints.rust] non_ascii_idents = "deny" diff --git a/test_dummy_only/Cargo.lock b/test_dummy_only/Cargo.lock new file mode 100644 index 0000000..fa62fcd --- /dev/null +++ b/test_dummy_only/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "test_only" +version = "0.0.1" diff --git a/test_dummy_only/Cargo.toml b/test_dummy_only/Cargo.toml new file mode 100644 index 0000000..ada847f --- /dev/null +++ b/test_dummy_only/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "test_dummy_only" +version = "0.0.1" +edition = "2021" + +authors = ["y86-dev"] +license = "MIT OR Apache-2.0" +description = "Proc macro only for test reproduction." + +publish = false + +[lib] +proc-macro = true diff --git a/test_dummy_only/src/lib.rs b/test_dummy_only/src/lib.rs new file mode 100644 index 0000000..0ea0925 --- /dev/null +++ b/test_dummy_only/src/lib.rs @@ -0,0 +1,4 @@ +#[proc_macro_derive(Dummy, attributes(dummy_attr))] +pub fn derive_device(_: proc_macro::TokenStream) -> proc_macro::TokenStream { + proc_macro::TokenStream::new() +} From 8193cd8d4945bfd729cd30a2ad2066ea61537b7e Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Wed, 26 Nov 2025 16:34:02 +0100 Subject: [PATCH 3/3] pin_data: Only keep meaningful attributes Instead of keeping all the member attributes, which might not even make sense for anything else than struct members, keep only those that we're either interested in or might alter the behaviour of the code. This is tested with a new test which illustrates the pre-existing issue where struct might use various attributes for its members which can be valid, but would (before this patch) fail to compile. Signed-off-by: Martin Kletzander --- internal/src/pin_data.rs | 2 +- tests/extra_attrs.rs | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/extra_attrs.rs diff --git a/internal/src/pin_data.rs b/internal/src/pin_data.rs index 04799aa..4ef4f62 100644 --- a/internal/src/pin_data.rs +++ b/internal/src/pin_data.rs @@ -355,7 +355,7 @@ fn keep_attr(attr: &syn::Attribute) -> bool { return false; } - true + path.is_ident("doc") || path.is_ident("cfg") } fn generate_the_pin_data( diff --git a/tests/extra_attrs.rs b/tests/extra_attrs.rs new file mode 100644 index 0000000..e0e3522 --- /dev/null +++ b/tests/extra_attrs.rs @@ -0,0 +1,23 @@ +#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))] + +use pin_init::*; +use test_dummy_only::Dummy; + +#[pin_data] +#[derive(Dummy)] +struct Pointless { + #[pin] + #[dummy_attr] + #[cfg(test)] + member: i8, + #[pin] + #[dummy_attr] + #[cfg(not(test))] + member: u8, +} + +#[test] +fn multiple_attributes() { + stack_pin_init!(let p = init!(Pointless { member: 0 })); + println!("{}", p.member); +}