I'm trying to define a macro that takes a module name as input, as :path
, and access its items.
Unfortunately, format_args
macro, and therefore print
/println
, do not let me use a :path
metavariable in their args
, expecting :tt
.
macro_rules! something {
( $path:path ) => (
//println!("Say: {}", $path::say);
format_args!("Say: {}", $path::say);
);
}
mod foo {
const say: &str = "Hello";
}
mod bar {
const say: &str = "World";
mod baz {
const say: &str = "Universe";
}
}
fn main() {
something!(foo);
something!(bar);
something!(bar::baz);
}
It fails with three instances of this error (with RUSTFLAGS='-Z external-macro-backtrace'
):
error: expected token: `,`
--> src/main.rs:4:9
|
1 | / macro_rules! talk {
2 | | ( $mod:path ) => (
3 | | // print!("Say: {}", $mod::say);
4 | | format_args!("Say: {}", $mod::say);
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | | );
6 | | }
| |_- in this expansion of `talk!`
...
21 | talk!(foo);
| ----------- in this macro invocation
I'm surprised to see that $path::say
doesn't resolve into a tt
before being passed to the internal macro call. Isn't this how path
metavariables are expected to be used?
Or maybe the limit here is the format_args
implementation? If so, what input token type can format_args
use to address this limit?
I couldn't find a answer looking at the Macros docs. Any ideas?