summaryrefslogtreecommitdiff
path: root/rust/pin-init/internal/src/init.rs
AgeCommit message (Collapse)Author
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-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: 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-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-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-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-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-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-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-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>
2026-04-30rust: pin-init: internal: move alignment check to `make_field_check`Gary Guo
Instead of having the reference creation serving dual-purpose as both for let bindings and alignment check, detangle them so that the alignment check is done explicitly in `make_field_check`. This is more robust against refactors that may change the way let bindings are created. Cc: stable@vger.kernel.org Reviewed-by: Alice Ryhl <aliceryhl@google.com> Signed-off-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260427-pin-init-fix-v3-1-496a699674dd@garyguo.net [ Reworded for typo. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-03-25rust: pin-init: replace `addr_of_mut!` with `&raw mut`Antonio Hickey
`feature(raw_ref_op)` became stable in Rust 1.82.0 which is the current MSRV of pin-init with no default features. Earlier Rust versions will now need to enable `raw_ref_op` to continue to work with pin-init. This reduces visual complexity and improves consistency with existing reference syntax. Suggested-by: Benno Lossin <lossin@kernel.org> Link: https://github.com/Rust-for-Linux/linux/issues/1148 Closes: https://github.com/Rust-for-Linux/pin-init/issues/99 Signed-off-by: Antonio Hickey <contact@antoniohickey.com> Link: https://github.com/Rust-for-Linux/pin-init/commit/e27763004e2f6616b089437fbe9b3719cd72bd5c [ Reworded commit message. - Benno ] Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260319093542.3756606-6-lossin@kernel.org Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-03-25rust: pin-init: properly document let binding workaroundBenno Lossin
The three let bindings (in the bodies of `cast_init`, `cast_pin_init` and the `init!` macro) are used to avoid the following compiler error in Rust 1.78.0, 1.79.0, 1.80.0, 1.80.1, and 1.81.0 (just showing the one for `cast_init`, the others are similar): error[E0391]: cycle detected when computing type of opaque `cast_init::{opaque#0}` --> src/lib.rs:1160:66 | 1160 | pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> { | ^^^^^^^^^^^^^^^ | note: ...which requires borrow-checking `cast_init`... --> src/lib.rs:1160:1 | 1160 | pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const checking `cast_init`... --> src/lib.rs:1160:1 | 1160 | pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing whether `cast_init::{opaque#0}` is freeze... = note: ...which requires evaluating trait selection obligation `cast_init::{opaque#0}: core::marker::Freeze`... = note: ...which again requires computing type of opaque `cast_init::{opaque#0}`, completing the cycle note: cycle used when computing type of `cast_init::{opaque#0}` --> src/lib.rs:1160:66 | 1160 | pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> { | ^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information Once we raise the nightly-MSRV above 1.81, we can remove this workaround. Link: https://github.com/Rust-for-Linux/pin-init/commit/bb3e96f3e9a4f5fca80a22af883c7e5aa90f0893 [ Moved this commit after the previous one to avoid a build failure due to unstable features. Changed the cfg to use `USE_RUSTC_FEAUTURES`. - Benno ] Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260319093542.3756606-3-lossin@kernel.org Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-03-12rust: pin-init: replace shadowed return token by `unsafe`-to-create tokenBenno Lossin
We use a unit struct `__InitOk` in the closure generated by the initializer macros as the return value. We shadow it by creating a struct with the same name again inside of the closure, preventing early returns of `Ok` in the initializer (before all fields have been initialized). In the face of Type Alias Impl Trait (TAIT) and the next trait solver, this solution no longer works [1]. The shadowed struct can be named through type inference. In addition, there is an RFC proposing to add the feature of path inference to Rust, which would similarly allow [2]. Thus remove the shadowed token and replace it with an `unsafe` to create token. The reason we initially used the shadowing solution was because an alternative solution used a builder pattern. Gary writes [3]: In the early builder-pattern based InitOk, having a single InitOk type for token is unsound because one can launder an InitOk token used for one place to another initializer. I used a branded lifetime solution, and then you figured out that using a shadowed type would work better because nobody could construct it at all. The laundering issue does not apply to the approach we ended up with today. With this change, the example by Tim Chirananthavat in [1] no longer compiles and results in this error: error: cannot construct `pin_init::__internal::InitOk` with struct literal syntax due to private fields --> src/main.rs:26:17 | 26 | InferredType {} | ^^^^^^^^^^^^ | = note: private field `0` that was not provided help: you might have meant to use the `new` associated function | 26 - InferredType {} 26 + InferredType::new() | Applying the suggestion of using the `::new()` function, results in another expected error: error[E0133]: call to unsafe function `pin_init::__internal::InitOk::new` is unsafe and requires unsafe block --> src/main.rs:26:17 | 26 | InferredType::new() | ^^^^^^^^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior Reported-by: Tim Chirananthavat <theemathas@gmail.com> Link: https://github.com/rust-lang/rust/issues/153535 [1] Link: https://github.com/rust-lang/rfcs/pull/3444#issuecomment-4016145373 [2] Link: https://github.com/rust-lang/rust/issues/153535#issuecomment-4017620804 [3] Fixes: fc6c6baa1f40 ("rust: init: add initialization macros") Cc: stable@vger.kernel.org Signed-off-by: Benno Lossin <lossin@kernel.org> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260311105056.1425041-1-lossin@kernel.org [ Added period as mentioned. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-03-06rust: pin-init: internal: init: document load-bearing fact of field accessorsBenno Lossin
The functions `[Pin]Init::__[pinned_]init` and `ptr::write` called from the `init!` macro require the passed pointer to be aligned. This fact is ensured by the creation of field accessors to previously initialized fields. Since we missed this very important fact from the beginning [1], document it in the code. Link: https://rust-for-linux.zulipchat.com/#narrow/channel/561532-pin-init/topic/initialized.20field.20accessor.20detection/with/576210658 [1] Fixes: 90e53c5e70a6 ("rust: add pin-init API core") Cc: <stable@vger.kernel.org> # 6.6.y, 6.12.y: 42415d163e5d: rust: pin-init: add references to previously initialized fields Cc: <stable@vger.kernel.org> # 6.6.y, 6.12.y, 6.18.y, 6.19.y Signed-off-by: Benno Lossin <lossin@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260302140424.4097655-2-lossin@kernel.org [ Updated Cc: stable@ tags as discussed. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-03-06rust: pin-init: internal: init: remove `#[disable_initialized_field_access]`Benno Lossin
Gary noticed [1] that the initializer macros as well as the `[Pin]Init` traits cannot support unaligned fields, since they use operations that require aligned pointers. This means that any code using structs with unaligned fields in pin-init is unsound. By default, the `init!` macro generates references to initialized fields, which makes the compiler check that those fields are aligned. However, we added the `#[disable_initialized_field_access]` attribute to avoid this behavior in commit ceca298c53f9 ("rust: pin-init: internal: init: add escape hatch for referencing initialized fields"). Thus remove the `#[disable_initialized_field_access]` attribute from `init!`, which is the only safe way to create an initializer handling unaligned fields. If support for in-place initializing structs with unaligned fields is required in the future, we could figure out a solution. This is tracked in [2]. Reported-by: Gary Guo <gary@garyguo.net> Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/561532-pin-init/topic/initialized.20field.20accessor.20detection/with/576210658 [1] Link: https://github.com/Rust-for-Linux/pin-init/issues/112 [2] Fixes: ceca298c53f9 ("rust: pin-init: internal: init: add escape hatch for referencing initialized fields") Signed-off-by: Benno Lossin <lossin@kernel.org> Acked-by: Janne Grunau <j@jannau.net> Reviewed-by: Gary Guo <gary@garyguo.net> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Link: https://patch.msgid.link/20260302140424.4097655-1-lossin@kernel.org [ Adjusted tags and reworded as discussed. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-01-17rust: pin-init: internal: init: simplify Zeroable safety checkBenno Lossin
The `Zeroable` type check uses a small dance with a raw pointer to aid type inference. It turns out that this is not necessary and type inference is powerful enough to resolve any ambiguity. Thus remove it. Suggested-by: Gary Guo <gary@garyguo.net> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-01-17rust: pin-init: internal: init: add escape hatch for referencing initialized ↵Benno Lossin
fields The initializer macro emits mutable references for already initialized fields, which allows modifying or accessing them later in code blocks or when initializing other fields. This behavior results in compiler errors when combining with packed structs, since those do not permit creating references to misaligned fields. For example: #[repr(C, packed)] struct Foo { a: i8, b: i32, } fn main() { let _ = init!(Foo { a: -42, b: 42 }); } This will lead to an error like this: error[E0793]: reference to field of packed struct is unaligned --> tests/ui/compile-fail/init/packed_struct.rs:10:13 | 10 | let _ = init!(Foo { a: -42, b: 42 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this struct is 1-byte aligned, but the type of this field may require higher alignment = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) = note: this error originates in the macro `init` (in Nightly builds, run with -Z macro-backtrace for more info) This was requested by Janne Grunau [1] and will most certainly be used by the kernel when we eventually end up with trying to initialize packed structs. Thus add an initializer attribute `#[disable_initialized_field_access]` that does what the name suggests: do not generate references to already initialized fields. There is space for future work: add yet another attribute which can be applied on fields of initializers that ask for said field to be made accessible. We can add that when the need arises. Requested-by: Janne Grunau <j@jannau.net> Link: https://lore.kernel.org/all/20251206170214.GE1097212@robin.jannau.net [1] Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-01-17rust: pin-init: internal: init: add support for attributes on initializer fieldsBenno Lossin
Initializer fields ought to support the same attributes that are allowed in struct initializers on fields. For example, `cfg` or lint levels such as `expect`, `allow` etc. Add parsing support for these attributes using syn to initializer fields and adjust the macro expansion accordingly. Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-01-17rust: pin-init: add `#[default_error(<type>)]` attribute to initializer macrosBenno Lossin
The `#[default_error(<type>)]` attribute can be used to supply a default type as the error used for the `[pin_]init!` macros. This way one can easily define custom `try_[pin_]init!` variants that default to your project specific error type. Just write the following declarative macro: macro_rules! try_init { ($($args:tt)*) => { ::pin_init::init!( #[default_error(YourCustomErrorType)] $($args)* ) } } Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-01-17rust: pin-init: rewrite the initializer macros using `syn`Benno Lossin
Rewrite the initializer macros `[pin_]init!` using `syn`. No functional changes intended aside from improved error messages on syntactic and semantical errors. For example if one forgets to use `<-` with an initializer (and instead uses `:`): impl Bar { fn new() -> impl PinInit<Self> { ... } } impl Foo { fn new() -> impl PinInit<Self> { pin_init!(Self { bar: Bar::new() }) } } Then the declarative macro would report: error[E0308]: mismatched types --> tests/ui/compile-fail/init/colon_instead_of_arrow.rs:21:9 | 14 | fn new() -> impl PinInit<Self> { | ------------------ the found opaque type ... 21 | pin_init!(Self { bar: Bar::new() }) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | expected `Bar`, found opaque type | arguments to this function are incorrect | = note: expected struct `Bar` found opaque type `impl pin_init::PinInit<Bar>` note: function defined here --> $RUST/core/src/ptr/mod.rs | | pub const unsafe fn write<T>(dst: *mut T, src: T) { | ^^^^^ = note: this error originates in the macro `$crate::__init_internal` which comes from the expansion of the macro `pin_init` (in Nightly builds, run with -Z macro-backtrace for more info) And the new error is: error[E0308]: mismatched types --> tests/ui/compile-fail/init/colon_instead_of_arrow.rs:21:31 | 14 | fn new() -> impl PinInit<Self> { | ------------------ the found opaque type ... 21 | pin_init!(Self { bar: Bar::new() }) | --- ^^^^^^^^^^ expected `Bar`, found opaque type | | | arguments to this function are incorrect | = note: expected struct `Bar` found opaque type `impl pin_init::PinInit<Bar>` note: function defined here --> $RUST/core/src/ptr/mod.rs | | pub const unsafe fn write<T>(dst: *mut T, src: T) { | ^^^^^ Importantly, this error gives much more accurate span locations, pointing to the offending field, rather than the entire macro invocation. Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>