Skip to content

internal: add tuple struct support in pin_data and pin_init!#113

Open
mqqz wants to merge 4 commits intoRust-for-Linux:mainfrom
mqqz:add_tuple_structs
Open

internal: add tuple struct support in pin_data and pin_init!#113
mqqz wants to merge 4 commits intoRust-for-Linux:mainfrom
mqqz:add_tuple_structs

Conversation

@mqqz
Copy link

@mqqz mqqz commented Feb 28, 2026

Extend pin_data and pin_init! to support tuple struct syntax.

pin_data (internal/src/pin_data.rs):

  • add tuple-field handling via a refactored FieldInfo struct
  • generate projections and pin-data accessors for unnamed members

pin_init! (internal/src/init.rs):

  • parse initialiser keys as syn::Member (named or tuple index)
  • extend parser to support both:
    • tuple-like syntax e.g. Foo(a, <- b, c)
    • and brace syntax e.g. Foo{0 : a, 1 <- b, 2: c}
    • Couldn't decide on appropriate syntax, I'm not sure if keeping both is a good idea

Testing:

  • tests/tuple_struct.rs
  • tests/ui/compile-fail/tuple_{duplicate,invalid,missing}_field.rs
  • tests/ui/compile-fail/tuple_shorthand.rs
  • tests/ui/expand/pin_{data,init}

Note that currently for tuple struct internal fields identifiers like _0 (for the first index) which clippy doesn't like. I'm not sure whether it's better to change naming or add #[allow(clippy::just_underscores_and_digits)] (I don't want to go through the effort of spamming clippy and changing all expanded tests just yet).

Closes: #85

@mqqz mqqz marked this pull request as draft February 28, 2026 18:14
@mqqz mqqz force-pushed the add_tuple_structs branch 5 times, most recently from cd3f0a3 to 78043e4 Compare March 2, 2026 21:33
@mqqz mqqz marked this pull request as ready for review March 2, 2026 21:55
@mqqz mqqz force-pushed the add_tuple_structs branch from f58c415 to 757cb2e Compare March 2, 2026 22:11
Copy link
Member

@BennoLossin BennoLossin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks for the PR!

I have several suggestions and some bigger things, but overall very happy with your changes & the style of code you used.

I really like the idea of adding FieldInfo before doing the changes to support tuple structs. I think we can take it a bit further and clean up a lot of the pin_data.rs code by moving code generation & handling pinned/unpinned fields in that type instead of the generation functions. Do you mind doing that work in the first commit as well?

Regarding syntax in the tuple form, I think it's fine to only support { 0 <- init } at the moment. I have thought about removing the <- syntax altogether (#66) & always expecting an initializer, but there are some drawbacks. So when one writes init!(Struct(a, b, c)), we just treat it as init!(Struct { 0: a, 1: b, 2: c }) and if they want to use an initializer, they need the braced version.

You can just add #[allow(clippy::just_underscores_and_digits)] to the generated code, that lint isn't useful for our code, since it's macro-generated.

We also should think about if the pin-projected version of a tuple struct should also be a tuple struct. That makes the code quite a lot more complex.

Lastly, I think we should have some more tests, some things that are missing: generics and !Unpin types with #[pin].

.filter_map(|(pinned, field)| (!pinned).then_some(field))
.map(|Field { ident, .. }| format!(" - `{}`", ident.as_ref().unwrap()));
.filter(|f| !f.pinned)
.map(|f| format!(" - {}", f.display_name));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's keep the `

Suggested change
.map(|f| format!(" - {}", f.display_name));
.map(|f| format!(" - `{}`", f.display_name));

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the backticks into display_name instead if that's what you meant.

For unnamed fields:

                format!("index `{i}`"),

Named are still unchanged

mqqz added 2 commits March 10, 2026 01:52
Introduce `FieldInfo` struct to encapsulate field and other relevant
data (e.g. pinned and member name) to abstract over named/unnamed
fields and extract relevant field data code into methods.

Also, generate projections and pin-data accessors for unnamed
members.

Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Refactor to parse initialiser keys as `Member` (named or tuple index).

Additionally, extend init parser to support both tuple-like init
constructor e.g. `Foo(a, <- b, c)` and brace syntax e.g.
`Foo{0 : a, 1 <- b, 2: c}`.

Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
@mqqz mqqz force-pushed the add_tuple_structs branch from 757cb2e to cc01981 Compare March 10, 2026 04:23
@mqqz mqqz requested a review from BennoLossin March 10, 2026 04:54
@mqqz mqqz force-pushed the add_tuple_structs branch from cc01981 to 940ccb6 Compare March 10, 2026 05:20
@mqqz
Copy link
Author

mqqz commented Mar 10, 2026

Thanks for the review! I appreciate you taking the time to look at my work. I have looked at the comments and pushed changes that should hopefully address most of them.


I think we can take it a bit further and clean up a lot of the pin_data.rs code by moving code generation & handling pinned/unpinned fields in that type instead of the generation functions. Do you mind doing that work in the first commit as well?

I heavily refactored pin_data.rs and extracted code much of the relevant code into FieldInfo methods.

You can just add #[allow(clippy::just_underscores_and_digits)] to the generated code, that lint isn't useful for our code, since it's macro-generated.

Done. I made sure the generated code doesn't raise any lint warnings.

We also should think about if the pin-projected version of a tuple struct should also be a tuple struct. That makes the code quite a lot more complex.

I am unsure of how much value that would add apart from aesthetics/ergonomics. I would not bother it just yet as the churn might not justify it unless an apparent user need surfaces later. I would focus on having a safe + sound implementation and adding separate codegen paths for named vs tuple projected types makes it harder.

Lastly, I think we should have some more tests, some things that are missing: generics and !Unpin types with #[pin].

I added a new commit that expands the testing coverage with more comprehensive and meaningful test cases (incl. (const) generics, lifetimes and !Unpin types as requested).


Also, during testing I found that

#[pin_data]
struct Tuple<T>(T, #[pin] #[pin] i32);

compiles fine and treats it as one #[pin], (I personally think it should panic) but this isn't a pressing issue. I can address this or leave it as is, whichever option makes more sense for you.

best,
~mo

mqqz added 2 commits March 10, 2026 09:22
Add initial tests to validate the basic functionality of tuple struct
support. Mainly, focusing on init syntax and pin data.

Tests include:
  - `tests/tuple_struct.rs`
  - `tests/ui/compile-fail/tuple_{duplicate,invalid,missing}_field.rs`
  - `tests/ui/compile-fail/no_tuple_shorthand.rs`
  - `tests/ui/expand/tuple_struct.rs`

Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Increase test coverage for new tuple struct feature with more
comprehensive cases focusing on generics and !Unpin types.

Extend `tests/tuple_struct.rs` cases
  - add runtime checks for generic payloads (type, lifetime, const
    generics)
  - cover multi-pinned tuple fields and `PinnedDrop` delegation
  - verify partial-init failure cleanup/rollback semantics

Expand tuple struct UI test coverage
  - `tests/ui/compile-fail/init/` (wrong generics, invalid index,
     tuple arrow/syntax error cases)
  - `tests/ui/compile-fail/pin_data/` (missing #[pin])

Update tuple expand expectations
  - `tests/ui/expand/tuple_struct.rs`

Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
@mqqz mqqz force-pushed the add_tuple_structs branch from 940ccb6 to 528ad75 Compare March 10, 2026 06:23
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.

Support for initializing tuple-structs

2 participants