Skip to content

Commit b3b97f5

Browse files
nbdd0121BennoLossin
authored andcommitted
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 <[email protected]>
1 parent e0d04a6 commit b3b97f5

File tree

2 files changed

+13
-9
lines changed

2 files changed

+13
-9
lines changed

rust/macros/helpers.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use syn::{
77
Parse,
88
ParseStream, //
99
},
10+
Attribute,
1011
Error,
1112
LitStr,
1213
Result, //
@@ -53,3 +54,11 @@ pub(crate) fn file() -> String {
5354
proc_macro::Span::call_site().file()
5455
}
5556
}
57+
58+
/// Obtain all `#[cfg]` attributes.
59+
pub(crate) fn gather_cfg_attrs(attr: &[Attribute]) -> Vec<Attribute> {
60+
attr.iter()
61+
.filter(|a| a.path().is_ident("cfg"))
62+
.cloned()
63+
.collect()
64+
}

rust/macros/vtable.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use syn::{
2323

2424
fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
2525
let mut gen_items = Vec::new();
26-
let mut gen_consts = HashSet::new();
2726

2827
gen_items.push(parse_quote! {
2928
/// A marker to prevent implementors from forgetting to use [`#[vtable]`](vtable)
@@ -38,22 +37,17 @@ fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> {
3837
&format!("HAS_{}", name.to_string().to_uppercase()),
3938
name.span(),
4039
);
41-
// Skip if it's declared already -- this can happen if `#[cfg]` is used to selectively
42-
// define functions.
43-
// FIXME: `#[cfg]` should be copied and propagated to the generated consts.
44-
if gen_consts.contains(&gen_const_name) {
45-
continue;
46-
}
4740

4841
// We don't know on the implementation-site whether a method is required or provided
4942
// so we have to generate a const for all methods.
43+
let cfg_attrs = crate::helpers::gather_cfg_attrs(&fn_item.attrs);
5044
let comment =
5145
format!("Indicates if the `{name}` method is overridden by the implementor.");
5246
gen_items.push(parse_quote! {
47+
#(#cfg_attrs)*
5348
#[doc = #comment]
5449
const #gen_const_name: bool = false;
5550
});
56-
gen_consts.insert(gen_const_name);
5751
}
5852
}
5953

@@ -87,10 +81,11 @@ fn handle_impl(mut item: ItemImpl) -> Result<ItemImpl> {
8781
if defined_consts.contains(&gen_const_name) {
8882
continue;
8983
}
84+
let cfg_attrs = crate::helpers::gather_cfg_attrs(&fn_item.attrs);
9085
gen_items.push(parse_quote! {
86+
#(#cfg_attrs)*
9187
const #gen_const_name: bool = true;
9288
});
93-
defined_consts.insert(gen_const_name);
9489
}
9590
}
9691

0 commit comments

Comments
 (0)