Skip to content

Commit ab0c828

Browse files
committed
Allow other attributes in #[pin_data] structs
When using a macro with custom attributes in a `#[pin_data]` struct it can mess up the generated `__Unpin` struct. This commit catches all other (not just `#[pin]`) attributes, moves the `#[cfg]` one in `$accum` (so that it is used for both the original struct and the generated `__Unpin` one), and keeps all other (custom, documentation, etc.) only in the original struct. With this commit a struct can use both #[pin] and other custom attributes, allowing combining multiple attribute macros without clashing. To keep this functionality this commit also adds a test with a custom attribute that fails without this fix. Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
1 parent bc137a3 commit ab0c828

File tree

7 files changed

+90
-3
lines changed

7 files changed

+90
-3
lines changed

Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ trybuild = { version = "1.0", features = ["diff"] }
3232
macrotest = "1.0"
3333
# needed for macrotest, have to enable verbatim feature to be able to format `&raw` expressions.
3434
prettyplease = { version = "0.2", features = ["verbatim"] }
35+
dummy = { path = "tests/dummy" }
3536

3637
[lints.rust]
3738
non_ascii_idents = "deny"

src/macros.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -779,8 +779,9 @@ macro_rules! __pin_data {
779779
@ty_generics($($ty_generics:tt)*),
780780
@decl_generics($($decl_generics:tt)*),
781781
@where($($whr:tt)*),
782-
// Some other attribute, just put it into `$accum`.
783-
@fields_munch(#[$($attr:tt)*] $($rest:tt)*),
782+
// The #[cfg] attributes are kept for those members that are not
783+
// removed, so we need to keep them.
784+
@fields_munch(#[cfg $($attr:tt)*] $($rest:tt)*),
784785
@pinned($($pinned:tt)*),
785786
@not_pinned($($not_pinned:tt)*),
786787
@fields($($fields:tt)*),
@@ -800,7 +801,41 @@ macro_rules! __pin_data {
800801
@pinned($($pinned)*),
801802
@not_pinned($($not_pinned)*),
802803
@fields($($fields)*),
803-
@accum($($accum)* #[$($attr)*]),
804+
@accum($($accum)* #[cfg $($attr)*]),
805+
@is_pinned($($is_pinned)?),
806+
@pinned_drop($($pinned_drop)?),
807+
);
808+
};
809+
(find_pinned_fields:
810+
@struct_attrs($($struct_attrs:tt)*),
811+
@vis($vis:vis),
812+
@name($name:ident),
813+
@impl_generics($($impl_generics:tt)*),
814+
@ty_generics($($ty_generics:tt)*),
815+
@decl_generics($($decl_generics:tt)*),
816+
@where($($whr:tt)*),
817+
// Some other attribute, just put it into `$fields`
818+
@fields_munch(#[$($attr:tt)*] $($rest:tt)*),
819+
@pinned($($pinned:tt)*),
820+
@not_pinned($($not_pinned:tt)*),
821+
@fields($($fields:tt)*),
822+
@accum($($accum:tt)*),
823+
@is_pinned($($is_pinned:ident)?),
824+
@pinned_drop($($pinned_drop:ident)?),
825+
) => {
826+
$crate::__pin_data!(find_pinned_fields:
827+
@struct_attrs($($struct_attrs)*),
828+
@vis($vis),
829+
@name($name),
830+
@impl_generics($($impl_generics)*),
831+
@ty_generics($($ty_generics)*),
832+
@decl_generics($($decl_generics)*),
833+
@where($($whr)*),
834+
@fields_munch($($rest)*),
835+
@pinned($($pinned)*),
836+
@not_pinned($($not_pinned)*),
837+
@fields($($fields)* #[$($attr)*]),
838+
@accum($($accum)*),
804839
@is_pinned($($is_pinned)?),
805840
@pinned_drop($($pinned_drop)?),
806841
);

tests/dummy/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/dummy/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "dummy"
3+
version = "0.0.0"
4+
edition = "2024"
5+
6+
license = "MIT OR Apache-2.0"
7+
description = "Proc macro only for test reproduction."
8+
9+
publish = false
10+
11+
[lib]
12+
proc-macro = true

tests/dummy/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[proc_macro_derive(Dummy, attributes(dummy_attr))]
2+
pub fn derive_device(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
3+
proc_macro::TokenStream::new()
4+
}

tests/extra_attrs.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
2+
3+
use pinned_init::*;
4+
use dummy::Dummy;
5+
6+
#[pin_data]
7+
#[derive(Dummy)]
8+
struct Pointless {
9+
#[pin]
10+
#[dummy_attr]
11+
#[cfg(test)]
12+
member: i8,
13+
#[pin]
14+
#[dummy_attr]
15+
#[cfg(not(test))]
16+
member: u8,
17+
}
18+
19+
#[test]
20+
fn multiple_attributes() {
21+
stack_pin_init!(let p = init!(Pointless { member: 0 }));
22+
println!("{}", p.member);
23+
}

0 commit comments

Comments
 (0)