summaryrefslogtreecommitdiff
path: root/rust/pin-init
AgeCommit message (Collapse)Author
2026-10-12rust: pin-init: internal: suppress `explicit_outlives_requirements`Gary Guo
`#[pin_data]` inserts outlive bounds between lifetimes to allow closure callbacks to rely on their relationship. In some cases, these relations are implied by fields, and Rust generates `explicit_outlives_requirements` allow-by-default lint, which is turned out by kernel as part of rust-2018-idioms lint group. As `#[pin_data]` is a proc macro and it cannot know if the bounds are already implied, suppress such lints for generated code. Link: https://patch.msgid.link/20261011133904.600785-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: support existential lifetimesGary Guo
There are many cases where structs that have interior mutability, but they do not need the invariance over captured lifetimes as the lifetime is captured upon construction, and new data of that particular lifetime does not flow back into the struct. For these use cases, the same mechanism as pin-init self-reference may be used. Add support for existential lifetimes, introduced by having where clauses such as exists<'a>: 'b The lifetime `'a` above is minted similar to field lifetimes. Because `'a` is an erased lifetime living longer than `'b`, the only variance requirement that we have is that `'b` cannot be contravariant; that defense is fulfilled by adding `PhantomData<&'b ()>` so the struct is either covariant or invariant over `'b`. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-20-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: support shared projectionGary Guo
For fields that self-references, it is desirable that projection can happen on shared references too, so lifetime between different fields can be correlated. Add support for that with `with_project_ref`. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-19-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: perform AST lifetime replacement if possibleGary Guo
Currently lifetimes are replaced via function type and `FnOutput` trait. This is very general approach as it uses generic associated type to replace lifetime, so it can even work when macros are involved. This does cause more generated code, and does not render in documentation nicely. Thus, just replace the lifetime in the AST if no macros are involved. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-18-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: complete invariant borrow supportGary Guo
Non-covariant types can already be accessed inside projections. As projections are only generated for `Pin<&mut T>`, they're not accessible otherwise. Add `with_{field_name}` methods so fields can be accessed using closures with just `&T`. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-17-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: make field lifetime invariance imply ↵Gary Guo
type invariance If invariant field captures a field lifetime, then we also need to make sure that field is also invariant. Imagine this struct: #[pin_data] struct SelfRef<'a> { #[uses('outer: invariant)] part: Mutex<&'outer str>, outer: &'a String, } fn new<'a>(str: &'a String) -> impl PinInit<SelfRef<'a>, Infallible> { pin_init!(SelfRef { outer: str, part: Mutex::new(*outer), }) } If we make this struct covariant over `'a`, then we can have the following case: let mut long = "hello world".to_owned(); let s = Box::pin_init(new(&long)).unwrap(); { let mut short = "hello world".to_owned(); // If `s` is covariant, this would be okay, because we shorten from // `SelfRef<'long>` to `SelfRef<'short>`. s.with_project_ref(|p| { *p.part.lock().unwrap() = &short; }); } Conceptually, a field's type must outlive the field's lifetime, so if we have a covariant `'a`, we can have a shortened `SelfRef<'short_a>` where `'outer` outlives `'short_a`. But the wellformedness requirement of the field will imply `'short_a: 'outer`, which enables the `&'short_a` to `'outer` coercion, effectively making the field lifetime `'f` behave covariantly, too, breaking the requirement that it is invariant. Therefore, compute an invariant closure and use an additional generics on `Borrowed` to allow capturing things invariantly. Note that we do capture all parameters explicitly rather than capture the field type invariantly, because if type aliases are involved, we might be syntactically determining that the field uses a type parameter but actually not, causing the invariance enforcement to be missed. Outlive bounds between field lifetimes can also cause the same issue (an invariant field lifetime cannot be a lower bound of a covariant field lifetime). Since we cannot deduce whether any implied bounds from type wellformness would create such outlive relationships, prevent such bounds from happening by using a split outlive chain. Note that this is not a soundness hole in itself in absence of `with_project_ref`, because with single field accessors only, the field lifetimes of the fields are not connected; in methods like `with_project` lifetimes are invariant so shortening cannot happen. However, such method is likely desirable, so include the variance rule before it has been heavily relied upon. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-16-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: parse explicit `#[uses]` annotationGary Guo
Add support for explicit self-referential annotations. `#[uses]` attribute is used to mark what other field lifetimes are captured by this field, and also the variance of the type in respect to the field lifetimes. For example, #[uses('a: covariant, 'b: invariant)] indicates that the field captures the field lifetime `'a` covariantly, and field lifetime `'b` invariantly. Many types are covariant, so this is the default variance if the variance is omitted (e.g. `#[uses('a)]`), consistent with the automatically inferred borrow. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-15-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: support mutable borrowsGary Guo
Allow fields to be mutably referenced by other fields in addition to shared references. In order for this to be sound, the fields that can be mutably borrowed are blocked from being accessed via field access syntax or projection to maintain the aliasing requirements. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-14-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: parse explicit `#[borrowed]` annotationGary Guo
`#[borrowed]` attribute explicitly marks a field as potentially being borrowed by other fields. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-13-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: allow lifetime to be shortened per field ↵Gary Guo
drop order Add the outlive relations per field drop order. This allows a single lifetime to be used when a field potentially borrow from two different fields, by allowing the longer-living field lifetime to be shortened to a shorter-living field lifetime. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-12-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: enable self-referential supportGary Guo
Enable self-referential support, and add example and test cases. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-11-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: add `with_project` methodGary Guo
The `project` method needs to perform covariant coercion on covariant fields, causing them to no longer being mutable. Implement a `with_project` that does not require covariant coercion by using higher-ranked trait bounds, thus allow the fields to be assignable inside the callback. This mechanism can also be used to access non-covariant fields. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-10-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: project self-referential fieldsGary Guo
This adds the projection for fields that are shared borrowed or that borrows other fields but is covariant. Both cases allow a shared reference to be accessed. No mutable references can be created for these cases for different reasons: * For fields that are shared borrowed, aliasing restriction prevents creation of mutable reference * For fields that borrow other fields, their proper type contains field lifetimes. These lifetimes cannot be made available in the returned `project` struct (because there is no way to represent existential lifetime in return position). For covariant types, it is possible to shorten these lifetimes to that of `&self`; but doing so requires the reference to also be covariant over the pointee type, so we cannot give out `&mut` as it is invariant over the pointee. Due to field-referencing fields being wrapped inside `Erase`, the normal accessor syntax stop working; create accessor methods for these fields instead. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-9-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: implement initialization of borrowed structsGary Guo
We now have the checks to ensure that lifetime relations are what is expected, we can generate the slot projections in `generate_pin_data` so self-referential struct can be implemented. New slot and guard types are defined (`SelfRefSlot` and `SelfRefDropGuard`) which gives the generated let bindings longer lifetime than the guard themselves. Have `__make_closure` take `data` back as an argument. This gives `#[pin_data]` an opportunity to change the type to add lifetimes. Higher-ranked trait bound on `__make_closure` is used to ensure that the initialization closure cannot make arbitrary assumptions of those lifetimes. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-8-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: check covariance of self-referential fieldsGary Guo
We implicitly infer covariance for fields that self-references. This needs to be checked to ensure that the fields are really covariant, so the rest of expansion code can rely on this fact. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-7-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: self-referential drop order checksGary Guo
Check drop order to ensure that usage of lifetime inside self-referential struct is consistent with the order that the fields will dropped in drop glue. First, fields are checked according to their index to ensure that if `a` borrows from `b`, `b` must outlive `a`. This is simple and produces a very good diagnostic when misused. Lifetime bounds can also be indirectly crafted with implied bounds that make fields well-formed. For example, in this struct struct Foo { x: &'b &'a (), a: String, y: PrintOnDrop<&'b str>, b: String, } `&'b &'a ()` will imply that `a` outlive `b`, which is inconsistent with the actual drop order. For this case, create a `__drop_order_check` function with field lifetimes and outlive relationship of them as generic parameter, and ask Rust to prove that the types are well-formed inside the generated function, to ensure that the bad implied bounds cannot happen. The `__drop_order_check` also need to correlate lifetimes or types captured by generics and the field lifetimes. Do this by inserting outlive bounds when a field mentions a specific type or lifetime parameter. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-6-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: teach drop check about generics that ↵Gary Guo
cannot dangle Lifetimes not needed by drop glue are considered by Rust's drop check to be considered `#[may_dangle]`. In case for a self-referential struct, we may have fields which need lifetime of borrowed fields in their drop glue, so compiler's automatic check is insufficient. Code like this: #[pin_data] struct SelfRef<'a> { borrow: PrintOnDrop<&'owner str>, owner: &'a str, } may access `owner` during the drop, however Rust will determine that since `'a` only is used in `owner`, the `'a` lifetime may dangle during drop. This is undesirable for pin-init self references, because `&'a str` could be coerced to `&'owner str` and this could further coerce if there're implied outlives, e.g. `&'earlier_field &'owner ()` would allow `&'owner str` to further coerce to `&'earlier_field`. Thus, if any self-referential field require field lifetime access in `Drop` impl, we would need to ensure that the all generic parameters visible by self-referential fields would strictly outlive the struct. And this can be done by a simple `Drop` impl that does nothing. Without a dropck eye patch, presence of `Drop` impl, albeit empty, tells the drop check that the strict outlive relation is needed. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-5-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: pin borrowed fields with wrapperGary Guo
For fields that are borrowed, a mutable reference to the struct no longer mean that it has the permission to access these fields. Therefore, the memory that they refer to must be pinned. Wrap these fields inside a `Borrowed` struct which pins it. They may be accessed directly (if they're not themselves referencing other struct fields), so implement a `Deref`. As such fields are always pinned, there is no need to generate a conditional `Unpin` implementations that implements `Unpin` when all fields are. Simply generate a never satisfiable `Unpin` implementation to prevent user from adding their own. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-4-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: rewrite fields that borrow othersGary Guo
Fields that borrow other fields have lifetimes that are within the struct and these are not part of the struct generics. Therefore, these fields need to have their lifetime erased. A naive implementation would be to replace their lifetimes with `'static`. However, doing so is unsound for multiple reasons: * Users may directly access such field with field access syntax, and get exposed with wrong lifetime; * Auto trait implementations will cause the struct to be implementing auto traits when the type only implements the auto trait for specific lifetime. This is similar to how specialization can be unsound if specialized on lifetime. Create a `Erase` type, which has `for<'a> fn(&'a ()) -> Foo<'a>` as generic parameter. Internally, it uses a helper trait to resolve that to `Foo<'static>`. The first issue is solved by not exposing any public accessor on that type. The second issue is solved by add custom `Send` and `Sync` implementations that requires `Send` to be implemented for all lifetimes, thus closing the lifetime specialization hole. The actual implementation is a bit more convoluted because it supports erasing multiple lifetimes. This is more or less a stable polyfill of the unstable `unsafe_binder` feature, without `unsafe_binders`'s no drop glue requirement. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-3-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-11rust: pin-init: internal: pin_data: infer self-referential structGary Guo
As a first step towards adding self-referential data structures in pin-init, add parsing support. Scan all field types for unbounded lifetimes, and if the names that of fields, it is inferred as a self-referential field lifetime. No explicit annotations are supported yet. Acked-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20261008-dev-selfref-v2-2-e280b3c8fba5@garyguo.net/ Signed-off-by: Gary Guo <gary@garyguo.net>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-10-07rust: 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>
2026-09-30rust: 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>
2026-09-30rust: 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>
2026-09-30rust: 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>
2026-09-28rust: 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>
2026-09-28rust: 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>
2026-09-28rust: 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>