| Age | Commit message (Collapse) | Author |
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
`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>
|
|
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>
|
|
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>
|
|
`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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
`#[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>
|
|
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>
|
|
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>
|
|
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>
|
|
`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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
`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>
|
|
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>
|
|
workarounds
`syn` makes parsing Rust from proc-macros a lot simpler. `pin-init` has
not used `syn` up until now, because the we did not support it. That
changed in commit 54e3eae85562 ("Merge patch series "`syn` support""),
so we can finally utilize the added ergonomics of parsing proc-macro
input with `syn`.
Previously we only had the `proc-macro` library available, whereas the
user-space version also used `proc-macro2` and `quote`. Now both are
available, so remove the workarounds.
Due to these changes, clippy emits warnings about unnecessary
`.to_string()` as `proc-macro2` provides an additional `PartialEq` impl
on `Ident`, so the warnings are fixed.
[ Adjusted wording from upstream version and added build system changes
for the kernel - Benno ]
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Benno Lossin <lossin@kernel.org>
|
|
rust-next
Pull pin-init updates from Benno Lossin:
"Added:
- 'Wrapper<T>' trait for creating pin-initializers for wrapper
structs with a structurally pinned value such as 'UnsafeCell<T>' or
'MaybeUninit<T>'.
- 'MaybeZeroable' derive macro to try to derive 'Zeroable', but not
error if not all fields implement it. This is needed to derive
'Zeroable' for all bindgen-generated structs.
- 'unsafe fn cast_[pin_]init()' functions to unsafely change the
initialized type of an initializer. These are utilized by the
'Wrapper<T>' implementations.
Changed:
- Added support for visibility in 'Zeroable' derive macro.
- Added support for 'union's in 'Zeroable' derive macro.
Upstream dev news:
- The CI has been streamlined & some bugs with it have been fixed. I
also added new workflows to check if the user-space version and the
one in the kernel tree have diverged.
- I also started to use the issues [1] tab to keep track of any
problems or unexpected/unwanted things. This should help folks
report and diagnose issues w.r.t. 'pin-init' better.
[1] https://github.com/rust-for-linux/pin-init/issues"
* tag 'pin-init-v6.16' of https://github.com/Rust-for-Linux/linux:
rust: pin-init: improve documentation for `Zeroable` derive macros
rust: pin-init: fix typos
rust: pin-init: add `MaybeZeroable` derive macro
rust: pin-init: allow `Zeroable` derive macro to also be applied to unions
rust: pin-init: allow `pub` fields in `derive(Zeroable)`
rust: pin-init: Update the structural pinning link in readme.
rust: pin-init: Update Changelog and Readme
rust: pin-init: Implement `Wrapper` for `UnsafePinned` behind feature flag.
rust: pin-init: Add the `Wrapper` trait.
rust: pin-init: add `cast_[pin_]init` functions to change the initialized type
rust: pin-init: examples: use `allow` instead of `expect`
rust: pin-init: examples: conditionally enable `feature(lint_reasons)`
rust: pin-init: internal: skip rustfmt formatting of kernel-only module
rust: pin-init: synchronize README.md
|
|
Starting with Rust 1.88.0 (expected 2025-06-26) [1], `rustc` may move
back the `uninlined_format_args` to `style` from `pedantic` (it was
there waiting for rust-analyzer suppotr), and thus we will start to see
lints like:
warning: variables can be used directly in the `format!` string
--> rust/macros/kunit.rs:105:37
|
105 | let kunit_wrapper_fn_name = format!("kunit_rust_wrapper_{}", test);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
help: change this to
|
105 - let kunit_wrapper_fn_name = format!("kunit_rust_wrapper_{}", test);
105 + let kunit_wrapper_fn_name = format!("kunit_rust_wrapper_{test}");
There is even a case that is a pure removal:
warning: variables can be used directly in the `format!` string
--> rust/macros/module.rs:51:13
|
51 | format!("{field}={content}\0", field = field, content = content)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
help: change this to
|
51 - format!("{field}={content}\0", field = field, content = content)
51 + format!("{field}={content}\0")
The lints all seem like nice cleanups, thus just apply them.
We may want to disable `allow-mixed-uninlined-format-args` in the future.
Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Link: https://github.com/rust-lang/rust-clippy/pull/14160 [1]
Acked-by: Benno Lossin <lossin@kernel.org>
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250502140237.1659624-6-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
|
|
This derive macro implements `Zeroable` for structs & unions precisely
if all fields also implement `Zeroable` and does nothing otherwise. The
plain `Zeroable` derive macro instead errors when it cannot derive
`Zeroable` safely. The `MaybeZeroable` derive macro is useful in cases
where manual checking is infeasible such as with the bindings crate.
Move the zeroable generics parsing into a standalone function in order
to avoid code duplication between the two derive macros.
Link: https://github.com/Rust-for-Linux/pin-init/pull/42/commits/1165cdad1a391b923efaf30cf76bc61e38da022e
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
|
|
The `quote` module only is available in the kernel and thus running
`cargo fmt` or `rustfmt internal/src/lib.rs` in the user-space
repository [1] results in:
error: couldn't read `~/pin-init/internal/src/../../../macros/quote.rs`: No such file or directory (os error 2)
--> ~/pin-init/internal/src/lib.rs:25:1
|
25 | mod quote;
| ^^^^^^^^^^
Error writing files: failed to resolve mod `quote`: ~/pin-init/internal/src/../../../macros/quote.rs does not exist
Thus mark it with `rustfmt::skip` when compiling without kernel support.
Link: https://github.com/Rust-for-Linux/pin-init [1]
Link: https://github.com/Rust-for-Linux/pin-init/pull/33/commits/a6caf1945e51da38761aab4dffa56e63e2baa218
Link: https://lore.kernel.org/all/20250414195928.129040-2-benno.lossin@proton.me
Reviewed-by: Christian Schrefl <chrisi.schrefl@gmail.com>
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
|
|
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>
|
|
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>
|
|
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>
|
|
Add infrastructure for moving the initialization API to its own crate.
Covers all make targets such as `rust-analyzer` and `rustdoc`. The tests
of pin-init are not added to `rusttest`, as they are already tested in
the user-space repository [1].
Link: https://github.com/Rust-for-Linux/pin-init [1]
Co-developed-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250308110339.2997091-15-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
|
|
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>
|
|
In preparation of splitting off the pin-init crate from the kernel
crate, move all pin-init API code (including proc-macros) into
`rust/pin-init`.
Moved modules have their import path adjusted via the `#[path = "..."]`
attribute. This allows the files to still be imported in the kernel
crate even though the files are in different directories.
Code that is moved out of files (but the file itself stays where it is)
is imported via the `include!` macro. This also allows the code to be
moved while still being part of the kernel crate.
Note that this commit moves the generics parsing code out of the GPL-2.0
file `rust/macros/helpers.rs` into the Apache-2.0 OR MIT file
`rust/pin_init/internal/src/helpers.rs`. I am the sole author of that
code and it already is available with that license at [1].
The same is true for the entry-points of the proc-macros `pin_data`,
`pinned_drop` and `derive_zeroable` in `rust/macros/lib.rs` that are
moved to `rust/pin_data/internal/src/lib.rs`. Although there are some
smaller patches that fix the doctests.
Link: https://github.com/Rust-for-Linux/pinned-init [1]
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Fiona Behrens <me@kloenk.dev>
Tested-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250308110339.2997091-3-benno.lossin@proton.me
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
|