summaryrefslogtreecommitdiff
path: root/rust/pin-init
AgeCommit message (Collapse)Author
2026-05-29rust: pin_init: internal: use `loop {}` to produce never valueGary Guo
In the `init!`/`pin_init!` macros, we rely on a trick that assigns never (`!`) values to all mentioned fields in never-executed code to let the compiler check that all fields have been initialized. Currently we use `::core::panic!()` to produce this value, but before Rust 1.91.0, it creates outlined `panic_cold_explicit` functions which do not get removed by the optimizer, thus leaving dead code behind in the binary. This has been fixed by [1], which lands in Rust 1.91.0+, higher than the kernel minimum version 1.85.0. This causes ~200 dead `panic_cold_explicit` instances being included in the binary, with ~90 of them from nova-core's usage of pin-init. Work around the issue by using `loop {}` which creates the never value without macro expansion or function call at all. All instances of `panic_cold_explicit` outside libcore are removed by this change in my kernel build. Link: https://github.com/rust-lang/rust/pull/145304 [1] Link: https://patch.msgid.link/20260508152950.833635-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: remove `E` from `InitClosure`Gary Guo
Move `E` from type to trait impl block. This greatly shortens the monomorphized type names. The `__pinned_init` function name is only slightly shortened as it still encodes the `E` as part of `PinInit<T, E>` in the symbol. `T` cannot be moved to trait impl block otherwise it will start to conflict with the `impl Init<T> for T` as Rust cannot deduce that there're no types that fulfill `T: FnOnce(*mut T)`. Link: https://patch.msgid.link/20260527-pin-init-sync-v1-6-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: move `InitClosure` out from `__internal`Gary Guo
The `__internal` module is for exposing internal items publicly to procedural macros (pin-init-internal). Types that are crate-local only can just have proper visibility and does not need to be in `__internal`. The type name of `InitClosure` can often shows up in symbol names, this reduces the length slightly. Link: https://patch.msgid.link/20260527-pin-init-sync-v1-5-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: docs: fix typos in MaybeZeroable documentationXiaobo Liu
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com> Link: https://patch.msgid.link/20260527-pin-init-sync-v1-4-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`Mirko Adzic
Allows `non_snake_case` lint on local variables generated in `[pin_]init!`. Conceptually the identifiers in `[pin_]init!` just references the field names, and are not defining them, so the warning should not be generated, similar to how constructing a struct with non-snake-case field names do no generate these warnings. Reported-by: Gary Guo <gary@garyguo.net> Closes: https://github.com/Rust-for-Linux/pin-init/issues/125 Closes: https://lore.kernel.org/rust-for-linux/DGTBJBIVFZ2K.2F1ZEFGY0G7NK@garyguo.net/ Fixes: 42415d163e5d ("rust: pin-init: add references to previously initialized fields") Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260527-pin-init-sync-v1-3-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`Mirko Adzic
Allows `non_snake_case` lint on struct fields generated by `#[pin_data]`. Since the same warning will be reported by the compiler on the struct definition, having extra warnings for the generated code is unnecessary and confusing. Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com> Link: https://patch.msgid.link/20260527-pin-init-sync-v1-2-e20335ed2501@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-29rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated codeMartin Kletzander
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>
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-14rust: pin-init: internal: add `PhantomInvariant` and `PhantomInvariantLifetime`Gary Guo
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>
2026-05-14rust: pin-init: internal: pin_data: add struct to record field infoMohamad Alsadhan
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>
2026-05-14rust: pin-init: internal: pin_data: use closure for `handle_field`Gary Guo
`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>
2026-05-10rust: pin-init: examples: fix `useless_borrows_in_formatting` clippy warningGary Guo
Clippy 1.97 introduces new `useless_borrows_in_formatting` warning which fires on the examples as we have `&*expr` where the format macro takes reference already. Remove the extra borrow. Link: https://patch.msgid.link/20260505115138.2466966-1-gary@kernel.org Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: remove `collect_tuple` polyfill after MSRV bumpGary Guo
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>
2026-05-10rust: pin-init: internal: turn `PhantomPinned` error into warningsGary Guo
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>
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-05-10rust: pin-init: fix badge URL in READMEGary Guo
The old CI workflow has been deleted ~1 year ago. Fix the URL to point to the correct one. Link: https://patch.msgid.link/20260428-pin-init-sync-v1-8-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: internal: adjust license identifier of `zeroable.rs`Benno Lossin
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>
2026-05-10rust: pin-init: internal: remove redundant `#[pin]` filteringGary Guo
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>
2026-05-10rust: pin-init: internal: add missing where clause to projection typesMohamad Alsadhan
`#[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>
2026-05-10rust: pin-init: extend `impl_zeroable_option` macro to handle genericsMohamad Alsadhan
Improve impl_zeroable_option macro to handle generic impls for types like `&T`, `&mut T`, `NonNull<T>`, and others (for which `Option<T>` is guaranteed to be zeroable) with similar approach to `impl_zeroable`. Also, update old declarations to use generics e.g. `NonZeroU8` to `NonZero<u8>`. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260428-pin-init-sync-v1-4-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: cleanup `Zeroable` and `ZeroableOptions`Mohamad Alsadhan
Place definitions and implementations (incl. macro invocations) of the `Zeroable` trait first in the relevant section of `src/lib.rs`, followed by the ZeroableOption trait and its implementations. Rename `impl_non_zero_int_zeroable_option` to `impl_zeroable_option` for consistency. This commit should not introduce any functional changes. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://patch.msgid.link/20260428-pin-init-sync-v1-3-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: bump minimum Rust version to 1.82Gary Guo
Following the kernel minimum version bump in commit f32fb9c58a5b ("rust: bump Rust minimum supported version to 1.85.0 (Debian Trixie)"), bump pin-init's minimum Rust version to 1.82. This removes the `lint_reasons` feature which is stabilized in 1.81 and the `raw_ref_ops` and `new_uninit` features which are stabilized in 1.82. Given we do not use any features that are stabilized in 1.82..=1.85 range, and pin-init crate is useful for other projects which may have their own MSRV requirements, the minimum version is not straightly bumped to 1.85. Reviewed-by: Benno Lossin <lossin@kernel.org> Link: https://patch.msgid.link/20260428-pin-init-sync-v1-2-07f9bd3859fb@garyguo.net Signed-off-by: Gary Guo <gary@garyguo.net>
2026-05-10rust: pin-init: examples: mark as `#[inline]` all `From::from()`s for `Error`Alistair Francis
There was a recent request in kernel [1] to mark as `#[inline]` the simple `From::from()` functions implemented for `Error`. Thus mark all of the existing impl From<...> for Error { fn from(err: ...) -> Self { ... } } functions as `#[inline]`. While in pin-init crate the relevant code is just examples, it nevertheless does not hurt to use good practice for them. Suggested-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/all/8403c8b7a832b5274743816eb77abfa4@garyguo.net/ [1] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Gary Guo <gary@garyguo.net> [ Reworded commit message - Gary ] Link: https://patch.msgid.link/20260428-pin-init-sync-v1-1-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: implement ZeroableOption for NonZero* integer typesHamdan-Khan
Add a macro for implementing `ZeroableOption` for `NonZero*` types. `Option<NonZero*>` now automatically implements `Zeroable` trait by implementing `ZeroableOption` for `NonZero*` types, which serves as a blanket impl. Closes: https://github.com/Rust-for-Linux/pin-init/issues/95 Signed-off-by: Hamdan-Khan <hamdankhan212@gmail.com> Link: https://github.com/Rust-for-Linux/pin-init/commit/74f772641cd9670848fa360f4ebfd20fdb40bf78 [ Fixed a typo in the commit message. - Benno ] Link: https://patch.msgid.link/20260319093542.3756606-5-lossin@kernel.org Signed-off-by: Benno Lossin <lossin@kernel.org>
2026-03-25rust: pin-init: doc: de-clutter documentation with fake-variadicsGary Guo
Currently the doc for `Zeroable` and `ZeroableOption` are filled with the generated impl of tuples and fn pointers. Use the internal "fake_variadics" feature to improve the rendered quality. This makes use of an internal feature, however this is of minimal risk as it's for documentation only, not activated during normal build, gated behind `USE_RUSTC_FEATURES`, and can be removed at any time. This feature is already used by serde and bevy to improve documentation quality. For compilers that cannot use this feature, we still hide most generated impls, and the existence of them are hinted by doc comments on the single non-hidden impl. Signed-off-by: Gary Guo <gary@garyguo.net> Link: https://github.com/Rust-for-Linux/pin-init/commit/530c4eb79a449599e219821f9397f03250cc2aa4 [ Reordered `#[doc]` attributes and safety comments to avoid errors in older versions of clippy. - Benno ] Link: https://patch.msgid.link/20260319093542.3756606-4-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-25rust: pin-init: build: simplify use of nightly featuresGary Guo
We use some features that are already stable in later versions of Rust, but only available as unstable features in older Rust versions that the kernel needs to support. Instead of checking if a feature is already stable, simply enable them and allow the warning if the feature is already stable. This avoids the need of hardcoding whether a feature has been stabilized at a given version. `#[feature(...)]` is used when cfg `USE_RUSTC_FEATURES` is enabled. The build script automatically does this when a nightly compiler is detected or `RUSTC_BOOTSTRAP` is set. Signed-off-by: Gary Guo <gary@garyguo.net> Link: https://github.com/Rust-for-Linux/pin-init/commit/885c5d83d7eb778a796d4a17380a0898b0d0a571 [ Added kernel build system changes to always enable USE_RUSTC_FEATURES. Moved this commit earlier (swapped with the next one) to avoid a build error. - Benno ] Link: https://patch.msgid.link/20260319093542.3756606-2-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-02-22Merge tag 'rust-fixes-7.0' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux Pull rust fixes from Miguel Ojeda: "Toolchain and infrastructure: - Pass '-Zunstable-options' flag required by the future Rust 1.95.0 - Fix 'objtool' warning for Rust 1.84.0 'kernel' crate: - 'irq' module: add missing bound detected by the future Rust 1.95.0 - 'list' module: add missing 'unsafe' blocks and placeholder safety comments to macros (an issue for future callers within the crate) 'pin-init' crate: - Clean Clippy warning that changed behavior in the future Rust 1.95.0" * tag 'rust-fixes-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: rust: list: Add unsafe blocks for container_of and safety comments rust: pin-init: replace clippy `expect` with `allow` rust: irq: add `'static` bounds to irq callbacks objtool/rust: add one more `noreturn` Rust function rust: kbuild: pass `-Zunstable-options` for Rust 1.95.0
2026-02-19rust: pin-init: replace clippy `expect` with `allow`Benno Lossin
`clippy` has changed behavior in [1] (Rust 1.95) where it no longer warns about the `let_and_return` lint when a comment is placed between the let binding and the return expression. Nightly thus fails to build, because the expectation is no longer fulfilled. Thus replace the expectation with an `allow`. [ The errors were: error: this lint expectation is unfulfilled --> rust/pin-init/src/lib.rs:1279:10 | 1279 | #[expect(clippy::let_and_return)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D unfulfilled-lint-expectations` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]` error: this lint expectation is unfulfilled --> rust/pin-init/src/lib.rs:1295:10 | 1295 | #[expect(clippy::let_and_return)] | ^^^^^^^^^^^^^^^^^^^^^^ - Miguel ] Link: https://github.com/rust-lang/rust-clippy/pull/16461 [1] Signed-off-by: Benno Lossin <lossin@kernel.org> Cc: stable@vger.kernel.org # Needed in 6.18.y and later. Link: https://patch.msgid.link/20260215132232.1549861-1-lossin@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-01-17rust: pin-init: Implement `InPlaceWrite<T>` for `&'static mut MaybeUninit<T>`Oleksandr Babak
This feature allows users to use `&'static mut MaybeUninit<T>` as a place to initialize the value. It mirrors an existing implemetation for `Box<MaybeUninit>`, but enables users to use external allocation mechanisms such as `static_cell` [1]. Signed-off-by: Oleksandr Babak <alexanderbabak@proton.me> Link: https://crates.io/crates/static_cell [1] [ Added link to `static_cell` - Benno ] Signed-off-by: Benno Lossin <lossin@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>
2026-01-17rust: pin-init: add `?Sized` bounds to traits in `#[pin_data]` macroBenno Lossin
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>
2026-01-17rust: pin-init: rewrite `#[pin_data]` using `syn`Benno Lossin
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>
2026-01-17rust: pin-init: rewrite the `#[pinned_drop]` attribute macro using `syn`Benno Lossin
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>
2026-01-17rust: pin-init: rewrite `derive(Zeroable)` and `derive(MaybeZeroable)` using ↵Benno Lossin
`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>
2026-01-17rust: pin-init: internal: add utility API for syn error handlingBenno Lossin
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>