Change:
I believe this should output the string : But I get this error: Rust version:
Note that standard recursive macros work fine, e.g., And outputs . Maybe the bug here is that expanding macros within other macros is using an older environment that doesn't include the name ?
It's even worse than that. only uses the compiler built-in macros:
I think this might be a dupe of
Does fixing mean that 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'!)
both and use , which doesn't work with non-builtin macros.
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.)

Discussion:
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult}; use syntax::parse::token; use syntax::print::pprust; <ins> use syntax::fold::Folder; </ins> use rustc::plugin::Registry;

/// Otherwise, logs an error with cx.span_err and returns None. fn parse(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Option<String> { let mut parser = cx.new_parser_from_tts(tts); <del> let entry = cx.expand_expr(parser.parse_expr()); </del> <ins> let entry = cx.expander().fold_expr(parser.parse_expr()); </ins> let regex = match entry.node { ast::ExprLit(lit) => { match lit.node {

use parse::token::{InternedString, intern, str_to_ident}; use util::small_vector::SmallVector; use ext::mtwt; <ins> use fold::Folder; </ins> use std::collections::HashMap; use std::gc::{Gc, GC};

pub trace_mac: bool, pub exported_macros: Vec<Gc<ast::Item>>, <del> pub syntax_env: SyntaxEnv, </del> <ins> pub syntax_env: SyntaxEnv, </ins> } impl<'a> ExtCtxt<'a> {

} } <del> pub fn expand_expr(&mut self, mut e: Gc<ast::Expr>) -> Gc<ast::Expr> { loop { match e.node { ast::ExprMac(..) => { let mut expander = expand::MacroExpander { cx: self, }; e = expand::expand_expr(e, &mut expander); } _ => return e } } </del> <ins> #[deprecated = "Replaced with `expander().fold_expr()`"] pub fn expand_expr(&mut self, e: Gc<ast::Expr>) -> Gc<ast::Expr> { self.expander().fold_expr(e) } /// Returns a `Folder` for deeply expanding all macros in a AST node. pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { expand::MacroExpander { cx: self } </ins> } pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree])

pub fn expr_to_string(cx: &mut ExtCtxt, expr: Gc<ast::Expr>, err_msg: &str) -> Option<(InternedString, ast::StrStyle)> { // we want to be able to handle e.g. concat("foo", "bar") <del> let expr = cx.expand_expr(expr); </del> <ins> let expr = cx.expander().fold_expr(expr); </ins> match expr.node { ast::ExprLit(l) => match l.node { ast::LitStr(ref s, style) => return Some(((*s).clone(), style)),

let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::EOF { <del> es.push(cx.expand_expr(p.parse_expr())); </del> <ins> es.push(cx.expander().fold_expr(p.parse_expr())); </ins> if p.eat(&token::COMMA) { continue; }

use std::gc::{Gc, GC}; <del> pub fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> { </del> <ins> fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> { </ins> match e.node { // expr_mac should really be expr_ext or something; it's the // entry-point for all syntax extensions.

name_finder.ident_accumulator } <del> //fn expand_and_resolve(crate_str: @str) -> ast::crate { //let expanded_ast = expand_crate_str(crate_str); // println!("expanded: {:?}n",expanded_ast); //mtwt_resolve_crate(expanded_ast) //} //fn expand_and_resolve_and_pretty_print (crate_str: @str) -> String { //let resolved_ast = expand_and_resolve(crate_str); //pprust::to_string(&resolved_ast,fake_print_crate,get_ident_interner()) //} </del> #[test] fn macro_tokens_should_match(){ expand_crate_str( "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_string());

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![feature(macro_rules)] macro_rules! foo2 { () => { "foo" } } macro_rules! foo { () => { foo2!() } } fn main() { assert_eq!(concat!(foo!(), "bar"), "foobar") } </ins>