Skip to content

Conversation

@nertpinx
Copy link

When the __pin_data!(find_pinned_fields: part of the macro encounters an unknown attribute (anything apart from $[pin]) before a field, it is put into the accumulator and the macro proceeds further. Whatever is in the accumulator is later saved into $fields and then also into $pinned or $not_pinned depending on whether that field is pinned. Pinned fields, with all their unknown attributes are also used in the internal __Unpin struct.

A field can have multiple different attributes, mostly belonging into two different categories. Built-in (defined by the language itself) and arbitrary (any other attribute that is used by another proc-macro crate).

Out of the built-in ones [1] the only things that make sense to be usable for struct fields are most probably just "cfg", "doc", lint levels ("allow", "expect", "warn", "deny", "forbid"), and "deprecated". Out of these the only one that makes sense to keep around for the pin_data macro is "cfg" since that one does a conditional compilation and we only want the members to be included if they are included in the original struct.

From the arbitrary (basically unknown) ones there is no reason for them to be used, mainly because they will likely be part of a derive which will not be included for the __Unpin struct, therefore making the code fail to compile if included. Since those need to be kept for the original struct, move them to the $fields instead of $accum in order not to pollute the struct __Unpin with unknown attributes.

To put this all together, add a test with a custom attribute that fails without this fix. Unfortunately, another crate needs to be added for the test.

[1] https://doc.rust-lang.org/reference/attributes.html#built-in-attributes-index

When the `__pin_data!(find_pinned_fields:` part of the macro encounters
an unknown attribute (anything apart from `$[pin]`) before a field, it
is put into the accumulator and the macro proceeds further.  Whatever is
in the accumulator is later saved into `$fields` and then also into
`$pinned` or `$not_pinned` depending on whether that field is pinned.
Pinned fields, with all their unknown attributes are also used in the
internal `__Unpin` struct.

A field can have multiple different attributes, mostly belonging into
two different categories. Built-in (defined by the language itself) and
arbitrary (any other attribute that is used by another proc-macro
crate).

Out of the built-in ones [1] the only things that make sense to be
usable for struct fields are most probably just "cfg", "doc", lint
levels ("allow", "expect", "warn", "deny", "forbid"), and "deprecated".
Out of these the only one that makes sense to keep around for the
pin_data macro is "cfg" since that one does a conditional compilation
and we only want the members to be included if they are included in the
original struct.

From the arbitrary (basically unknown) ones there is no reason for them
to be used, mainly because they will likely be part of a derive which
will not be included for the `__Unpin` struct, therefore making the code
fail to compile if included.  Since those need to be kept for the
original struct, move them to the `$fields` instead of `$accum` in order
not to pollute the `struct __Unpin` with unknown attributes.

To put this all together, add a test with a custom attribute that fails
without this fix.  Unfortunately, another crate needs to be added for
the test.

[1] https://doc.rust-lang.org/reference/attributes.html#built-in-attributes-index

Signed-off-by: Martin Kletzander <[email protected]>
@BennoLossin
Copy link
Member

Thanks for your PR! I'm currently very busy and won't be taking a look for the next few weeks, sorry about that.

This limitation is annoying and I wanted to get rid of it in the future. I will be merging #89 in the next kernel cycle (in around 5-6 weeks). Would you mind re-doing the work based on syn instead? That'll probably be a lot easier than doing this with declarative macros :)

The test looks good by the way!

@nertpinx
Copy link
Author

I'll see what I can do. I finally understood how to fix it in the legacy branch and I have to figure out how it works after #89 but I'll do my best.
Just out of curiosity, are there no legacy releases scheduled where this could be merged in the meantime?

@nertpinx nertpinx changed the title Allow other attributes in #[pin_data] structs [legacy] Allow other attributes in #[pin_data] structs Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants