| 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 ...
|
| 580cc37b | 02-Mar-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: internal: init: document load-bearing fact of field accessors
The functions `[Pin]Init::__[pinned_]init` and `ptr::write` called from the `init!` macro require the passed pointer to
rust: pin-init: internal: init: document load-bearing fact of field accessors
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>
show more ...
|
| 1f1cd696 | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: internal: init: simplify Zeroable safety check
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
rust: pin-init: internal: init: simplify Zeroable safety check
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>
show more ...
|
| ceca298c | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: internal: init: add escape hatch for referencing initialized fields
The initializer macro emits mutable references for already initialized fields, which allows modifying or accessing
rust: pin-init: internal: init: add escape hatch for referencing initialized 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>
show more ...
|
| d26732e5 | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: internal: init: add support for attributes on initializer fields
Initializer fields ought to support the same attributes that are allowed in struct initializers on fields. For exampl
rust: pin-init: internal: init: add support for attributes on initializer fields
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>
show more ...
|
| aeabc92e | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: add `#[default_error(<type>)]` attribute to initializer macros
The `#[default_error(<type>)]` attribute can be used to supply a default type as the error used for the `[pin_]init!` m
rust: pin-init: add `#[default_error(<type>)]` attribute to initializer macros
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>
show more ...
|
| 4883830e | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: rewrite the initializer macros using `syn`
Rewrite the initializer macros `[pin_]init!` using `syn`. No functional changes intended aside from improved error messages on syntactic an
rust: pin-init: rewrite the initializer macros using `syn`
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>
show more ...
|
| dae5466c | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: add `?Sized` bounds to traits in `#[pin_data]` macro
The `#[pin_data]` macro uses some auxiliary traits to ensure that a user does not implement `Drop` for the annotated struct, as t
rust: pin-init: add `?Sized` bounds to traits in `#[pin_data]` macro
The `#[pin_data]` macro uses some auxiliary traits to ensure that a user does not implement `Drop` for the annotated struct, as that is unsound and can lead to UB. However, if the struct that is annotated is `!Sized`, the current bounds do not work, because `Sized` is an implicit bound for generics.
This is *not* a soundness hole of pin-init, as it currently is impossible to construct an unsized struct using pin-init.
Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
show more ...
|
| 560f6d13 | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: rewrite `#[pin_data]` using `syn`
Rewrite the attribute macro `#[pin_data]` using `syn`. No functional changes intended aside from improved error messages on syntactic and semantical
rust: pin-init: rewrite `#[pin_data]` using `syn`
Rewrite the attribute macro `#[pin_data]` using `syn`. No functional changes intended aside from improved error messages on syntactic and semantical errors. For example if one forgets a comma at the end of a field:
#[pin_data] struct Foo { a: Box<Foo> b: Box<Foo> }
The declarative macro reports the following errors:
error: expected `,`, or `}`, found `b` --> tests/ui/compile-fail/pin_data/missing_comma.rs:5:16 | 5 | a: Box<Foo> | ^ help: try adding a comma: `,`
error: recursion limit reached while expanding `$crate::__pin_data!` --> tests/ui/compile-fail/pin_data/missing_comma.rs:3:1 | 3 | #[pin_data] | ^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`$CRATE`) = note: this error originates in the macro `$crate::__pin_data` which comes from the expansion of the attribute macro `pin_data` (in Nightly builds, run with -Z macro-backtrace for more info)
The new `syn` version reports:
error: expected `,`, or `}`, found `b` --> tests/ui/compile-fail/pin_data/missing_comma.rs:5:16 | 5 | a: Box<Foo> | ^ help: try adding a comma: `,`
error: expected `,` --> tests/ui/compile-fail/pin_data/missing_comma.rs:6:5 | 6 | b: Box<Foo> | ^
Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
show more ...
|
| a92f5fd2 | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: rewrite the `#[pinned_drop]` attribute macro using `syn`
Rewrite the attribute macro for implementing `PinnedDrop` using `syn`. Otherwise no functional changes intended aside from im
rust: pin-init: rewrite the `#[pinned_drop]` attribute macro using `syn`
Rewrite the attribute macro for implementing `PinnedDrop` using `syn`. Otherwise no functional changes intended aside from improved error messages on syntactic and semantical errors. For example:
When missing the `drop` function in the implementation, the old error was:
error: no rules expected `)` --> tests/ui/compile-fail/pinned_drop/no_fn.rs:6:1 | 6 | #[pinned_drop] | ^^^^^^^^^^^^^^ no rules expected this token in macro call | note: while trying to match keyword `fn` --> src/macros.rs | | fn drop($($sig:tt)*) { | ^^ = note: this error originates in the attribute macro `pinned_drop` (in Nightly builds, run with -Z macro-backtrace for more info)
And the new one is:
error[E0046]: not all trait items implemented, missing: `drop` --> tests/ui/compile-fail/pinned_drop/no_fn.rs:7:1 | 7 | impl PinnedDrop for Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^ missing `drop` in implementation | = help: implement the missing item: `fn drop(self: Pin<&mut Self>, _: OnlyCallFromDrop) { todo!() }`
Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
show more ...
|
| 50426bde | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: rewrite `derive(Zeroable)` and `derive(MaybeZeroable)` using `syn`
Rewrite the two derive macros for `Zeroable` using `syn`. One positive side effect of this change is that tuple str
rust: pin-init: rewrite `derive(Zeroable)` and `derive(MaybeZeroable)` using `syn`
Rewrite the two derive macros for `Zeroable` using `syn`. One positive side effect of this change is that tuple structs are now supported by them. Additionally, syntax errors and the error emitted when trying to use one of the derive macros on an `enum` are improved. Otherwise no functional changes intended.
For example:
#[derive(Zeroable)] enum Num { A(u32), B(i32), }
Produced this error before this commit:
error: no rules expected keyword `enum` --> tests/ui/compile-fail/zeroable/enum.rs:5:1 | 5 | enum Num { | ^^^^ no rules expected this token in macro call | note: while trying to match keyword `struct` --> src/macros.rs | | $vis:vis struct $name:ident | ^^^^^^
Now the error is:
error: cannot derive `Zeroable` for an enum --> tests/ui/compile-fail/zeroable/enum.rs:5:1 | 5 | enum Num { | ^^^^
error: cannot derive `Zeroable` for an enum
Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> Signed-off-by: Benno Lossin <lossin@kernel.org>
show more ...
|
| 26bd9402 | 16-Jan-2026 |
Benno Lossin <lossin@kernel.org> |
rust: pin-init: internal: add utility API for syn error handling
The API is similar to diagnostics handling in rustc and uses a `ErrorGuaranteed` value to signify that an error has been emitted. It
rust: pin-init: internal: add utility API for syn error handling
The API is similar to diagnostics handling in rustc and uses a `ErrorGuaranteed` value to signify that an error has been emitted. It supports both fatal errors (which abort the macro expansion immediately by returning `Err(ErrorGuaranteed)`) and non-fatal ones at generation time. These errors are appended to the token stream after generation has finished normally. This allows giving good errors while still expanding most of the code as expected to avoid the user encountering additional errors (for example missing definitions).
Suggested-by: Gary Guo <gary@garyguo.net> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Gary Guo <gary@garyguo.net> [ remove duplicate word in commit message - Benno ] Signed-off-by: Benno Lossin <lossin@kernel.org>
show more ...
|
| a9fa3a9c | 08-Mar-2025 |
Benno Lossin <benno.lossin@proton.me> |
rust: pin-init: miscellaneous synchronization with the user-space version
Remove the last differences between the kernel version and the user-space version.
Signed-off-by: Benno Lossin <benno.lossi
rust: pin-init: miscellaneous synchronization with the user-space version
Remove the last differences between the kernel version and the user-space version.
Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Fiona Behrens <me@kloenk.dev> Link: https://lore.kernel.org/r/20250308110339.2997091-20-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
show more ...
|
| 7cb5dee4 | 08-Mar-2025 |
Benno Lossin <benno.lossin@proton.me> |
rust: pin-init: internal: synchronize with user-space version
Synchronize the internal macros crate with the user-space version that uses the quote crate [1] instead of a custom `quote!` macro. The
rust: pin-init: internal: synchronize with user-space version
Synchronize the internal macros crate with the user-space version that uses the quote crate [1] instead of a custom `quote!` macro. The imports in the different version are achieved using `cfg` on the kernel config value. This cfg is always set in the kernel and never set in the user-space version.
Since the quote crate requires the proc_macro2 crate, imports also need to be adjusted and `.into()` calls have to be inserted.
Link: https://crates.io/crates/quote [1] Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Reviewed-by: Fiona Behrens <me@Kloenk.dev> Link: https://lore.kernel.org/r/20250308110339.2997091-19-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
show more ...
|
| dbd5058b | 08-Mar-2025 |
Benno Lossin <benno.lossin@proton.me> |
rust: make pin-init its own crate
Rename relative paths inside of the crate to still refer to the same items, also rename paths inside of the kernel crate and adjust the build system to build the cr
rust: make pin-init its own crate
Rename relative paths inside of the crate to still refer to the same items, also rename paths inside of the kernel crate and adjust the build system to build the crate.
[ Remove the `expect` (and thus the `lint_reasons` feature) since the tree now uses `quote!` from `rust/macros/export.rs`. Remove the `TokenStream` import removal, since it is now used as well.
In addition, temporarily (i.e. just for this commit) use an `--extern force:alloc` to prevent an unknown `new_uninit` error in the `rustdoc` target. For context, please see a similar case in:
https://lore.kernel.org/lkml/20240422090644.525520-1-ojeda@kernel.org/
And adjusted the message above. - Miguel ]
Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Fiona Behrens <me@kloenk.dev> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250308110339.2997091-16-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
show more ...
|
| 4b11798e | 08-Mar-2025 |
Benno Lossin <benno.lossin@proton.me> |
rust: pin-init: move proc-macro documentation into pin-init crate
Move the documentation of proc-macros from pin-init-internal into pin-init. This is because documentation can only reference types f
rust: pin-init: move proc-macro documentation into pin-init crate
Move the documentation of proc-macros from pin-init-internal into pin-init. This is because documentation can only reference types from dependencies and pin-init-internal cannot have pin-init as a dependency, as that would be cyclic.
Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Fiona Behrens <me@kloenk.dev> Tested-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250308110339.2997091-5-benno.lossin@proton.me Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
show more ...
|