Description
openedon Sep 5, 2024
I tried this code:
// my_macro proc-macro crate
use use proc_macro::TokenStream;
#[proc_macro_derive(Derive)]
pub fn derive(input: TokenStream) -> TokenStream {
eprintln!("{input}");
TokenStream::default()
}
// lib.rs
#[derive(my_macro::Derive)]
enum Enum {
X = {
fn foo(#[cfg(any())] arg1: (), arg2: ()) {}
0
},
}
I'm not sure what exactly I expected to see in the stderr
output when I compile the crate. Maybe this with the #[cfg(...)]
attribute left intact on the function
enum Enum { X = { fn foo(#[cfg(any())] arg1: (), arg2: ()) {} 0 }, }
or this with the #[cfg(...)]
attribute completely removed togther with the syntax it was placed on:
enum Enum { X = { fn foo(arg2: ()) {} 0 }, }
Instead, the output is invalid rust code:
enum Enum { X = { fn foo(, arg2: ()) {} 0 }, }
Notice that the #[cfg(...)]
was removed, but... the coma after the function parameter was not removed. This output results in an invalid token tree not parsable by syn
Meta
rustc --version --verbose
:
rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7
Context
Why would I ever write such code? I'd like to support conditional compilation with my proc macro that generates a builder from a function called bon
. But... since it's a proc macro attribute, the #[cfg(...)]
and #[cfg_attr(...)]
attributes aren't automatically removed when the macro runs.
So I thought I'd workaround it by delegating to a derive macro that accepts the function item in the expression position as the first item of the block for the default value of the enum's variant. This is because derive macros benefit from automatic expansion of #[cfg(...)/cfg_attr(...)]
attributes before they run. Thus, by using a derive macro wrapper I could get the results of cfg evaluation this way.
I could work around that by passing the item as an argument to the proc-macro derive... But IDEs and Rust Analyzer don't work this way. They somehow mess up span information.