How does this macro optimize?
⚓ Rust 📅 2025-09-20 👤 surdeus 👁️ 8I have the following macro:
macro_rules! a {
($item:item) => {
#[b]
$item
}
}
I am nesting it 10 times:
a!(a!(a!(a!(a!(a!(a!(a!(a!(a!(
struct Foo;
))))))))));
How does it optimize? Is it like this:
#[proc_macro]
fn a(input: TokenStream) -> TokenStream {
let item = parse_macro_input!(input as Item);
quote! { #[b] #item }
}
With 10 nested calls to a, the same macro input will be parsed and quoted 10 times in a row.
Or does the compiler optimize it to do all the work in 1 go:
#[proc_macro]
fn a(input: TokenStream) -> TokenStream {
let item = parse_macro_input!(input as Item);
quote! { #[b] #[b] #[b] #[b] #[b] #[b] #[b] #[b] #[b] #[b] #item }
}
The above is a very simplified example of the real use-case: I am making a crate derive_aliases and I am currently implementing it as a proc macro. I generate all the derives in a single go. I realized I can implement my crate using declarative macros instead, nesting the user's input in 10-20 plus calls to the macros. I have a feeling this will be much slower, but I'm wondering if the compiler has any optimization passes for macros which would make the declarative version faster
Just imagine this: another macro b!() nests the $item in 20 calls to a!(). b!() is called thousands of times in the code-base. These are the numbers
Or alternatively, b!() is a proc macro and does all of the work for 20 calls in a single pass. All logic for a!() is inlined in a single macro call. No nesting. $item is parsed just once.
I have a feeling the 2nd version will have much better compile-time speeds
2 posts - 2 participants
🏷️ Rust_feed