From 779f6e3e1cef07cb0c1241d483ed364e522bd280 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 13 Jan 2026 17:05:21 +0000 Subject: [PATCH] rust: macros: support `#[cfg]` properly in `#[vtable]` macro. 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 Reviewed-by: Benno Lossin Link: https://patch.msgid.link/20260113170529.2240744-1-gary@kernel.org Signed-off-by: Miguel Ojeda --- rust/macros/helpers.rs | 6 ++++++ rust/macros/vtable.rs | 13 ++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/rust/macros/helpers.rs b/rust/macros/helpers.rs index adfa60d8f42d8..37ef6a6f2c851 100644 --- a/rust/macros/helpers.rs +++ b/rust/macros/helpers.rs @@ -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 + '_ { + attr.iter().filter(|a| a.path().is_ident("cfg")) +} diff --git a/rust/macros/vtable.rs b/rust/macros/vtable.rs index 72ae0a1816a04..c6510b0c4ea1d 100644 --- a/rust/macros/vtable.rs +++ b/rust/macros/vtable.rs @@ -23,7 +23,6 @@ use syn::{ fn handle_trait(mut item: ItemTrait) -> Result { 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 { &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 { 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); } } -- 2.47.3