internal: add tuple struct support in pin_data and pin_init!#113
internal: add tuple struct support in pin_data and pin_init!#113mqqz wants to merge 4 commits intoRust-for-Linux:mainfrom
pin_data and pin_init!#113Conversation
cd3f0a3 to
78043e4
Compare
BennoLossin
left a comment
There was a problem hiding this comment.
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)); |
There was a problem hiding this comment.
let's keep the `
| .map(|f| format!(" - {}", f.display_name)); | |
| .map(|f| format!(" - `{}`", f.display_name)); |
There was a problem hiding this comment.
I moved the backticks into display_name instead if that's what you meant.
For unnamed fields:
format!("index `{i}`"),
Named are still unchanged
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>
|
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 heavily refactored
Done. I made sure the generated code doesn't raise any lint warnings.
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.
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, |
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>
Extend
pin_dataandpin_init!to support tuple struct syntax.pin_data(internal/src/pin_data.rs):FieldInfostructpin_init!(internal/src/init.rs):syn::Member(named or tuple index)Foo(a, <- b, c)Foo{0 : a, 1 <- b, 2: c}Testing:
tests/tuple_struct.rstests/ui/compile-fail/tuple_{duplicate,invalid,missing}_field.rstests/ui/compile-fail/tuple_shorthand.rstests/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