| d2f30922 | 08-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin_init: internal: use `loop {}` to produce never value
In the `init!`/`pin_init!` macros, we rely on a trick that assigns never (`!`) values to all mentioned fields in never-executed code to
rust: pin_init: internal: use `loop {}` to produce never value
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>
show more ...
|
| 5423ef9d | 27-May-2026 |
Mirko Adzic <adzicmirko97@gmail.com> |
rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`
Allows `non_snake_case` lint on local variables generated in `[pin_]init!`.
Conceptually the identifiers in `[pin_]init!` j
rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`
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>
show more ...
|
| e6405dca | 27-May-2026 |
Mirko Adzic <adzicmirko97@gmail.com> |
rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`
Allows `non_snake_case` lint on struct fields generated by `#[pin_data]`.
Since the same warning will be reported by the co
rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`
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>
show more ...
|
| 28ba76f3 | 27-May-2026 |
Martin Kletzander <mkletzan@redhat.com> |
rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code
When using a macro with custom attributes in a `#[pin_data]` struct it can mess up the generated code. The generated co
rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code
When using a macro with custom attributes in a `#[pin_data]` struct it can mess up the generated code. The generated code needs nothing more than the `#[cfg]` attribute, thus strip away all other attributes.
[ Rebased and updated to only include `#[cfg]` instead of both `#[cfg]` and `#[doc]`; doc is not needed for the generated hidden items. - Gary ]
Signed-off-by: Martin Kletzander <mkletzan@redhat.com> Co-developed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260527-pin-init-sync-v1-1-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| 6fb5912c | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: project using full slot
Instead of projecting using pointer to a field project the full slot. This further shifts the code generation from the initializer site to the struc
rust: pin-init: internal: project using full slot
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>
show more ...
|
| 5483a97d | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: project slots instead of references
By projecting slots, the `pin_init!` and `init!` code path can be more unified. This also reduces the amount of macro-generated code and
rust: pin-init: internal: project slots instead of references
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>
show more ...
|
| 57b0a0d7 | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: make `make_closure` inherent methods
The `InitData` and `PinData` traits do not need to exist, the inference helpers could be inherent methods instead.
There is no risk fo
rust: pin-init: internal: make `make_closure` inherent methods
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>
show more ...
|
| 27693a56 | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: use marker on drop guard type for pinned fields
Instead of projecting the created reference, simply create drop guards with different marker types and have the `let_binding
rust: pin-init: internal: use marker on drop guard type for pinned fields
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>
show more ...
|
| df1827ba | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: init: handle code blocks early
`InitializerKind::Code` is a special case where it does not initialize a field, and thus generate no guard and accessors. Handle it earlier a
rust: pin-init: internal: init: handle code blocks early
`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>
show more ...
|
| fea304ec | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: add `PhantomInvariant` and `PhantomInvariantLifetime`
Currently, the `pin_init` library has an `Invariant` type alias, and it is instantiated using `PhantomData`. Generated
rust: pin-init: internal: add `PhantomInvariant` and `PhantomInvariantLifetime`
Currently, the `pin_init` library has an `Invariant` type alias, and it is instantiated using `PhantomData`. Generated code from `pin_data` on the other hand cannot access the crate-local type alias, so it generates `PhantomData<fn(T) -> T>` directly. This is all very inconsistent, despite the exact same use case of ensuring invariance.
Add `PhantomInvariant` and `PhantomInvariantLifetime` and switch all users that need to express the concept of invariance to use these. They're polyfills of unstable types in the same names in the Rust standard library.
Link: https://patch.msgid.link/20260512-pin-init-sync-v1-3-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| 4b60f38c | 12-May-2026 |
Mohamad Alsadhan <mo@sdhn.cc> |
rust: pin-init: internal: pin_data: add struct to record field info
Introduce `FieldInfo` struct to encapsulate field and other relevant data, instead of carrying a pair of `(pinned, field)` in all
rust: pin-init: internal: pin_data: add struct to record field info
Introduce `FieldInfo` struct to encapsulate field and other relevant data, instead of carrying a pair of `(pinned, field)` in all places. This allows us to add more information to the struct in the future.
Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Co-developed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260512-pin-init-sync-v1-2-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| 1e648c22 | 12-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: pin_data: use closure for `handle_field`
`handle_field` is currently a function, which precludes it from referencing things in the scope of the parent function. Given that
rust: pin-init: internal: pin_data: use closure for `handle_field`
`handle_field` is currently a function, which precludes it from referencing things in the scope of the parent function. Given that it's only called once, inline its contents to the closure that invokes it instead, so it can directly reference `struct_name` without having to pass in as argument.
Link: https://patch.msgid.link/20260512-pin-init-sync-v1-1-81963130dfbd@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| faed8194 | 01-May-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: remove `collect_tuple` polyfill after MSRV bump
Tuples implement `FromIterator` since Rust 1.79. Remove the `collect_tuple` polyfill now the MSRV is above 1.79.
To avoid o
rust: pin-init: internal: remove `collect_tuple` polyfill after MSRV bump
Tuples implement `FromIterator` since Rust 1.79. Remove the `collect_tuple` polyfill now the MSRV is above 1.79.
To avoid over-identing the closure, I move the `Field` destructure from the closure parameter to a let binding. This keeps the diff small.
Link: https://patch.msgid.link/20260501134445.3809731-1-gary@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| e5cece93 | 28-Apr-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: turn `PhantomPinned` error into warnings
The `PhantomPinned` detection is just a lint, and is emitted as an error because there is no `compile_warning!()` macro, and `proc-
rust: pin-init: internal: turn `PhantomPinned` error into warnings
The `PhantomPinned` detection is just a lint, and is emitted as an error because there is no `compile_warning!()` macro, and `proc-macro-diagnostics` is not stable.
Use of `#[deprecated = ""]` attribute to approximate custom proc-macro warnings. A new line is added before message for visual clarity.
An example warning with this trick looks like this:
warning: use of deprecated function `_::warn`: The field `pin` of type `PhantomPinned` only has an effect if it has the `#[pin]` attribute --> test.rs:9:5 | 9 | pin: marker::PhantomPinned, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Suggested-by: Benno Lossin <lossin@kernel.org> Link: https://github.com/Rust-for-Linux/pin-init/issues/51 Link: https://patch.msgid.link/20260428-pin-init-sync-v1-10-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| 3dc01266 | 28-Apr-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: cleanup workaround for old Rust compiler
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-
rust: pin-init: cleanup workaround for old Rust compiler
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>
show more ...
|
| 38a07ef9 | 28-Apr-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: internal: adjust license identifier of `zeroable.rs`
The pin-init crate has been licensed under `Apache-2.0 OR MIT` since the beginning. I introduced in commit 071cedc84e90 ("rust: a
rust: pin-init: internal: adjust license identifier of `zeroable.rs`
The pin-init crate has been licensed under `Apache-2.0 OR MIT` since the beginning. I introduced in commit 071cedc84e90 ("rust: add derive macro for `Zeroable`") `zeroable.rs` with incompatible GPL-2.0 SPDX identifier. The file has not been modified by other authors, so relicense it under the above license.
Signed-off-by: Benno Lossin <lossin@kernel.org> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260428-pin-init-sync-v1-7-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| c64c793d | 28-Apr-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: internal: remove redundant `#[pin]` filtering
The `generate_projections` and `generate_the_pin_data` function already receive filtered field lists, they do not need to filter out `#[
rust: pin-init: internal: remove redundant `#[pin]` filtering
The `generate_projections` and `generate_the_pin_data` function already receive filtered field lists, they do not need to filter out `#[pin]` again.
Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260428-pin-init-sync-v1-6-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| 5edf8ac2 | 28-Apr-2026 |
Mohamad Alsadhan <mo@sdhn.cc> |
rust: pin-init: internal: add missing where clause to projection types
`#[pin_data]` failed to propagate the struct's `where` clause to the generated projection struct. As a result, bounds written i
rust: pin-init: internal: add missing where clause to projection types
`#[pin_data]` failed to propagate the struct's `where` clause to the generated projection struct. As a result, bounds written in a `where` clause could be dropped during expansion, causing type errors when fields depended on those bounds.
Fix this by adding the missing `where` clause to the generated projection struct.
Reported-by: Andreas Hindborg <a.hindborg@kernel.org> Closes: https://rust-for-linux.zulipchat.com/#narrow/channel/561532-pin-init/topic/generic.20bounds.20and.20.60.23.5Bpin_data.5D.60/with/578381591 Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Reviewed-by: Gary Guo <gary@garyguo.net> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260428-pin-init-sync-v1-5-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
show more ...
|
| 68bf1022 | 27-Apr-2026 |
Gary Guo <gary@garyguo.net> |
rust: pin-init: fix incorrect accessor reference lifetime
When a field has been initialized, `init!`/`pin_init!` create a reference or pinned reference to the field so it can be accessed later durin
rust: pin-init: fix incorrect accessor reference lifetime
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>
show more ...
|
| 960c37cb | 19-Mar-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: properly document let binding workaround
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 i
rust: pin-init: properly document let binding workaround
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>
show more ...
|
| fdbaa9d2 | 11-Mar-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: replace shadowed return token by `unsafe`-to-create token
We use a unit struct `__InitOk` in the closure generated by the initializer macros as the return value. We shadow it by crea
rust: pin-init: replace shadowed return token by `unsafe`-to-create token
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>
show more ...
|