Expanded colons not allowed to match in macros?

macro_rules! spam {
    (spam: { $($t:tt)* }) => { stringify!($($t)*) };
}

macro_rules! super_spam {
    ($x:ident) => { spam: { $x $x $x } };
}

fn main() {
    // Doesn't work:
    println!(spam! { super_spam!(spam) });
}

(Playground)

Trying to do something like in downcast-rs.

Edit: The expanded colon I said refers to the one in the definition of super_spam!

i have no idea what you mean about colons, but macros are evalueted outside-in.

and spam expect to receive spam: { $($t:tt)* }, and super_spam!(spam) doesn't fit that expectation.

you might find this weird, as values in functions are avaluated inside out, but it's necessary to make macros able to absorb arbitrary code that may itself contain macros

2 Likes

Macros can only expand to grammar constructions that are a) valid Rust and b) in a sense self-contained. This is neither.

1 Like
macro_rules! spam {
    ($($t:tt)*) => { concat!($($t)*, " ", $($t)*, " ", $($t)*) };
}

macro_rules! inner_spam {
    ($x:ident) => { stringify!($x)};
}

fn main() {
    // Doesn't work:
    println!(spam! { inner_spam!(spam) });
}

here is an example that works. as you can see spam is evaluated first, and makes 3 inner_spam, and the the 3 get evaluated. concat! does allow macros to be evaluated before doing the actual concatenation, making it kinda special, which is why it is a compiler builtin

1 Like