General substition in macros

I have a question about advanced macros: I’m trying to achieve a substitution where both module::StructName and StructName could be accepted (so I think both a tt and a path). Is it possible?

Example:

macro_rules! my_macro {
    ($this_new_token:tt) => (
        let constant = $this_new_token::from("Hello world!");
    )
}

my_macro!(module::StructName);

The above example gives me:

$this_new_token::from("Hello world!");
               ^^ expected one of `.`, `;`, `?`, or an operator here

Thanks!

Unfortunately I don’t think it’s possible to graft onto a $:path matcher, which seems to be what you want.

If you’re ok accepting a subset of paths (that is, ones without generic qualification), you can match $($:ident)::+:

macro_rules! m {
    ($($i:ident)::+) => ($($i)::+ ::default());
}

fn main() {
    let x: u32 = m!(std::default::Default);
    println!("{}", x);
}
1 Like

If you need something that matches both module::StructName and StructName I would recommend using $:path.

macro_rules! my_macro {
    ($p:path) => {
        let constant = <$p>::from("Hello world!");
        println!("{}", constant);
    };
}

fn main() {
    my_macro!(String);
    my_macro!(std::string::String);
}
2 Likes

Worked perfectly, thank you!