]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
rust: pin-init: internal: pin_data: filter non-`#[cfg]` attr in generated code
authorMartin Kletzander <mkletzan@redhat.com>
Wed, 27 May 2026 17:19:52 +0000 (18:19 +0100)
committerGary Guo <gary@garyguo.net>
Fri, 29 May 2026 20:34:53 +0000 (21:34 +0100)
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>
rust/pin-init/internal/src/pin_data.rs

index 2284256a62207279e30d00c2b52099eba4ef0387..9ca8235ed3d6ade5647cf2e611a0c3c0ed7ab319 100644 (file)
@@ -7,7 +7,7 @@ use syn::{
     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 @@ impl Parse for Args {
 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,