Change:
I haven't finished investigating this, so I'm making an issue just so I don't forget it:
Actually, I'm really not sure this should work. I'm nominating this for well-defined.
Actually... this definitely shouldn't work in our current system. The basic issue is that a lonely sigil is not a complete "thing". The "tt" macro option is only intended for macros that expand into macro invocations. There are a number of ways around this; at the most basic level, you can insist that the user provide the sigil and the thing it's attached to. This works, but it may be unsatisfying if you want the sigil to be attached to names that are introduced by the macro. In this case, you have a couple of choices. use an unhygienic macro (and tell everyone what name you want to attach to the sigil, ugh) explicitly have three different versions of the macro, one for each sigil (bleah) clean up the second option by nesting one macro definition inside another one make sigils expand into macro invocations. Anyhow, I would say that as of right now, at least, this is not a bug. I'm going to leave this as nominated mostly because this came up in Vancouver as something that Graydon and I both expected to work.
Visiting for triage: still doesn't work, nothing more to add.
accepted for well-defined milestone
You can work around this by using a dummy macro so that you can pass the directly to it, e.g. for the example in the issue:
reading this workaround makes me feel like our macro system is really broken :(.
/cc
The modernized example gives me which looks like .
notes that another hacky work-around is a nested macro invocation, which avoids needing to define/export dummy macros (although one will want to be careful about giving that internal macro a fairly unique name to avoid trampling on any other macros in scope, unfortunately :disappointed: ).
Updated example: error:
Triage: This is an ancient P-low bug but per it actually comes up in the wild a lot - macro writers have to know how to do this workaround. Can this be escalated? Is there a solution somebody could mentor?
Discussed at lang meeting, we believe this should remain p-low since we don't know a very easy fix. It should be fixed by converting macro_rules to expand to pure tokens then parsing, rather than mixing the two steps (which we hop would be back-compat). cc
Fixed in .

Discussion:
use errors::{Handler, DiagnosticBuilder}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{DocComment, MatchNt, SubstNt}; <del> use parse::token::{Token, NtIdent, SpecialMacroVar}; </del> <ins> use parse::token::{Token, Interpolated, NtIdent, NtTT, SpecialMacroVar}; </ins> use parse::token; use parse::lexer::TokenAndSpan; use tokenstream::{self, TokenTree};

} // FIXME #2887: think about span stuff here TokenTree::Token(sp, SubstNt(ident)) => { <del> r.stack.last_mut().unwrap().idx += 1; </del> match lookup_cur_matched(r, ident) { None => { <ins> r.stack.last_mut().unwrap().idx += 1; </ins> r.cur_span = sp; r.cur_tok = SubstNt(ident); return ret_val;

// (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. MatchedNonterminal(NtIdent(ref sn)) => { <ins> r.stack.last_mut().unwrap().idx += 1; </ins> r.cur_span = sn.span; r.cur_tok = token::Ident(sn.node); return ret_val; } <ins> MatchedNonterminal(NtTT(ref tt)) => { r.stack.push(TtFrame { forest: TokenTree::Token(sp, Interpolated(NtTT(tt.clone()))), idx: 0, dotdotdoted: false, sep: None, }); } </ins> MatchedNonterminal(ref other_whole_nt) => { <ins> r.stack.last_mut().unwrap().idx += 1; </ins> // FIXME(pcwalton): Bad copy. r.cur_span = sp; <del> r.cur_tok = token::Interpolated((*other_whole_nt).clone()); </del> <ins> r.cur_tok = Interpolated((*other_whole_nt).clone()); </ins> return ret_val; } MatchedSeq(..) => {

} TokenTree::Token(_, token::SpecialVarNt(..)) => 2, TokenTree::Token(_, token::MatchNt(..)) => 3, <ins> TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1, </ins> TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2, TokenTree::Sequence(_, ref seq) => seq.tts.len(), TokenTree::Token(..) => 0,

TokenTree::Token(sp, token::Ident(kind))]; v[index].clone() } <ins> (&TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(ref tt))), _) => { tt.clone().unwrap() } </ins> (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), _ => panic!("Cannot expand a token tree"), }

<ins> // Copyright 2016 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(rustc_attrs)] macro_rules! foo { ($x:tt) => (type Alias = $x<i32>;) } foo!(Box); #[rustc_error] fn main() {} //~ ERROR compilation successful </ins>