]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rust: pin-init: internal: init: handle code blocks early
authorGary Guo <gary@garyguo.net>
Tue, 12 May 2026 12:09:49 +0000 (13:09 +0100)
committerGary Guo <gary@garyguo.net>
Mon, 18 May 2026 11:18:06 +0000 (12:18 +0100)
`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>
rust/pin-init/internal/src/init.rs

index b0bfe44695e19a2cc26e677dd928088683445033..7eda1bcf0f28b779ae51c1d241fd02a75c70fab1 100644 (file)
@@ -231,6 +231,20 @@ fn init_fields(
             cfgs.retain(|attr| attr.path().is_ident("cfg"));
             cfgs
         };
+
+        let ident = match kind {
+            InitializerKind::Value { ident, .. } => ident,
+            InitializerKind::Init { ident, .. } => ident,
+            InitializerKind::Code { block, .. } => {
+                res.extend(quote! {
+                    #(#attrs)*
+                    #[allow(unused_braces)]
+                    #block
+                });
+                continue;
+            }
+        };
+
         let init = match kind {
             InitializerKind::Value { ident, value } => {
                 let mut value_ident = ident.clone();
@@ -283,55 +297,51 @@ fn init_fields(
                     }
                 }
             }
-            InitializerKind::Code { block: value, .. } => quote! {
-                #(#attrs)*
-                #[allow(unused_braces)]
-                #value
-            },
+            InitializerKind::Code { .. } => unreachable!(),
         };
-        res.extend(init);
-        if let Some(ident) = kind.ident() {
-            // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
-            let guard = format_ident!("__{ident}_guard", span = Span::mixed_site());
 
-            // NOTE: The reference is derived from the guard so that it only lives as long as the
-            // guard does and cannot escape the scope. If it's created via `&mut (*#slot).#ident`
-            // like the unaligned field guard, it will become effectively `'static`.
-            let accessor = if pinned {
-                let project_ident = format_ident!("__project_{ident}");
-                quote! {
-                    // SAFETY: the initialization is pinned.
-                    unsafe { #data.#project_ident(#guard.let_binding()) }
-                }
-            } else {
-                quote! {
-                    #guard.let_binding()
-                }
-            };
+        // `mixed_site` ensures that the guard is not accessible to the user-controlled code.
+        let guard = format_ident!("__{ident}_guard", span = Span::mixed_site());
 
-            res.extend(quote! {
-                #(#cfgs)*
-                // Create the drop guard.
-                //
-                // SAFETY:
-                // - `&raw mut (*slot).#ident` is valid.
-                // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned.
-                // - `(*slot).#ident` has been initialized above.
-                // - We only need the ownership to the pointee back when initialization has
-                //   succeeded, where we `forget` the guard.
-                let mut #guard = unsafe {
-                    ::pin_init::__internal::DropGuard::new(
-                        &raw mut (*slot).#ident
-                    )
-                };
+        // NOTE: The reference is derived from the guard so that it only lives as long as the
+        // guard does and cannot escape the scope. If it's created via `&mut (*#slot).#ident`
+        // like the unaligned field guard, it will become effectively `'static`.
+        let accessor = if pinned {
+            let project_ident = format_ident!("__project_{ident}");
+            quote! {
+                // SAFETY: the initialization is pinned.
+                unsafe { #data.#project_ident(#guard.let_binding()) }
+            }
+        } else {
+            quote! {
+                #guard.let_binding()
+            }
+        };
 
-                #(#cfgs)*
-                #[allow(unused_variables)]
-                let #ident = #accessor;
-            });
-            guards.push(guard);
-            guard_attrs.push(cfgs);
-        }
+        res.extend(quote! {
+            #init
+
+            #(#cfgs)*
+            // Create the drop guard.
+            //
+            // SAFETY:
+            // - `&raw mut (*slot).#ident` is valid.
+            // - `make_field_check` checks that `&raw mut (*slot).#ident` is properly aligned.
+            // - `(*slot).#ident` has been initialized above.
+            // - We only need the ownership to the pointee back when initialization has
+            //   succeeded, where we `forget` the guard.
+            let mut #guard = unsafe {
+                ::pin_init::__internal::DropGuard::new(
+                    &raw mut (*slot).#ident
+                )
+            };
+
+            #(#cfgs)*
+            #[allow(unused_variables)]
+            let #ident = #accessor;
+        });
+        guards.push(guard);
+        guard_attrs.push(cfgs);
     }
     quote! {
         #res