summaryrefslogtreecommitdiff
path: root/rust/pin-init/internal/src
AgeCommit message (Collapse)Author
5 daysrust: pin-init: internal: pin_data: parse into `StructInfo` before generatingGary Guo
Organize parsing and generation into two separate phases, with a single `StructInfo` in the middle. This allows analysis and processing to happen with a single struct and avoid having to pass different information into the token stream generation functions. A drawback of this approach is that as we consume the `Fields`, we cannot expand the original struct using `quote!(#struct_)` anymore, and the field needs to be re-constructed in `generate_struct_def` function. However, this is only a temporary drawback, as the upcoming pin-init self-referential feature will require modification of the generated struct anyway. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-8-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: pin_data: rename `'__pin` lifetime to `'__this`Gary Guo
"pin" is a very overloaded word in pin-init. For the generated projection structs, the lifetime refer to that of the whole struct, so rename the lifetime used in expansion from `'__pin` to `'__this` instead. The `__pin_phantom_data` field is renamed to `__this` for the same reason and for clarity purpose, capture a `PhantomData` of the mutable reference to the struct. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-7-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: pin_data: extract `#[cfg]` processing to its own ↵Gary Guo
function The `pin_data` function is getting big. Split the `#[cfg]` handling which does not interact with other part of expansion to its own `expand_with_cfg` function. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-6-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: pin_data: move projection struct into `const _: ↵Gary Guo
()` block Most users would not need to mention the generated projection struct. With the upcoming self-referential support, there needs to be additional projection structs. Instead of give them publicly visible names, simply make the name not publicly accessible. A heavy user of pin projection outside kernel is for async programming. I've checked tokio codebase there is a single use case and that's for enums. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-5-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: add utility for extract a single attributeGary Guo
More attributes are to be added which has the requirement that they should only be specified once. Add a utility code to extract attributes for a specific path and report error when appeared multiple times. Convert `#[pin]` parsing to use the added utility. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-4-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: add utility to handle generics mergingGary Guo
There're many cases where we want to merge multiple generics together. Currently this is done by cloning generics and modifying it, making the code less readable. Add a utility code that allow printing multiple generics together, ensuring correct ordering between lifetime and other parameters. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-3-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: init: set span location of guardsGary Guo
Set the span location of the guards to point to the identifier. The generated diagnostic is still not ideal, as ideally it points the place where the identifier is used rather than the identifier name in initializer, but is still an improvement to status quo. Before the change: error[E0505]: cannot move out of value because it is borrowed --> tests/ui/compile-fail/init/accessor_lifetime.rs:8:13 | 8 | let _ = init!(Foo { | _____________^ 9 | | x: 0, 10 | | _: { 11 | | let _: &'static usize = x; | | -------------- type annotation requires that borrow lasts for `'static` 12 | | }, 13 | | }); | | ^ | | | | |______move out of value occurs here | borrow of value occurs here After the change: error[E0505]: cannot move out of value because it is borrowed --> tests/ui/compile-fail/init/accessor_lifetime.rs:9:9 | 9 | x: 0, | ^ | | | move out of value occurs here | borrow of value occurs here 10 | _: { 11 | let _: &'static usize = x; | -------------- type annotation requires that borrow lasts for `'static` Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-2-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
5 daysrust: pin-init: internal: init: forget guards in reverse orderGary Guo
Currently, the forget order is the same as initialization order, this is the wrong way around compared to their drop order when going out-of-scope. The wrong order will cause borrow checker errors if there are lifetime dependencies between the guards. This does not matter for now because there cannot be any lifetime dependency; it would matter for self-referential borrows. Reverse the order to be consistent with their out-of-scope drop order. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261006-dev-selfref-dep-v1-1-da716f740d6d@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
11 daysrust: pin-init: internal: init: use span of `<-` or `:` for the init/write call.Gary Guo
Currently we use the full span of the field initializer as the span of the generated init call. This produces overlapping spans for type mismatch errors, which is hard to read. Use the span of `<-` or `:` for the method name, which wll cause type mismatch errors or trait bound not implemented error to be appear from the `<-` or `:` token, which declutter the output a bit and make it easier to read. Before the change: error[E0277]: `impl pin_init::PinInit<Bar>` cannot be used to movably initialize `Bar` with error `_` --> tests/ui/compile-fail/init/invalid_init.rs:19:16 | 19 | bar <- Bar::new(), | -------^^^^^^^^^^ | | | | | the trait `Init<Bar, _>` is not implemented for `impl pin_init::PinInit<Bar>` | required by a bound introduced by this call | = note: if your type implements `PinInit` but not `Init`, you might be forgetting a `#[pin]` annotation on fields After the change: error[E0277]: `impl pin_init::PinInit<Bar>` cannot be used to movably initialize `Bar` with error `_` --> tests/ui/compile-fail/init/invalid_init.rs:19:16 | 19 | bar <- Bar::new(), | -- ^^^^^^^^^^ the trait `Init<Bar, _>` is not implemented for `impl pin_init::PinInit<Bar>` | | | required by a bound introduced by this call | = note: if your type implements `PinInit` but not `Init`, you might be forgetting a `#[pin]` annotation on fields Suggested-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260928-dev-pin-init-sync-v1-3-e591c8e9cf0e@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
11 daysrust: pin-init: internal: init: improve diagnostics from field checksGary Guo
Use span of the field name for generated alignment and field duplication checks. This avoids pointing diagnostics to the full macro invocation, but just the part of it going wrong. Before the change: error[E0062]: field `0` specified more than once --> tests/ui/compile-fail/init/tuple_duplicate_field.rs:7:37 | 7 | let _ = pin_init!(Tuple { 0: 1, 0: 2, 1: 3 }); | ------------------------^------------ | | | | | used more than once | first use of `0` After the change: error[E0062]: field `0` specified more than once --> tests/ui/compile-fail/init/tuple_duplicate_field.rs:7:37 | 7 | let _ = pin_init!(Tuple { 0: 1, 0: 2, 1: 3 }); | - ^ used more than once | | | first use of `0` Link: https://patch.msgid.link/20260928-dev-pin-init-sync-v1-2-e591c8e9cf0e@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
11 daysrust: pin-init: internal: init: allow reborrow of `Pin<&mut T>` bindingsGary Guo
Use `let mut` for created bindings of initialized field, so `Pin<&mut T>` bindings may be reborrowed in subsequent initializers or code blocks. Without `let mut`, attempt to reborrow can produce error (and also a confusing fix): error[E0596]: cannot borrow `gpu` as mutable, as it is not declared as mutable --> drivers/gpu/nova-core/driver.rs:129:17 | 129 | gpu.as_mut().run_selftests(pdev); | ^^^ cannot borrow as mutable | help: consider changing this to be mutable | 119 | mut gpu <- Gpu::new( | +++ error: aborting due to 1 previous error Reported-by: Danilo Krummrich <dakr@kernel.org> Closes: https://lore.kernel.org/nova-gpu/DLQXWXRP3P1J.28SLFOJJQ2EDK@kernel.org/ Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Tested-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Danilo Krummrich <dakr@kernel.org> Link: https://patch.msgid.link/20260928-dev-pin-init-sync-v1-1-e591c8e9cf0e@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
14 daysrust: pin-init: internal: improve diagnostics robustness against panickingGary Guo
Currently, if proc macro panicked, the diagnostics clean up is not executed, and further invocation will cause the "DiagCtxt cannot be nested" error. While we should aim to have no panics inside proc macros, producing a sensible diagnostics message even when macro panicked is very useful for developing. Thus, catch proc macro panics and convert them to errors, and emit them together with all diagnostics accumulated so far. Ideally we would like panic location w/ line numbers being available as well; however this is not currently implementable without overriding the global panic hook. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260923140618.1978181-3-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
14 daysrust: pin-init: internal: make `DiagCtxt` available inside parserGary Guo
Currently, there is a split between `syn::Error` and pin-init's custom `DiagCtxt`. Parsing has no access to `DiagCtxt` and therefore cannot report diagnostics without failing the parse. Bridge the gap by making the `DiagCtxt` available inside parsers using `thread_local!`. `parse_macro_input!` returns error as token stream directly, so it is no longer suitable when the parsing is moved inside `DiagCtxt` closure. Add a `From<syn::Error> for ErrorGuaranteed` implementation so `?` can be used to add a `syn::Error` into the current diagnostic context and obtain a `ErrorGuaranteed`. Clean up the handler of using `<-` inside tuple expression as a demonstration of the usefulness of having `DiagCtxt` access inside `Parse`. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260923140618.1978181-2-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
14 daysrust: pin-init: internal: handle item and expr diagnostics differentlyGary Guo
Currently `DiagCtxt` is used to allow error recovery in the pin-init macros, by generating both a `compile_error!()` macro item and continue expansion, and then merge token streams together. This works very well for items, however for expressions, this will produce invalid expression and result in a confusing error message. error: macro expansion ignores `::` and any tokens following --> tests/ui/compile-fail/zeroable/invalid_spread.rs:15:9 | 13 | let _ = init!(Foo { | _____________- 14 | | a: 0, 15 | | ..MyZeroable::init_zeroed() | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 16 | | }); | |______- caused by the macro expansion here | = note: the usage of `init!` is likely invalid in expression context Fix this by wrap the concatenated diagnostics in a block, with the generated expression in its tail position. This results in the desired error message. error: expected nothing or `..Zeroable::init_zeroed()`. --> tests/ui/compile-fail/zeroable/invalid_spread.rs:15:9 | 15 | ..MyZeroable::init_zeroed() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260923140618.1978181-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-25rust: pin-init: internal: use `HasInitData` to provide inference help onlyGary Guo
Currently, type inference of the initialized type is done by use the function calling syntax `PATH::__pin_data` or `PATH::__init_data` to obtain the required init data type, without needing the user to explicitly mention all generics. Switch to always use `HasInitData::__init_data` to provide that inference, which will not produce method-not-found errors as it is always available. Change `__pin_data` to take `InitData<Self>` as the receiver, so for types that require `HasPinData`, `HasPinData::__pin_data(data)` can be used to obtain the needed type without having to mention the user-provided path again. The expanded code also uses the span of the type, so diagnostics will hint to user that the type is causing the issue. With this change, the error message when `HasPinData` is not implemented changes from error[E0599]: no associated function or constant named `__pin_data` found for struct `Foo` in the current scope --> tests/ui/compile-fail/init/missing_pin_data.rs:9:9 | 3 | struct Foo { | ---------- associated function or constant `__pin_data` not found for this struct ... 9 | pin_init!(Self { a: 42 }) | ^^^^^^^^^^^^^^^^^^^^^^^^^ associated function or constant not found in `Foo` | = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `__pin_data`, perhaps you need to implement it: candidate #1: `pin_init::__internal::HasPinData` to error[E0277]: the trait bound `Foo: pin_init::__internal::HasPinData` is not satisfied --> tests/ui/compile-fail/init/missing_pin_data.rs:9:19 | 9 | pin_init!(Self { a: 42 }) | ^^^^ unsatisfied trait bound | help: the trait `pin_init::__internal::HasPinData` is not implemented for `Foo` --> tests/ui/compile-fail/init/missing_pin_data.rs:3:1 | 3 | struct Foo { | ^^^^^^^^^^ Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-3-e4d7193569e5@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-25rust: pin-init: internal: make `__init_data` and `__pin_data` safeGary Guo
Remove the unsafe markers of `__init_data` and `__pin_data`. These methods are for inference help and does not need to be unsafe. The `HasInitData` cannot be implemented outside pin-init, so the `unsafe trait` marker is not necessary. Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-1-e4d7193569e5@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-25rust: pin-init: internal: pin_data: use HRTB to work around `trivial_bounds` ↵Gary Guo
for `Unpin` `#[pin_data]` generates a `Unpin` implementation for the user, which requires reasoning using field types. This is rejected by rustc as "trivial bounds", which can only be specified using the `#![feature(trivial_bounds)]`. Currently we use an extra lifetime in `__Unpin` to work around this; use HRTB to introduce a dummy lifetime can achieve the same, which the `Zeroable` implementation already uses. Unify the `Unpin` impl to also use the same HRTB trick that `Zeroable` uses. This produces slightly better error message and slightly shorter expansion. Link: https://patch.msgid.link/20260922211320.1390159-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-18rust: pin-init: internal: use span of `Index` for generated identifiersGary Guo
Use the span of `Index` for generated identifiers, so diagnostics can point to the span of the index. Link: https://patch.msgid.link/20260916184131.435059-1-gary@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-18rust: pin-init: internal: init: provide span for slot projectionGary Guo
When initializing a field, pin-init first projects the full slot to a slot of the field, then initialize it by invoking a method. Currently the span location is not explicitly set, so the error message points to the full macro invocation. Improve it by provide a span, so Rust will point to the specific fields causing the error when type check fails. Old error message: error[E0308]: mismatched types --> tests/ui/compile-fail/init/field_value_wrong_type.rs:8:28 | 8 | let _ = init!(Foo { a: () }); | ---------------^^--- | | | | | expected `usize`, found `()` | arguments to this method are incorrect New error message: error[E0308]: mismatched types --> tests/ui/compile-fail/init/field_value_wrong_type.rs:8:28 | 8 | let _ = init!(Foo { a: () }); | ---^^ | | | | | expected `usize`, found `()` | arguments to this method are incorrect Link: https://patch.msgid.link/20260916-dev-hygiene-v1-3-dfb6ae2588ba@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-18rust: pin-init: internal: init: use `slot` identifier directly with mixed siteGary Guo
Use `quote_spanned!(Span::mixed_site() => ...)` directly instead of creating `slot` identifier and interpolate it later. Do the same for `__data`, too. This is needed so that we can customize the location of the span without having the `slot` identifier getting in the way. For example: quote_spanned!(Span::mixed_site().located_at(loc) => ...) with `slot` mentioned directly will have the diagnostic pointing to the desired location, while `#slot` won't. Link: https://patch.msgid.link/20260916-dev-hygiene-v1-2-dfb6ae2588ba@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-18rust: pin-init: internal: init: emit `slot` using mixed site hygieneGary Guo
Syn/quote's default is the call site hygiene. If user provides a field named `slot`, it will conflict with pin-init generated `slot` identifier. Change it to use mixed site hygiene instead. Fixes: 4883830e9784 ("rust: pin-init: rewrite the initializer macros using `syn`") Link: https://patch.msgid.link/20260916-dev-hygiene-v1-1-dfb6ae2588ba@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-14rust: pin-init: internal: init: support tuple struct constructor syntaxMohamad Alsadhan
A tuple struct whose fields are all set to a value reads better written like a call to its constructor than with the indices spelled out: pin_init!(Foo(value, value)) Parse the two forms into separate types and rewrite the constructor arguments into the indexed fields they are shorthand for, so that only the parser has to know about the second form. The arguments have no names, so they cannot use `<-`. Parse it anyway and reject it afterwards, which reports the position of every offending `<-` rather than stopping at the first one. `cfg` needs different treatment for tuple constructor syntax. As non-derive proc macros are invoked before cfg is resolved, the macro cannot know whether a field survives, and dropping a tuple field renumbers every field after it. That cannot be expressed by attaching a `cfg` attribute to the initializer of a single field. Thus, resolve tuple field cfgs up front instead, by generating two cfg-gated invocations of the macro with one field resolved in each. This is the approach of commit 5bbf2b2deb94 ("rust: pin-init: internal: rework how `#[pin_data]` handles cfg"), and it is linear time because only one of the two branches is ever expanded. Struct expression syntax do not renumber, so using tuple structs with struct syntax can keep using the existing attribute-based handling. Suggested-by: Gary Guo <gary@garyguo.net> Link: https://github.com/Rust-for-Linux/pin-init/pull/165 Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> [ Pre-expand cfgs for tuple init syntax. Use generics instead of separate types for normalization - Gary ] Co-developed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260904-tuple-struct-v1-4-72c50bd037fd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-14rust: pin-init: internal: init: support tuple structs in `[pin_]init!`Mohamad Alsadhan
Extend the initializer syntax so that a field can be named by an index, addressing tuple struct fields the same way a struct expression does: pin_init!(Foo { 0: value, 1 <- initializer }) Tuple fields are not exposed by a `let` binding to the fields after them, since they have no name to bind; `_0` would shadow a user variable. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> [ Fixed incorrect index calculation and cleaned up the code - Gary ] Link: https://patch.msgid.link/20260904-tuple-struct-v1-3-72c50bd037fd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-14rust: pin-init: internal: pin_data: support tuple struct projectionsMohamad Alsadhan
`#[pin_data]` rejects tuple structs because it assumes every field has a name, which it uses for the projection field, the `__Unpin` field and the pin-data accessor. Identify fields by `syn::Member` instead, so that tuple fields are referred to by their index in generated field accesses. The names that generated items still need are derived from the index as `_0`, `_1`, etc. The projection of a tuple struct is a tuple struct itself, so projected fields are accessed with the same `.0`, `.1` syntax as on the input type rather than through synthesised names. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> [ Moved utility code to util.rs as extension trait - Gary ] Link: https://patch.msgid.link/20260904-tuple-struct-v1-2-72c50bd037fd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-14rust: pin-init: internal: extract utility code to new moduleGary Guo
Create a new `util.rs` to host utility code that are generic and can be shared by multiple macros. Link: https://patch.msgid.link/20260904-tuple-struct-v1-1-72c50bd037fd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-08-05rust: pin-init: add `#[inline]` to small functionsGary Guo
Currently `pin-init` crate is missing many inline annotations. They are all generic so still get inlined in normal builds, but are not inlined in `-C opt-level=s` build. Mark these functions as `#[inline]` so they are considered for inlining regardless. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-27rust: pin-init: internal: rework how `#[pin_data]` handles cfgGary Guo
Attribute macros are invoked without cfg being resolved. This adds quite a bit complexity to the macro because all of the macro needs to be careful to attach necessary cfgs. This becomes especially tricky for tuple structs. Thus, it is convenient if cfgs are all resolved like derive macros. The most optimal way to handle this is via `TokenStream::expand_expr`, but that is still unstable. We can also create an internal derive macro and transform the attribute macro invocation to be derive macro, but doing requires us to serialize all extracted information in a form of helper attributes; it would also make it more difficult if we want to make changes to the struct (which the self-reference feature would need). Implement an approach where we generate two cfg-gated macro invocations with cfg resolved within the invocation. This would mean when the loop falls through, all field cfgs are resolved, so remove all handling of cfg_attrs for the rest of the macro. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-13rust: pin-init: internal: generate brace in macro for init code blocksGary Guo
`init!` support interleaving code execution and initialization, and code execution is done using `_: { ... }` syntax. If the code inside block is a single statement, Rust may add a lint about unused braces, but the suggestion will be incorrect as block is required by pin-init. Currently we use `unused_brace` to suppress this, but this affect everything nested inside as well. Use an alternative approach by generating the block from the macro, then rustc will know to not emit the lint. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-5-8fa16cde87ae@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-13rust: pin-init: internal: remove `allow` and `expect`s that don't fireGary Guo
Most warnings are suppressed from external macro expansions by default. Thus remove `allow` and `expect`s for them. Note that `unfulfilled_lint_expectations` is one of them too. This means that all of our `expect`s inside macros do nothing, and actually mislead people to the lints would be actually emitted without them. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-4-8fa16cde87ae@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-13rust: pin-init: internal: error on duplicate `#[pin]` attributeLuiz Georg
Duplicated `#[pin]` has no effect, thus error if misused. Reported-by: Mohamad Alsadhan <mo@sdhn.cc> Closes: https://github.com/Rust-for-Linux/pin-init/issues/119 Signed-off-by: Luiz Georg <luizgngeorg@gmail.com> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-1-8fa16cde87ae@garyguo.net [ Reworded commit message, and change the logic so code generation still continue after reporting error - Gary ] Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin_init: internal: use `loop {}` to produce never valueGary Guo
In the `init!`/`pin_init!` macros, we rely on a trick that assigns never (`!`) values to all mentioned fields in never-executed code to let the compiler check that all fields have been initialized. Currently we use `::core::panic!()` to produce this value, but before Rust 1.91.0, it creates outlined `panic_cold_explicit` functions which do not get removed by the optimizer, thus leaving dead code behind in the binary. This has been fixed by [1], which lands in Rust 1.91.0+, higher than the kernel minimum version 1.85.0. This causes ~200 dead `panic_cold_explicit` instances being included in the binary, with ~90 of them from nova-core's usage of pin-init. Work around the issue by using `loop {}` which creates the never value without macro expansion or function call at all. All instances of `panic_cold_explicit` outside libcore are removed by this change in my kernel build. Link: https://github.com/rust-lang/rust/pull/145304 [1] Link: https://patch.msgid.link/20260508152950.833635-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`Mirko Adzic
Allows `non_snake_case` lint on local variables generated in `[pin_]init!`. Conceptually the identifiers in `[pin_]init!` just references the field names, and are not defining them, so the warning should not be generated, similar to how constructing a struct with non-snake-case field names do no generate these warnings. Reported-by: Gary Guo <gary@garyguo.net> Closes: https://github.com/Rust-for-Linux/pin-init/issues/125 Closes: https://lore.kernel.org/rust-for-linux/DGTBJBIVFZ2K.2F1ZEFGY0G7NK@garyguo.net/ Fixes: 42415d163e5d ("rust: pin-init: add references to previously initialized fields") Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260527-pin-init-sync-v1-3-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`Mirko Adzic
Allows `non_snake_case` lint on struct fields generated by `#[pin_data]`. Since the same warning will be reported by the compiler on the struct definition, having extra warnings for the generated code is unnecessary and confusing. Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com> Link: https://patch.msgid.link/20260527-pin-init-sync-v1-2-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated codeMartin Kletzander
When using a macro with custom attributes in a `#[pin_data]` struct it can mess up the generated code. The generated code needs nothing more than the `#[cfg]` attribute, thus strip away all other attributes. [ Rebased and updated to only include `#[cfg]` instead of both `#[cfg]` and `#[doc]`; doc is not needed for the generated hidden items. - Gary ] Signed-off-by: Martin Kletzander <mkletzan@redhat.com> Co-developed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260527-pin-init-sync-v1-1-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-18rust: pin-init: internal: project using full slotGary Guo
Instead of projecting using pointer to a field project the full slot. This further shifts the code generation from the initializer site to the struct definition site, which means less code is generated overall. It also makes the safety comment easier to justify, as now the projection is done by the `#[pin_data]` macro which has full visibility of pinnedness of fields. The field alignment could also be checked on the `#[pin_data]` side; however, since `init!()` macro works for other type of structs, we cannot remove the alignment check from `init!`/`pin_init!` side anyway, so I opted to still keep the alignment check in init.rs. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-18rust: pin-init: internal: project slots instead of referencesGary Guo
By projecting slots, the `pin_init!` and `init!` code path can be more unified. This also reduces the amount of macro-generated code and shifts them to the shared infrastructure. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-18rust: pin-init: internal: make `make_closure` inherent methodsGary Guo
The `InitData` and `PinData` traits do not need to exist, the inference helpers could be inherent methods instead. There is no risk for calling the wrong methods even when user defines it, as inherent methods take priority over trait methods. With this change, it unlocks the possibility of attaching additional bounds to the method per type, which is not possible for trait methods. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-18rust: pin-init: internal: use marker on drop guard type for pinned fieldsGary Guo
Instead of projecting the created reference, simply create drop guards with different marker types and have the `let_binding()` method of guards of different marker produce different type instead. This allows more flexible lifetime as this is now controlled by the guard. This will be needed when implementing self-referential fields. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-18rust: pin-init: internal: init: handle code blocks earlyGary Guo
`InitializerKind::Code` is a special case where it does not initialize a field, and thus generate no guard and accessors. Handle it earlier and make the rest of the code more linear. Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-14rust: pin-init: internal: add `PhantomInvariant` and `PhantomInvariantLifetime`Gary Guo
Currently, the `pin_init` library has an `Invariant` type alias, and it is instantiated using `PhantomData`. Generated code from `pin_data` on the other hand cannot access the crate-local type alias, so it generates `PhantomData<fn(T) -> T>` directly. This is all very inconsistent, despite the exact same use case of ensuring invariance. Add `PhantomInvariant` and `PhantomInvariantLifetime` and switch all users that need to express the concept of invariance to use these. They're polyfills of unstable types in the same names in the Rust standard library. Link: https://patch.msgid.link/20260512-pin-init-sync-v1-3-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-14rust: pin-init: internal: pin_data: add struct to record field infoMohamad Alsadhan
Introduce `FieldInfo` struct to encapsulate field and other relevant data, instead of carrying a pair of `(pinned, field)` in all places. This allows us to add more information to the struct in the future. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Co-developed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260512-pin-init-sync-v1-2-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-14rust: pin-init: internal: pin_data: use closure for `handle_field`Gary Guo
`handle_field` is currently a function, which precludes it from referencing things in the scope of the parent function. Given that it's only called once, inline its contents to the closure that invokes it instead, so it can directly reference `struct_name` without having to pass in as argument. Link: https://patch.msgid.link/20260512-pin-init-sync-v1-1-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: remove `collect_tuple` polyfill after MSRV bumpGary Guo
Tuples implement `FromIterator` since Rust 1.79. Remove the `collect_tuple` polyfill now the MSRV is above 1.79. To avoid over-identing the closure, I move the `Field` destructure from the closure parameter to a let binding. This keeps the diff small. Link: https://patch.msgid.link/20260501134445.3809731-1-gary@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: turn `PhantomPinned` error into warningsGary Guo
The `PhantomPinned` detection is just a lint, and is emitted as an error because there is no `compile_warning!()` macro, and `proc-macro-diagnostics` is not stable. Use of `#[deprecated = ""]` attribute to approximate custom proc-macro warnings. A new line is added before message for visual clarity. An example warning with this trick looks like this: warning: use of deprecated function `_::warn`: The field `pin` of type `PhantomPinned` only has an effect if it has the `#[pin]` attribute --> test.rs:9:5 | 9 | pin: marker::PhantomPinned, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Suggested-by: Benno Lossin <lossin@kernel.org> Link: https://github.com/Rust-for-Linux/pin-init/issues/51 Link: https://patch.msgid.link/20260428-pin-init-sync-v1-10-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: cleanup workaround for old Rust compilerGary Guo
The workaround mentions it's for Rust versions before 1.81. The minimum is now 1.82, thus clean up. Link: https://patch.msgid.link/20260428-pin-init-sync-v1-9-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: adjust license identifier of `zeroable.rs`Benno Lossin
The pin-init crate has been licensed under `Apache-2.0 OR MIT` since the beginning. I introduced in commit 071cedc84e90 ("rust: add derive macro for `Zeroable`") `zeroable.rs` with incompatible GPL-2.0 SPDX identifier. The file has not been modified by other authors, so relicense it under the above license. Signed-off-by: Benno Lossin <lossin@kernel.org> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260428-pin-init-sync-v1-7-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: remove redundant `#[pin]` filteringGary Guo
The `generate_projections` and `generate_the_pin_data` function already receive filtered field lists, they do not need to filter out `#[pin]` again. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260428-pin-init-sync-v1-6-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: add missing where clause to projection typesMohamad Alsadhan
`#[pin_data]` failed to propagate the struct's `where` clause to the generated projection struct. As a result, bounds written in a `where` clause could be dropped during expansion, causing type errors when fields depended on those bounds. Fix this by adding the missing `where` clause to the generated projection struct. Reported-by: Andreas Hindborg <a.hindborg@kernel.org> Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/561532-pin-init/topic/generic.20bounds.20and.20.60.23.5Bpin_data.5D.60/with/578381591 Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Reviewed-by: Gary Guo <gary@garyguo.net> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260428-pin-init-sync-v1-5-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: bump minimum Rust version to 1.82Gary Guo
Following the kernel minimum version bump in commit f32fb9c58a5b ("rust: bump Rust minimum supported version to 1.85.0 (Debian Trixie)"), bump pin-init's minimum Rust version to 1.82. This removes the `lint_reasons` feature which is stabilized in 1.81 and the `raw_ref_ops` and `new_uninit` features which are stabilized in 1.82. Given we do not use any features that are stabilized in 1.82..=1.85 range, and pin-init crate is useful for other projects which may have their own MSRV requirements, the minimum version is not straightly bumped to 1.85. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260428-pin-init-sync-v1-2-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-04-30rust: pin-init: fix incorrect accessor reference lifetimeGary Guo
When a field has been initialized, `init!`/`pin_init!` create a reference or pinned reference to the field so it can be accessed later during the initialization of other fields. However, the reference it created is incorrectly `&'static` rather than just the scope of the initializer. This means that you can do init!(Foo { a: 1, _: { let b: &'static u32 = a; } }) which is unsound. This is caused by `&mut (*#slot).#ident`, which actually allows arbitrary lifetime, so this is effectively `'static`. Somewhat ironically, the safety justification of creating the accessor is.. "SAFETY: TODO". Fix it by adding `let_binding` method on `DropGuard` to shorten lifetime. This results in exactly what we want for these accessors. The safety and invariant comments of `DropGuard` have been reworked; instead of reasoning about what caller can do with the guard, express it in a way that the ownership is transferred to the guard and `forget` takes it back, so the unsafe operations within the `DropGuard` can be more easily justified. Fixes: 42415d163e5d ("rust: pin-init: add references to previously initialized fields") Cc: stable@vger.kernel.org Signed-off-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260427-pin-init-fix-v3-2-496a699674dd@garyguo.net [ Reworded for missing word. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>