summaryrefslogtreecommitdiff
path: root/rust/pin-init
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>
12 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>
12 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>
12 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: add diagnostic attribute for `PinInit` and `Init`Gary Guo
Give a slightly more useful error message when these traits are not implemented. Before this change: error[E0277]: the trait bound `impl pin_init::PinInit<Bar>: Init<Bar, _>` is not satisfied --> 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 After this 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 Ideally, we would generate differnet message when `PinInit` is implemented but not `Init`; that is not feasible with today's `diagnostics::on_unimplemented` attribute. However, the added note is worth it because in `init!()` is more rarely used compared to `pin_init!()`; in most cases `Init` being unimplemented is the result of missing `#[pin]`. Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-5-e4d7193569e5@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-09-25rust: pin-init: internal: add custom diagnostic when `#[pin_data]` is not ↵Gary Guo
implemented Produce a more helpful error message when `#[pin_data]` is omitted. The error message changes from 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 { | ^^^^^^^^^^ to error[E0277]: `Foo` cannot be used with `pin_init!` macro --> 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 { | ^^^^^^^^^^ = note: did you forget to add `#[pin_data]` attribute to the struct? Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-4-e4d7193569e5@garyguo.net 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: remove associated type of `HasInitData`Gary Guo
There is only a single implementation, the associated type is not necessary. Remove it, and rename `AllData` to `InitData` to be a more meaningful name. The single implementation also means that "unsafe" is redundant, so remove it as well. Link: https://patch.msgid.link/20260923-dev-pin-data-diag-v1-2-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-09-01rust: pin-init: use irrefutable pattern for `stack_pin_init`Gary Guo
In Rust 1.100.0, `Infallible` will become an alias of `!`. The let binding in `stack_pin_init` will thus become unreachable and produce an "unreachable expression" warning for the subsequent match, and thus will fail a `-Dwarnings` build. For this macro, all we need to know is that the error type is uninhabited, so replace this with an irrefutable pattern instead. [ The error looks like (dummy reproducer): error: unreachable expression --> rust/kernel/sync.rs:177:5 | 177 | pin_init::stack_pin_init!(let num = 42u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | unreachable expression | any code following this expression is unreachable | = note: `-D unreachable-code` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(unreachable_code)]` = note: this error originates in the macro `pin_init::stack_pin_init` (in Nightly builds, run with -Z macro-backtrace for more info) - Miguel ] Reported-by: Mohamad Alsadhan <mo@sdhn.cc> Closes: https://github.com/Rust-for-Linux/pin-init/pull/171 Signed-off-by: Gary Guo <gary@garyguo.net> Cc: stable@vger.kernel.org # Needed in 7.1.y and later (for 6.12.y and 6.18.y a custom one is needed). Link: https://patch.msgid.link/20260828155033.2101924-1-gary@kernel.org [ Reworded for typos. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
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-08-05rust: pin-init: remove `__pinned_init` method for `cfg(kernel)`Gary Guo
Remove `__pinned_init` for kernel configuration, with all users gone. Still perserve it temporarily as deprecated so other users have time to move off it. Link: https://patch.msgid.link/20260729-merge-init-v2-5-26adf47109e7@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-08-05rust: pin-init: add `raw_init` and `raw_try_init` and recommend over `__init`Gary Guo
The `__init` method is not designed to be a public API (existence of "__" is a hint for this); but currently there is no other API that allows raw initialization on pointers. Add `raw_init` and `raw_try_init` and recommend people to use this instead if raw pointer initialization is needed. Link: https://patch.msgid.link/20260729-merge-init-v2-3-26adf47109e7@garyguo.net [ Renamed from `ptr_[try_]init` to `raw_[try_]init`. - Gary ] Reviewed-by: Benno Lossin <lossin@kernel.org> Signed-off-by: Gary Guo <gary@garyguo.net>
2026-08-03rust: pin-init: merge `__pinned_init` and `__init`Gary Guo
These functions have the same requirements and are also required to execute the same code. Prevent duplication by merging them to the single function and document the additional relaxation of `Init::__init` on both the merged function and the safety requirement of `Init`. The existing `__pinned_init` function is deprecated and kept for compatibility for existing users. For `cfg(kernel)`, it is soft-deprecated for now and will be removed when all users are migrated. Link: https://patch.msgid.link/20260729-merge-init-v2-2-26adf47109e7@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-08-03rust: pin-init: examples: use `Wrapper::pin_init` instead of manual ↵Gary Guo
reimplementation `UnsafeCell` gains the method via the extension trait `Wrapper`. Link: https://patch.msgid.link/20260729-merge-init-v2-1-26adf47109e7@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-27rust: pin-init: mark `pin_init::zeroed` and `Zeroable::zeroed` as `#[inline]`Nicolás Antinori
The `pin_init::zeroed` function is a trivial wrapper around `unsafe { core::mem::zeroed() }`, whereas `Zeroable::zeroed` is a trivial wrapper around `pin_init::zeroed`. Mark them both as `#[inline]` to avoid generating unnecessary symbols for them. Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com> Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-27rust: pin-init: docs: link `Zeroable::zeroed` and `pin_init::zeroed` in ↵Nicolás Antinori
documentation Modify the comments in the `pin_init::zeroed` and `Zeroable::zeroed` functions to cross-reference each other and make developers aware of both options. This also adapts the example code in `Zeroable::zeroed` doc comments to use that function. Suggested-by: Miguel Ojeda <ojeda@kernel.org> Link: https://lore.kernel.org/rust-for-linux/CANiq72kdCAyRUmXFcqQfkHpk1miG8Gagsn0_5U8p4WpKxv9d_g@mail.gmail.com/ Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com> [ Fix link. - Gary ] 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: make `[pin_]chain` unwind safeMirko Adzic
Add a drop guard before the call to the chained closure so that the value initialized by the first stage is dropped if the closure errors or panics; `mem::forget` the guard on success. The previous code only ran cleanup on the explicit error path, leaking the first-stage value if the chained closure panicked. Reported-by: Gary Guo <gary@garyguo.net> Closes: https://github.com/Rust-for-Linux/pin-init/issues/136 Suggested-by: Gary Guo <gary@garyguo.net> Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-7-8fa16cde87ae@garyguo.net [ Fix Clippy missing safety comment false positive when `slot` and `guard` creation are merged in a single line. - Gary ] Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-13rust: pin-init: make `[pin_]init_array_from_fn` unwind safeMirko Adzic
The previous code only ran cleanup on the explicit error path. If the per- element initializer panicked partway through, the elements already written into the array would be leaked: their `Drop` impls would never run. This violates the pinning requirement. Fix the unwind safety issue by adding a guard type that drops element on both error and panic path. To avoid having to duplicate code between `pin_init_array_from_fn` and the non-pin variant, extract the code to a shared `ArrayInit` type; this type is internal and not visible via API. Reported-by: Gary Guo <gary@garyguo.net> Closes: https://github.com/Rust-for-Linux/pin-init/issues/136 Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-6-8fa16cde87ae@garyguo.net [ Split guard type and the initializer type, move the guard type to be within __pinned_init. - Gary ] Co-developed-by: Gary Guo <gary@garyguo.net> 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: remove redundant clippy expects in doc testsGary Guo
These lints are automatically suppressed inside doc tests. Previously this is needed because kernel builds doc tests with the default set of clippy flags; but now `clippy::disallowed_names` is globally allowed inside doc tests. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-3-8fa16cde87ae@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-07-13rust: pin-init: examples: fix incorrect dropGary Guo
Remove the drop and associated clippy allow. The warning reported by Clippy here is genuine; the binding created is `Pin<&mut T>` so dropping it does nothing. `stack_pin_init` created bindings are only dropped at the end of scope. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260710-pin-init-sync-v1-2-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: remove `E` from `InitClosure`Gary Guo
Move `E` from type to trait impl block. This greatly shortens the monomorphized type names. The `__pinned_init` function name is only slightly shortened as it still encodes the `E` as part of `PinInit<T, E>` in the symbol. `T` cannot be moved to trait impl block otherwise it will start to conflict with the `impl Init<T> for T` as Rust cannot deduce that there're no types that fulfill `T: FnOnce(*mut T)`. Link: https://patch.msgid.link/20260527-pin-init-sync-v1-6-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: move `InitClosure` out from `__internal`Gary Guo
The `__internal` module is for exposing internal items publicly to procedural macros (pin-init-internal). Types that are crate-local only can just have proper visibility and does not need to be in `__internal`. The type name of `InitClosure` can often shows up in symbol names, this reduces the length slightly. Link: https://patch.msgid.link/20260527-pin-init-sync-v1-5-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: docs: fix typos in MaybeZeroable documentationXiaobo Liu
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com> Link: https://patch.msgid.link/20260527-pin-init-sync-v1-4-e20335ed2501@garyguo.net 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>