]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rust: macros: support `#[cfg]` properly in `#[vtable]` macro.
authorGary Guo <gary@garyguo.net>
Tue, 13 Jan 2026 17:05:21 +0000 (17:05 +0000)
committerMiguel Ojeda <ojeda@kernel.org>
Wed, 28 Jan 2026 12:44:17 +0000 (13:44 +0100)
Currently, we generate `HAS_` constants as long as the definition exists in
the source, regardless if it is cfg-ed out or not.

Currently, uses of `#[cfg]` present in both trait and impl, so it is not a
problem; however if only the impl side uses `#[cfg]` then `HAS_` constants
will incorrectly be true while it shouldnt't.

With `syn` support, we can now implement `#[cfg]` handling properly by
propagating the `#[cfg]` attributes to the constants.

Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20260113170529.2240744-1-gary@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
rust/macros/helpers.rs
rust/macros/vtable.rs

index adfa60d8f42d8fb0e3ca4276bb8a621d8af7c3db..37ef6a6f2c851ecfe9e83b62c7b6f497a3ad22dd 100644 (file)
@@ -7,6 +7,7 @@ use syn::{
         Parse,
         ParseStream, //
     },
+    Attribute,
     Error,
     LitStr,
     Result, //
@@ -53,3 +54,8 @@ pub(crate) fn file() -> String {
         proc_macro::Span::call_site().file()
     }
 }
+
+/// Obtain all `#[cfg]` attributes.
+pub(crate) fn gather_cfg_attrs(attr: &[Attribute]) -> impl Iterator<Item = &Attribute> + '_ {
+    attr.iter().filter(|a| a.path().is_ident("cfg"))
+}
index 72ae0a1816a045d3f598a5b81418eb7dd974b691..c6510b0c4ea1d673687d3ff0f4c740eeee6e5401 100644 (file)
@@ -23,7 +23,6 @@ use syn::{
 
 fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
     let mut gen_items = Vec::new();
-    let mut gen_consts = HashSet::new();
 
     gen_items.push(parse_quote! {
          /// A marker to prevent implementors from forgetting to use [`#[vtable]`](vtable)
@@ -38,22 +37,17 @@ fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
                 &format!("HAS_{}", name.to_string().to_uppercase()),
                 name.span(),
             );
-            // Skip if it's declared already -- this can happen if `#[cfg]` is used to selectively
-            // define functions.
-            // FIXME: `#[cfg]` should be copied and propagated to the generated consts.
-            if gen_consts.contains(&gen_const_name) {
-                continue;
-            }
 
             // We don't know on the implementation-site whether a method is required or provided
             // so we have to generate a const for all methods.
+            let cfg_attrs = crate::helpers::gather_cfg_attrs(&fn_item.attrs);
             let comment =
                 format!("Indicates if the `{name}` method is overridden by the implementor.");
             gen_items.push(parse_quote! {
+                #(#cfg_attrs)*
                 #[doc = #comment]
                 const #gen_const_name: bool = false;
             });
-            gen_consts.insert(gen_const_name);
         }
     }
 
@@ -87,10 +81,11 @@ fn handle_impl(mut item: ItemImpl) -> Result<ItemImpl> {
             if defined_consts.contains(&gen_const_name) {
                 continue;
             }
+            let cfg_attrs = crate::helpers::gather_cfg_attrs(&fn_item.attrs);
             gen_items.push(parse_quote! {
+                #(#cfg_attrs)*
                 const #gen_const_name: bool = true;
             });
-            defined_consts.insert(gen_const_name);
         }
     }