diff --git a/crates/fayalite-proc-macros-impl/src/lib.rs b/crates/fayalite-proc-macros-impl/src/lib.rs index 1b1b61f..6ba177b 100644 --- a/crates/fayalite-proc-macros-impl/src/lib.rs +++ b/crates/fayalite-proc-macros-impl/src/lib.rs @@ -1210,17 +1210,29 @@ fn hdl_main( attr: TokenStream, item: TokenStream, ) -> syn::Result { - let (evaluated_cfgs, attr): (_, TokenStream) = Parser::parse2( + fn parse_evaluated_cfgs_attr( + input: ParseStream, + parse_inner: impl FnOnce(ParseStream) -> syn::Result, + ) -> syn::Result { + let _: Token![#] = input.parse()?; + let bracket_content; + bracketed!(bracket_content in input); + let _: kw::__evaluated_cfgs = bracket_content.parse()?; + let paren_content; + parenthesized!(paren_content in bracket_content); + parse_inner(&paren_content) + } + let (evaluated_cfgs, item): (_, TokenStream) = Parser::parse2( |input: ParseStream| { - if input.peek(Bracket) && input.peek2(kw::__evaluated_cfgs) { - let cfgs = input.parse()?; - let _: kw::__evaluated_cfgs = input.parse()?; - Ok((Some(cfgs), input.parse()?)) + let peek = input.fork(); + if parse_evaluated_cfgs_attr(&peek, |_| Ok(())).is_ok() { + let evaluated_cfgs = parse_evaluated_cfgs_attr(input, Cfgs::::parse)?; + Ok((Some(evaluated_cfgs), input.parse()?)) } else { Ok((None, input.parse()?)) } }, - attr, + item, )?; let cfgs = if let Some(cfgs) = evaluated_cfgs { cfgs @@ -1229,12 +1241,11 @@ fn hdl_main( if cfgs.cfgs_list.is_empty() { Cfgs::default() } else { - let key = kw::__evaluated_cfgs::default(); return Ok(quote! { ::fayalite::__cfg_expansion_helper! { [] #cfgs - #[::fayalite::#kw:(#key #attr)] { #item } + {#[::fayalite::#kw(#attr)]} { #item } } }); } diff --git a/crates/fayalite/src/lib.rs b/crates/fayalite/src/lib.rs index 5b5afb4..88fe169 100644 --- a/crates/fayalite/src/lib.rs +++ b/crates/fayalite/src/lib.rs @@ -22,7 +22,8 @@ macro_rules! __cfg_expansion_helper { $cfg:ident($($expr:tt)*), $($unevaluated_cfgs:ident($($unevaluated_exprs:tt)*),)* ] - #[$after_evaluation:path:($($after_evaluation_attr_args:tt)*)] {$($after_evaluation_args:tt)*} + // pass as tt so we get right span for attribute + $after_evaluation_attr:tt $after_evaluation_body:tt ) => { #[$cfg($($expr)*)] $crate::__cfg_expansion_helper! { @@ -33,7 +34,7 @@ macro_rules! __cfg_expansion_helper { [ $($unevaluated_cfgs($($unevaluated_exprs)*),)* ] - #[$after_evaluation:($($after_evaluation_attr_args)*)] {$($after_evaluation_args)*} + $after_evaluation_attr $after_evaluation_body } #[$cfg(not($($expr)*))] $crate::__cfg_expansion_helper! { @@ -44,7 +45,7 @@ macro_rules! __cfg_expansion_helper { [ $($unevaluated_cfgs($($unevaluated_exprs)*),)* ] - #[$after_evaluation:($($after_evaluation_attr_args)*)] {$($after_evaluation_args)*} + $after_evaluation_attr $after_evaluation_body } }; ( @@ -52,12 +53,14 @@ macro_rules! __cfg_expansion_helper { $($evaluated_cfgs:ident($($evaluated_exprs:tt)*) = $evaluated_results:ident,)* ] [] - #[$after_evaluation:path:($($after_evaluation_attr_args:tt)*)] {$($after_evaluation_args:tt)*} + // don't use #[...] so we get right span for `#` and `[]` of attribute + {$($after_evaluation_attr:tt)*} {$($after_evaluation_body:tt)*} ) => { - #[$after_evaluation([ + $($after_evaluation_attr)* + #[__evaluated_cfgs([ $($evaluated_cfgs($($evaluated_exprs)*) = $evaluated_results,)* - ] $($after_evaluation_attr_args)*)] - $($after_evaluation_args)* + ])] + $($after_evaluation_body)* }; } diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 42cc528..4e56df4 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -4288,7 +4288,8 @@ circuit check_deduce_resets: }; } -#[hdl_module(outline_generated)] +// intentionally not outline_generated to ensure we get correct macro hygiene +#[hdl_module] pub fn check_cfgs<#[cfg(cfg_false_for_tests)] A: Type, #[cfg(cfg_true_for_tests)] B: Type>( #[cfg(cfg_false_for_tests)] a: A, #[cfg(cfg_true_for_tests)] b: B, @@ -4335,12 +4336,12 @@ fn test_cfgs() { "/test/check_cfgs.fir": r"FIRRTL version 3.2.0 circuit check_cfgs: type Ty0 = {b: UInt<8>} - module check_cfgs: @[module-XXXXXXXXXX.rs 1:1] - input i_b: UInt<8> @[module-XXXXXXXXXX.rs 2:1] - output o_b: UInt<8> @[module-XXXXXXXXXX.rs 4:1] - wire w: Ty0 @[module-XXXXXXXXXX.rs 3:1] - connect o_b, w.b @[module-XXXXXXXXXX.rs 5:1] - connect w.b, i_b @[module-XXXXXXXXXX.rs 6:1] + module check_cfgs: @[the_test_file.rs 9962:1] + input i_b: UInt<8> @[the_test_file.rs 9979:20] + output o_b: UInt<8> @[the_test_file.rs 9992:24] + wire w: Ty0 @[the_test_file.rs 9981:25] + connect o_b, w.b @[the_test_file.rs 9993:9] + connect w.b, i_b @[the_test_file.rs 9994:9] ", }; }