rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.14k stars 12.8k forks source link

recursive macro --- macro doesn't exist #14946

Closed BurntSushi closed 10 years ago

BurntSushi commented 10 years ago

I believe this should output the string abc:

#![feature(macro_rules)]

macro_rules! rec(
    () => ("");
    ($a:ident) => (stringify!($a));
    ($a:ident, $($rest:tt),*) => (
        concat!(stringify!($a), rec!($($rest),*))
    );
)

fn main() {
    println!("{}", rec!(a, b, c));
}

But I get this error:

reem.rs:7:33: 7:36 error: macro undefined: 'rec'
reem.rs:7         concat!(stringify!($a), rec!($($rest),*))

Rust version:

[andrew@Liger rust] rustc --version
rustc 0.11.0-pre (6d8342f 2014-06-14 17:51:49 +0000)
host: x86_64-unknown-linux-gnu
BurntSushi commented 10 years ago

Note that standard recursive macros work fine, e.g.,

macro_rules! rec_works(
    () => (0);
    ($a:expr) => ($a);
    ($a:expr, $($rest:tt),*) => (
        $a + rec_works!($($rest),*)
    );
)

And rec_works!(1, 2, 3) outputs 6.

Maybe the bug here is that expanding macros within other macros is using an older environment that doesn't include the name rec?

sfackler commented 10 years ago

It's even worse than that. expand_expr only uses the compiler built-in macros: https://github.com/rust-lang/rust/blob/master/src/libsyntax/ext/base.rs#L421

huonw commented 10 years ago

I think this might be a dupe of https://github.com/rust-lang/rust/issues/12404.

BurntSushi commented 10 years ago

@huonw Does fixing print!(format!(...)) mean that print!(some_recursive_call!(...)) also gets fixed? I wouldn't assume so, but it might be possible depending on the implementation.

(Sorry I missed that issue. I searched for 'recursive macro' instead of 'nested macro'!)

sfackler commented 10 years ago

@BurntSushi both print! and concat_idents! use expand_expr, which doesn't work with non-builtin macros.

BurntSushi commented 10 years ago

@sfackler Right. I'm referring to the recursive aspect. Wasn't sure if that would make a difference. (I just don't know enough about how macros are expanded to know. Pure guesswork on my part.)