mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2)
@ 2026-05-27 17:19 Gary Guo
  2026-05-27 17:19 ` [PATCH 1/8] rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code Gary Guo
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Martin Kletzander,
	Mirko Adzic, Xiaobo Liu

This is a second round of patch syncs from upstream pin-init repo.
The following patches are included.

- Allow other attributes in #[pin_data] structs
  https://github.com/Rust-for-Linux/pin-init/pull/122

- init: allow `nonstandard_style` for generated accessor/value
  https://github.com/Rust-for-Linux/pin-init/pull/127

- docs: fix typos in MaybeZeroable documentation
  https://github.com/Rust-for-Linux/pin-init/pull/154

- Optimize symbol name length of `InitClosure`
  https://github.com/Rust-for-Linux/pin-init/pull/153

- unwind safety fixes
  https://github.com/Rust-for-Linux/pin-init/pull/140

Notably the `nonstandard_style` fix will allow a bunch of `#[allow]`s to be
removed from Nova's codebase.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
Gary Guo (2):
      rust: pin-init: move `InitClosure` out from `__internal`
      rust: pin-init: remove `E` from `InitClosure`

Martin Kletzander (1):
      rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code

Mirko Adzic (4):
      rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`
      rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`
      rust: pin-init: make `[pin_]init_array_from_fn` unwind safe
      rust: pin-init: make `[pin_]chain` unwind safe

Xiaobo Liu (1):
      rust: pin-init: docs: fix typos in MaybeZeroable documentation

 rust/pin-init/internal/src/init.rs     |   4 +-
 rust/pin-init/internal/src/pin_data.rs |  64 ++++++----
 rust/pin-init/src/__internal.rs        |  30 -----
 rust/pin-init/src/lib.rs               | 217 ++++++++++++++++++++++++---------
 4 files changed, 200 insertions(+), 115 deletions(-)
---
base-commit: 6fb5912c92926025a7e205d53feb73c3478c79a1
change-id: 20260527-pin-init-sync-41a0c2c9873c

Best regards,
--  
Gary Guo <gary@garyguo.net>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/8] rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 2/8] rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]` Gary Guo
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Martin Kletzander

From: Martin Kletzander <mkletzan@redhat.com>

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.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
[ Rebased and updated to only include `#[cfg]` instead of both `#[cfg]` and
  `#[doc]`; doc is not needed for the generated hidden items. - Gary ]
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/internal/src/pin_data.rs | 52 ++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 24 deletions(-)

diff --git a/rust/pin-init/internal/src/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
index 2284256a6220..9ca8235ed3d6 100644
--- a/rust/pin-init/internal/src/pin_data.rs
+++ b/rust/pin-init/internal/src/pin_data.rs
@@ -7,7 +7,7 @@
     parse_quote, parse_quote_spanned,
     spanned::Spanned,
     visit_mut::VisitMut,
-    Field, Generics, Ident, Item, PathSegment, Type, TypePath, Visibility, WhereClause,
+    Attribute, Field, Generics, Ident, Item, PathSegment, Type, TypePath, Visibility, WhereClause,
 };
 
 use crate::diagnostics::{DiagCtxt, ErrorGuaranteed};
@@ -38,6 +38,7 @@ fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
 struct FieldInfo<'a> {
     field: &'a Field,
     pinned: bool,
+    cfg_attrs: Vec<&'a Attribute>,
 }
 
 pub(crate) fn pin_data(
@@ -86,9 +87,16 @@ pub(crate) fn pin_data(
             field.attrs.retain(|a| !a.path().is_ident("pin"));
             let pinned = len != field.attrs.len();
 
+            let cfg_attrs = field
+                .attrs
+                .iter()
+                .filter(|a| a.path().is_ident("cfg"))
+                .collect();
+
             FieldInfo {
                 field: &*field,
                 pinned,
+                cfg_attrs,
             }
         })
         .collect();
@@ -171,7 +179,15 @@ fn generate_unpin_impl(
     else {
         unreachable!()
     };
-    let pinned_fields = fields.iter().filter(|f| f.pinned).map(|f| f.field);
+    let pinned_fields = fields.iter().filter(|f| f.pinned).map(|f| {
+        let ident = f.field.ident.as_ref().unwrap();
+        let ty = &f.field.ty;
+        let cfg_attrs = &f.cfg_attrs;
+        quote!(
+            #(#cfg_attrs)*
+            #ident: #ty
+        )
+    });
     quote! {
         // This struct will be used for the unpin analysis. It is needed, because only structurally
         // pinned fields are relevant whether the struct should implement `Unpin`.
@@ -259,27 +275,20 @@ fn generate_projections(
     let (fields_decl, fields_proj): (Vec<_>, Vec<_>) = fields
         .iter()
         .map(|field| {
-            let Field {
-                vis,
-                ident,
-                ty,
-                attrs,
-                ..
-            } = &field.field;
-
-            let mut no_doc_attrs = attrs.clone();
-            no_doc_attrs.retain(|a| !a.path().is_ident("doc"));
+            let Field { vis, ident, ty, .. } = &field.field;
+            let cfg_attrs = &field.cfg_attrs;
+
             let ident = ident
                 .as_ref()
                 .expect("only structs with named fields are supported");
             if field.pinned {
                 (
                     quote!(
-                        #(#attrs)*
+                        #(#cfg_attrs)*
                         #vis #ident: ::core::pin::Pin<&'__pin mut #ty>,
                     ),
                     quote!(
-                        #(#no_doc_attrs)*
+                        #(#cfg_attrs)*
                         // SAFETY: this field is structurally pinned.
                         #ident: unsafe { ::core::pin::Pin::new_unchecked(&mut #this.#ident) },
                     ),
@@ -287,11 +296,11 @@ fn generate_projections(
             } else {
                 (
                     quote!(
-                        #(#attrs)*
+                        #(#cfg_attrs)*
                         #vis #ident: &'__pin mut #ty,
                     ),
                     quote!(
-                        #(#no_doc_attrs)*
+                        #(#cfg_attrs)*
                         #ident: &mut #this.#ident,
                     ),
                 )
@@ -358,13 +367,8 @@ fn generate_the_pin_data(
     let field_accessors = fields
         .iter()
         .map(|f| {
-            let Field {
-                vis,
-                ident,
-                ty,
-                attrs,
-                ..
-            } = f.field;
+            let Field { vis, ident, ty, .. } = f.field;
+            let cfg_attrs = &f.cfg_attrs;
 
             let field_name = ident
                 .as_ref()
@@ -381,7 +385,7 @@ fn generate_the_pin_data(
                 /// - `(*slot).#field_name` is properly aligned.
                 /// - `(*slot).#field_name` points to uninitialized and exclusively accessed
                 ///   memory.
-                #(#attrs)*
+                #(#cfg_attrs)*
                 #[inline(always)]
                 #vis unsafe fn #field_name(
                     self,

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/8] rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
  2026-05-27 17:19 ` [PATCH 1/8] rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 3/8] rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!` Gary Guo
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Mirko Adzic

From: Mirko Adzic <adzicmirko97@gmail.com>

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>
Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/internal/src/pin_data.rs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/rust/pin-init/internal/src/pin_data.rs b/rust/pin-init/internal/src/pin_data.rs
index 9ca8235ed3d6..9fbbd25bcaac 100644
--- a/rust/pin-init/internal/src/pin_data.rs
+++ b/rust/pin-init/internal/src/pin_data.rs
@@ -191,7 +191,10 @@ fn generate_unpin_impl(
     quote! {
         // This struct will be used for the unpin analysis. It is needed, because only structurally
         // pinned fields are relevant whether the struct should implement `Unpin`.
-        #[allow(dead_code)] // The fields below are never used.
+        #[allow(
+            dead_code, // The fields below are never used.
+            non_snake_case // The warning will be emitted on the struct definition.
+        )]
         struct __Unpin #generics_with_pin_lt
         #where_token
             #predicates
@@ -318,7 +321,9 @@ fn generate_projections(
     let docs = format!(" Pin-projections of [`{ident}`]");
     quote! {
         #[doc = #docs]
-        #[allow(dead_code)]
+        // Allow `non_snake_case` since the same warning will be emitted on
+        // the struct definition.
+        #[allow(dead_code, non_snake_case)]
         #[doc(hidden)]
         #vis struct #projection #generics_with_pin_lt
             #whr
@@ -386,6 +391,9 @@ fn generate_the_pin_data(
                 /// - `(*slot).#field_name` points to uninitialized and exclusively accessed
                 ///   memory.
                 #(#cfg_attrs)*
+                // Allow `non_snake_case` since the same warning will be emitted on
+                // the struct definition.
+                #[allow(non_snake_case)]
                 #[inline(always)]
                 #vis unsafe fn #field_name(
                     self,

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/8] rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
  2026-05-27 17:19 ` [PATCH 1/8] rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code Gary Guo
  2026-05-27 17:19 ` [PATCH 2/8] rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]` Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 4/8] rust: pin-init: docs: fix typos in MaybeZeroable documentation Gary Guo
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Mirko Adzic

From: Mirko Adzic <adzicmirko97@gmail.com>

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 ]
Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/internal/src/init.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/rust/pin-init/internal/src/init.rs b/rust/pin-init/internal/src/init.rs
index 699b105570a5..041a84593730 100644
--- a/rust/pin-init/internal/src/init.rs
+++ b/rust/pin-init/internal/src/init.rs
@@ -296,7 +296,9 @@ fn init_fields(
             #init
 
             #(#cfgs)*
-            #[allow(unused_variables)]
+            // Allow `non_snake_case` since the same warning is going to be reported for the struct
+            // field.
+            #[allow(unused_variables, non_snake_case)]
             let #ident = #guard.let_binding();
         });
 

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/8] rust: pin-init: docs: fix typos in MaybeZeroable documentation
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
                   ` (2 preceding siblings ...)
  2026-05-27 17:19 ` [PATCH 3/8] rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!` Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 5/8] rust: pin-init: move `InitClosure` out from `__internal` Gary Guo
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Xiaobo Liu

From: Xiaobo Liu <cppcoffee@gmail.com>

Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/src/lib.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index c9e2cbe27915..84099474324e 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -431,7 +431,7 @@
 /// ```
 /// use pin_init::MaybeZeroable;
 ///
-/// // implmements `Zeroable`
+/// // implements `Zeroable`
 /// #[derive(MaybeZeroable)]
 /// pub struct DriverData {
 ///     pub(crate) id: i64,
@@ -439,7 +439,7 @@
 ///     len: usize,
 /// }
 ///
-/// // does not implmement `Zeroable`
+/// // does not implement `Zeroable`
 /// #[derive(MaybeZeroable)]
 /// pub struct DriverData2 {
 ///     pub(crate) id: i64,

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/8] rust: pin-init: move `InitClosure` out from `__internal`
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
                   ` (3 preceding siblings ...)
  2026-05-27 17:19 ` [PATCH 4/8] rust: pin-init: docs: fix typos in MaybeZeroable documentation Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 6/8] rust: pin-init: remove `E` from `InitClosure` Gary Guo
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, 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.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/src/__internal.rs | 30 ------------------------------
 rust/pin-init/src/lib.rs        | 34 ++++++++++++++++++++++++++++++++--
 2 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/rust/pin-init/src/__internal.rs b/rust/pin-init/src/__internal.rs
index 540add6cee8a..56dc655e323e 100644
--- a/rust/pin-init/src/__internal.rs
+++ b/rust/pin-init/src/__internal.rs
@@ -58,36 +58,6 @@ pub const fn new() -> Self {
     }
 }
 
-/// Module-internal type implementing `PinInit` and `Init`.
-///
-/// It is unsafe to create this type, since the closure needs to fulfill the same safety
-/// requirement as the `__pinned_init`/`__init` functions.
-pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) PhantomInvariant<(E, T)>);
-
-// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
-// `__init` invariants.
-unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E>
-where
-    F: FnOnce(*mut T) -> Result<(), E>,
-{
-    #[inline]
-    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
-        (self.0)(slot)
-    }
-}
-
-// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
-// `__pinned_init` invariants.
-unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E>
-where
-    F: FnOnce(*mut T) -> Result<(), E>,
-{
-    #[inline]
-    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
-        (self.0)(slot)
-    }
-}
-
 /// Token type to signify successful initialization.
 ///
 /// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this
diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 84099474324e..9732af32795c 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -1092,6 +1092,36 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
     }
 }
 
+/// Implement `PinInit` and `Init` for closures.
+///
+/// It is unsafe to create this type, since the closure needs to fulfill the same safety
+/// requirement as the `__pinned_init`/`__init` functions.
+struct InitClosure<F, T: ?Sized, E>(F, __internal::PhantomInvariant<(E, T)>);
+
+// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
+// `__init` invariants.
+unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E>
+where
+    F: FnOnce(*mut T) -> Result<(), E>,
+{
+    #[inline]
+    unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
+        (self.0)(slot)
+    }
+}
+
+// SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
+// `__pinned_init` invariants.
+unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E>
+where
+    F: FnOnce(*mut T) -> Result<(), E>,
+{
+    #[inline]
+    unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
+        (self.0)(slot)
+    }
+}
+
 /// Creates a new [`PinInit<T, E>`] from the given closure.
 ///
 /// # Safety
@@ -1108,7 +1138,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 pub const unsafe fn pin_init_from_closure<T: ?Sized, E>(
     f: impl FnOnce(*mut T) -> Result<(), E>,
 ) -> impl PinInit<T, E> {
-    __internal::InitClosure(f, __internal::PhantomInvariant::new())
+    InitClosure(f, __internal::PhantomInvariant::new())
 }
 
 /// Creates a new [`Init<T, E>`] from the given closure.
@@ -1127,7 +1157,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 pub const unsafe fn init_from_closure<T: ?Sized, E>(
     f: impl FnOnce(*mut T) -> Result<(), E>,
 ) -> impl Init<T, E> {
-    __internal::InitClosure(f, __internal::PhantomInvariant::new())
+    InitClosure(f, __internal::PhantomInvariant::new())
 }
 
 /// Changes the to be initialized type.

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/8] rust: pin-init: remove `E` from `InitClosure`
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
                   ` (4 preceding siblings ...)
  2026-05-27 17:19 ` [PATCH 5/8] rust: pin-init: move `InitClosure` out from `__internal` Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 7/8] rust: pin-init: make `[pin_]init_array_from_fn` unwind safe Gary Guo
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, 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)`.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/src/lib.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 9732af32795c..fd40c8f244a1 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -1096,11 +1096,11 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 ///
 /// It is unsafe to create this type, since the closure needs to fulfill the same safety
 /// requirement as the `__pinned_init`/`__init` functions.
-struct InitClosure<F, T: ?Sized, E>(F, __internal::PhantomInvariant<(E, T)>);
+struct InitClosure<F, T: ?Sized>(F, __internal::PhantomInvariant<T>);
 
 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
 // `__init` invariants.
-unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E>
+unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T>
 where
     F: FnOnce(*mut T) -> Result<(), E>,
 {
@@ -1112,7 +1112,7 @@ unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
 
 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the
 // `__pinned_init` invariants.
-unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E>
+unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T>
 where
     F: FnOnce(*mut T) -> Result<(), E>,
 {

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 7/8] rust: pin-init: make `[pin_]init_array_from_fn` unwind safe
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
                   ` (5 preceding siblings ...)
  2026-05-27 17:19 ` [PATCH 6/8] rust: pin-init: remove `E` from `InitClosure` Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-27 17:19 ` [PATCH 8/8] rust: pin-init: make `[pin_]chain` " Gary Guo
  2026-05-29 21:04 ` [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Mirko Adzic

From: Mirko Adzic <adzicmirko97@gmail.com>

Adds a guard type that safely initializes an array by running an
initializer on each element, keeping track of the number of initialized
elements. In the case of a panic or error in the per-element initializer,
the guard drops the already-initialized portion of the array; nothing is
dropped on success.

The previous code only ran cleanup on the explicit error path. If the per-
element initializer panicked partway through, the elements already written
into the array would be leaked: their `Drop` impls would never run.

Reported-by: Gary Guo <gary@garyguo.net>
Closes: https://github.com/Rust-for-Linux/pin-init/issues/136
Suggested-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com>
[ Add `#[inline]` to `ArrayInit::drop` - Gary ]
Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/src/lib.rs | 157 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 115 insertions(+), 42 deletions(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index fd40c8f244a1..1fdf9c2366ff 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -1193,6 +1193,117 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
     unsafe { init_from_closure(|_| Ok(())) }
 }
 
+/// Allows safe (pinned and non-pinned) initialization of an array.
+///
+/// Drops the already initialized elements of the array if an error or panic occurs
+/// partway through the initialization process.
+///
+/// # Invariants
+///
+/// If `ptr` is not null:
+/// - `ptr[..num_init]` contains initialized elements of type `T`
+/// - `ptr[num_init..N]` (where N is the size of the array) contains uninitialized memory
+struct ArrayInit<T, F> {
+    /// A pointer to the first element of the array.
+    ptr: *mut T,
+    /// The number of initialized elements in the array.
+    num_init: usize,
+    /// Initialization function factory.
+    make_init: F,
+}
+
+impl<T, F> ArrayInit<T, F> {
+    #[inline]
+    fn new(make_init: F) -> Self {
+        Self {
+            // INVARIANT: `ptr` is null prior to any initialization.
+            ptr: core::ptr::null_mut(),
+            num_init: 0,
+            make_init,
+        }
+    }
+}
+
+/// SAFETY: On success, all `N` elements of the array have been initialized through
+/// `I: Init`. On error or panic, the elements that have been initialized so far are
+/// dropped, thus leaving the array uninitialized and ready to deallocate. The `Init`
+/// implementation executes the same code as that of `PinInit`.
+unsafe impl<T, F, I, E, const N: usize> Init<[T; N], E> for ArrayInit<T, F>
+where
+    F: FnMut(usize) -> I,
+    I: Init<T, E>,
+{
+    unsafe fn __init(mut self, slot: *mut [T; N]) -> Result<(), E> {
+        debug_assert!(!slot.is_null());
+        // INVARIANT: `self.ptr` is non-null once initialization starts.
+        self.ptr = slot.cast::<T>();
+        for i in 0..N {
+            // INVARIANT: Elements `self.ptr[..self.num_init]` have been initialized
+            // thus far. This hold true for every `self.num_init = i`.
+            self.num_init = i;
+            let init = (self.make_init)(i);
+            // SAFETY: `self.ptr.add(i)` is in bounds.
+            let ptr = unsafe { self.ptr.add(i) };
+            // SAFETY: The pointer is derived from `slot` with a valid offset. It is
+            // thus valid for writes and points uninitialized memory.
+            unsafe { init.__init(ptr) }?;
+        }
+        // INVARIANT: `self.ptr` is null after the array is initialized.
+        self.ptr = core::ptr::null_mut();
+        Ok(())
+    }
+}
+
+/// SAFETY: On success, all `N` elements of the array have been initialized through
+/// `I`. Since `I: PinInit` guarantees that the pinning invariants of `T` are upheld,
+/// the guarantees of `[T; N]` are also upheld. On error or panic, the elements that
+/// have been initialized so far are dropped, thus leaving the array uninitialized
+/// and ready to deallocate.
+unsafe impl<T, F, I, E, const N: usize> PinInit<[T; N], E> for ArrayInit<T, F>
+where
+    F: FnMut(usize) -> I,
+    I: PinInit<T, E>,
+{
+    unsafe fn __pinned_init(mut self, slot: *mut [T; N]) -> Result<(), E> {
+        debug_assert!(!slot.is_null());
+        // INVARIANT: `self.ptr` is non-null once initialization starts.
+        self.ptr = slot.cast::<T>();
+        for i in 0..N {
+            // INVARIANT: Elements `self.ptr[..self.num_init]` have been initialized
+            // thus far. This hold true for every `self.num_init = i`.
+            self.num_init = i;
+            let init = (self.make_init)(i);
+            // SAFETY: `self.ptr.add(i)` is in bounds.
+            let ptr = unsafe { self.ptr.add(i) };
+            // SAFETY: The pointer is derived from `slot` with a valid offset. It is
+            // thus valid for writes and points uninitialized memory.
+            unsafe { init.__pinned_init(ptr) }?;
+        }
+        // INVARIANT: `self.ptr` is null after the array is initialized.
+        self.ptr = core::ptr::null_mut();
+        Ok(())
+    }
+}
+
+impl<T, F> Drop for ArrayInit<T, F> {
+    #[inline]
+    fn drop(&mut self) {
+        if self.ptr.is_null() {
+            // Since `self.ptr` is null - either no initialization has been attempted
+            // or the array was successfully initialized, per type invariant. Nothing
+            // to drop.
+            return;
+        }
+
+        // SAFETY: Since `self.ptr` is not null - the initialization has failed
+        // partway. Drop `self.ptr[..self.num_init]` which are initialized per
+        // type invariant.
+        unsafe {
+            core::ptr::drop_in_place(core::ptr::slice_from_raw_parts_mut(self.ptr, self.num_init))
+        };
+    }
+}
+
 /// Initializes an array by initializing each element via the provided initializer.
 ///
 /// # Examples
@@ -1204,31 +1315,12 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
 /// assert_eq!(array.len(), 1_000);
 /// ```
 pub fn init_array_from_fn<I, const N: usize, T, E>(
-    mut make_init: impl FnMut(usize) -> I,
+    make_init: impl FnMut(usize) -> I,
 ) -> impl Init<[T; N], E>
 where
     I: Init<T, E>,
 {
-    let init = move |slot: *mut [T; N]| {
-        let slot = slot.cast::<T>();
-        for i in 0..N {
-            let init = make_init(i);
-            // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
-            let ptr = unsafe { slot.add(i) };
-            // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
-            // requirements.
-            if let Err(e) = unsafe { init.__init(ptr) } {
-                // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
-                // `Err` below, `slot` will be considered uninitialized memory.
-                unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
-                return Err(e);
-            }
-        }
-        Ok(())
-    };
-    // SAFETY: The initializer above initializes every element of the array. On failure it drops
-    // any initialized elements and returns `Err`.
-    unsafe { init_from_closure(init) }
+    ArrayInit::new(make_init)
 }
 
 /// Initializes an array by initializing each element via the provided initializer.
@@ -1247,31 +1339,12 @@ pub fn init_array_from_fn<I, const N: usize, T, E>(
 /// assert_eq!(array.len(), 1_000);
 /// ```
 pub fn pin_init_array_from_fn<I, const N: usize, T, E>(
-    mut make_init: impl FnMut(usize) -> I,
+    make_init: impl FnMut(usize) -> I,
 ) -> impl PinInit<[T; N], E>
 where
     I: PinInit<T, E>,
 {
-    let init = move |slot: *mut [T; N]| {
-        let slot = slot.cast::<T>();
-        for i in 0..N {
-            let init = make_init(i);
-            // SAFETY: Since 0 <= `i` < N, it is still in bounds of `[T; N]`.
-            let ptr = unsafe { slot.add(i) };
-            // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
-            // requirements.
-            if let Err(e) = unsafe { init.__pinned_init(ptr) } {
-                // SAFETY: The loop has initialized the elements `slot[0..i]` and since we return
-                // `Err` below, `slot` will be considered uninitialized memory.
-                unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(slot, i)) };
-                return Err(e);
-            }
-        }
-        Ok(())
-    };
-    // SAFETY: The initializer above initializes every element of the array. On failure it drops
-    // any initialized elements and returns `Err`.
-    unsafe { pin_init_from_closure(init) }
+    ArrayInit::new(make_init)
 }
 
 /// Construct an initializer in a closure and run it.

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 8/8] rust: pin-init: make `[pin_]chain` unwind safe
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
                   ` (6 preceding siblings ...)
  2026-05-27 17:19 ` [PATCH 7/8] rust: pin-init: make `[pin_]init_array_from_fn` unwind safe Gary Guo
@ 2026-05-27 17:19 ` Gary Guo
  2026-05-29 21:04 ` [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-27 17:19 UTC (permalink / raw)
  To: Benno Lossin, Miguel Ojeda, Boqun Feng, Björn Roy Baron,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Gary Guo, Mirko Adzic

From: Mirko Adzic <adzicmirko97@gmail.com>

Adds a drop guard before the call to the chained closure so that the
value initialized by the first stage is dropped if the closure errors
or panics; `mem::forget` the guard on success.

The previous code only ran cleanup on the explicit error path, leaking
the first-stage value if the chained closure panicked.

Reported-by: Gary Guo <gary@garyguo.net>
Closes: https://github.com/Rust-for-Linux/pin-init/issues/136
Suggested-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Mirko Adzic <adzicmirko97@gmail.com>
Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/pin-init/src/lib.rs | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/rust/pin-init/src/lib.rs b/rust/pin-init/src/lib.rs
index 1fdf9c2366ff..b5af88c9e48b 100644
--- a/rust/pin-init/src/lib.rs
+++ b/rust/pin-init/src/lib.rs
@@ -965,13 +965,11 @@ unsafe impl<T: ?Sized, E, I, F> PinInit<T, E> for ChainPinInit<I, F, T, E>
 {
     unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
         // SAFETY: All requirements fulfilled since this function is `__pinned_init`.
-        unsafe { self.0.__pinned_init(slot)? };
-        // SAFETY: The above call initialized `slot` and we still have unique access.
-        let val = unsafe { &mut *slot };
-        // SAFETY: `slot` is considered pinned.
-        let val = unsafe { Pin::new_unchecked(val) };
-        // SAFETY: `slot` was initialized above.
-        (self.1)(val).inspect_err(|_| unsafe { core::ptr::drop_in_place(slot) })
+        let mut guard =
+            unsafe { __internal::Slot::<__internal::Pinned, _>::new(slot) }.init(self.0)?;
+        (self.1)(guard.let_binding())?;
+        core::mem::forget(guard);
+        Ok(())
     }
 }
 
@@ -1072,11 +1070,11 @@ unsafe impl<T: ?Sized, E, I, F> Init<T, E> for ChainInit<I, F, T, E>
 {
     unsafe fn __init(self, slot: *mut T) -> Result<(), E> {
         // SAFETY: All requirements fulfilled since this function is `__init`.
-        unsafe { self.0.__pinned_init(slot)? };
-        // SAFETY: The above call initialized `slot` and we still have unique access.
-        (self.1)(unsafe { &mut *slot }).inspect_err(|_|
-            // SAFETY: `slot` was initialized above.
-            unsafe { core::ptr::drop_in_place(slot) })
+        let mut guard =
+            unsafe { __internal::Slot::<__internal::Unpinned, _>::new(slot) }.init(self.0)?;
+        (self.1)(guard.let_binding())?;
+        core::mem::forget(guard);
+        Ok(())
     }
 }
 

-- 
2.54.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2)
  2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
                   ` (7 preceding siblings ...)
  2026-05-27 17:19 ` [PATCH 8/8] rust: pin-init: make `[pin_]chain` " Gary Guo
@ 2026-05-29 21:04 ` Gary Guo
  8 siblings, 0 replies; 10+ messages in thread
From: Gary Guo @ 2026-05-29 21:04 UTC (permalink / raw)
  To: Gary Guo, Benno Lossin, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich
  Cc: rust-for-linux, linux-kernel, Martin Kletzander, Mirko Adzic, Xiaobo Liu

On Wed May 27, 2026 at 6:19 PM BST, Gary Guo wrote:
> This is a second round of patch syncs from upstream pin-init repo.
> The following patches are included.
>
> - Allow other attributes in #[pin_data] structs
>   https://github.com/Rust-for-Linux/pin-init/pull/122
>
> - init: allow `nonstandard_style` for generated accessor/value
>   https://github.com/Rust-for-Linux/pin-init/pull/127
>
> - docs: fix typos in MaybeZeroable documentation
>   https://github.com/Rust-for-Linux/pin-init/pull/154
>
> - Optimize symbol name length of `InitClosure`
>   https://github.com/Rust-for-Linux/pin-init/pull/153
>
> - unwind safety fixes
>   https://github.com/Rust-for-Linux/pin-init/pull/140
>
> Notably the `nonstandard_style` fix will allow a bunch of `#[allow]`s to be
> removed from Nova's codebase.
>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> ---
> Gary Guo (2):
>       rust: pin-init: move `InitClosure` out from `__internal`
>       rust: pin-init: remove `E` from `InitClosure`
>
> Martin Kletzander (1):
>       rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code
>
> Mirko Adzic (2):
>       rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]`
>       rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!`
>
> Xiaobo Liu (1):
>       rust: pin-init: docs: fix typos in MaybeZeroable documentation

I've applied the above patches to pin-init-next. The two patches below are not
applied and would need a respin.

> Mirko Adzic (2):
>       rust: pin-init: make `[pin_]init_array_from_fn` unwind safe

This one has an issue reported by a Sashiko.

>       rust: pin-init: make `[pin_]chain` unwind safe

And this one triggers a false positive lint in Clippy 1.85, which appears to be
fixed in 1.96. I didn't bother bisecting.

Best,
Gary

>
>  rust/pin-init/internal/src/init.rs     |   4 +-
>  rust/pin-init/internal/src/pin_data.rs |  64 ++++++----
>  rust/pin-init/src/__internal.rs        |  30 -----
>  rust/pin-init/src/lib.rs               | 217 ++++++++++++++++++++++++---------
>  4 files changed, 200 insertions(+), 115 deletions(-)

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-05-29 21:04 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-27 17:19 [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo
2026-05-27 17:19 ` [PATCH 1/8] rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code Gary Guo
2026-05-27 17:19 ` [PATCH 2/8] rust: pin-init: internal: suppress `non_snake_case` lint in `#[pin_data]` Gary Guo
2026-05-27 17:19 ` [PATCH 3/8] rust: pin-init: internal: suppress `non_snake_case` lint in `[pin_]init!` Gary Guo
2026-05-27 17:19 ` [PATCH 4/8] rust: pin-init: docs: fix typos in MaybeZeroable documentation Gary Guo
2026-05-27 17:19 ` [PATCH 5/8] rust: pin-init: move `InitClosure` out from `__internal` Gary Guo
2026-05-27 17:19 ` [PATCH 6/8] rust: pin-init: remove `E` from `InitClosure` Gary Guo
2026-05-27 17:19 ` [PATCH 7/8] rust: pin-init: make `[pin_]init_array_from_fn` unwind safe Gary Guo
2026-05-27 17:19 ` [PATCH 8/8] rust: pin-init: make `[pin_]chain` " Gary Guo
2026-05-29 21:04 ` [PATCH 0/8] rust: pin-init upstream sync for v7.2 (round 2) Gary Guo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®