]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rust: pin-init: internal: project using full slot
authorGary Guo <gary@garyguo.net>
Tue, 12 May 2026 12:09:53 +0000 (13:09 +0100)
committerGary Guo <gary@garyguo.net>
Mon, 18 May 2026 11:21:28 +0000 (12:21 +0100)
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>
rust/pin-init/internal/src/init.rs
rust/pin-init/internal/src/pin_data.rs
rust/pin-init/src/lib.rs

index e6f5ea06f91bcf0b14e74b645930241ddb397de3..699b105570a54fb9e46fcb6518414d270538d326 100644 (file)
@@ -245,12 +245,11 @@ fn init_fields(
         let slot = if pinned {
             quote! {
                 // SAFETY:
-                // - `&raw mut (*slot).#ident` points to the `#ident` field of `slot`.
-                // - `&raw mut (*slot).#ident` is valid.
+                // - `slot` is valid and properly aligned.
                 // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned.
                 // - `make_field_check` prevents `#ident` from being used twice, therefore
                 //   `(*slot).#ident` is exclusively accessed and has not been initialized.
-                (unsafe { #data.#ident(&raw mut (*#slot).#ident) })
+                (unsafe { #data.#ident(#slot) })
             }
         } else {
             quote! {
index 926f84a014c613991fad3a2a1ed5ca0bd9dc47a6..2284256a62207279e30d00c2b52099eba4ef0387 100644 (file)
@@ -377,21 +377,21 @@ fn generate_the_pin_data(
             quote! {
                 /// # Safety
                 ///
-                /// - `slot` points to a `#field_name` field of a pinned struct that this
-                ///   `__ThePinData` describes.
-                /// - `slot` is a valid, properly aligned and points to uninitialized and
-                ///   exclusively accessed memory.
+                /// - `slot` is valid and properly aligned.
+                /// - `(*slot).#field_name` is properly aligned.
+                /// - `(*slot).#field_name` points to uninitialized and exclusively accessed
+                ///   memory.
                 #(#attrs)*
                 #[inline(always)]
                 #vis unsafe fn #field_name(
                     self,
-                    slot: *mut #ty,
+                    slot: *mut #struct_name #ty_generics,
                 ) -> ::pin_init::__internal::Slot<::pin_init::__internal::#pin_marker, #ty> {
                     // SAFETY:
                     // - If `#pin_marker` is `Pinned`, the corresponding field is structurally
                     //   pinned.
                     // - Other safety requirements follows the safety requirement.
-                    unsafe { ::pin_init::__internal::Slot::new(slot) }
+                    unsafe { ::pin_init::__internal::Slot::new(&raw mut (*slot).#field_name) }
                 }
             }
         })
index e891d65cc469a792499ff41dc4f73fbad8d58fd7..c9e2cbe279157dbae3a5da1db2f37886c53010a5 100644 (file)
@@ -868,7 +868,7 @@ pub use pin_init_internal::init;
 macro_rules! assert_pinned {
     ($ty:ty, $field:ident, $field_ty:ty, inline) => {
         // SAFETY: This code is unreachable.
-        let _ = move |ptr: *mut $field_ty| unsafe {
+        let _ = move |ptr: *mut $ty| unsafe {
             let data = <$ty as $crate::__internal::HasPinData>::__pin_data();
             _ = data
                 .$field(ptr)