Rust doesn’t yet support eager macro expansion (except for a few special built in cases rustc devs granted themselves), which makes it hard to implement some macros robustly. If you put
#[myproc] on something the macro gets the unexpanded item as input, which prevents users from being able to use macros that expand into tokens
myproc is looking for.
I was thinking about how to use
build.rs to workaround this when I stumbled on this
cbindgenexpands macros by essentially calling
cargo rustc --pretty=expanded.
Which makes sense,
cbindgen needs to generate bindings for everything, even things that may only exist after macro expansion. This is exactly like my use case.
I don’t know how robust their approach is — I assume it’s equivalent to
cargo expand which actually warns not to rely on its output being accurate:
Be aware that macro expansion to text is a lossy process. This is a debugging aid only. There should be no expectation that the expanded code can be compiled successfully, nor that if it compiles then it behaves the same as the original code.
But… a lossless version must be possible in order for
rustc to work? So I started digging into what
cbindgen actually does… which is apparently manually reimplement a significant amount of cargo in order to divine what arguments to give cargo to give rustc.
… there must be easier ways? Like I thought the whole idea of compiler-as-a-library being thought about from the beginning was that rustc and cargo would just have some nice API I can call to say “do whatever you’ve got to do to expand this” and get accurate output? I realize they may be unstable APIs The top Google result for “rustc as library” and “rust embed compiler” is a blog from 2014 which I’m guessing is out of date?