Auto merge of #28552 - apasel422:issue-28527, r=Manishearth
Closes #28527. r? @Manishearth
This commit is contained in:
commit
d2faba28c0
@ -28,7 +28,6 @@ pub use self::Item_::*;
|
||||
pub use self::KleeneOp::*;
|
||||
pub use self::Lit_::*;
|
||||
pub use self::LitIntType::*;
|
||||
pub use self::Mac_::*;
|
||||
pub use self::MacStmtStyle::*;
|
||||
pub use self::MetaItem_::*;
|
||||
pub use self::Mutability::*;
|
||||
@ -1132,12 +1131,13 @@ pub type Mac = Spanned<Mac_>;
|
||||
/// is being invoked, and the vector of token-trees contains the source
|
||||
/// of the macro invocation.
|
||||
///
|
||||
/// There's only one flavor, now, so this could presumably be simplified.
|
||||
/// NB: the additional ident for a macro_rules-style macro is actually
|
||||
/// stored in the enclosing item. Oog.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum Mac_ {
|
||||
// NB: the additional ident for a macro_rules-style macro is actually
|
||||
// stored in the enclosing item. Oog.
|
||||
MacInvocTT(Path, Vec<TokenTree>, SyntaxContext), // new macro-invocation
|
||||
pub struct Mac_ {
|
||||
pub path: Path,
|
||||
pub tts: Vec<TokenTree>,
|
||||
pub ctxt: SyntaxContext,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
|
||||
use ast::{Local, Ident, MacInvocTT};
|
||||
use ast::{Local, Ident, Mac_};
|
||||
use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
|
||||
use ast::{StmtExpr, StmtSemi};
|
||||
use ast::TokenTree;
|
||||
@ -509,78 +509,75 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac,
|
||||
F: for<'a> FnOnce(Box<MacResult+'a>) -> Option<T>,
|
||||
G: FnOnce(T, Mrk) -> T,
|
||||
{
|
||||
match mac.node {
|
||||
// it would almost certainly be cleaner to pass the whole
|
||||
// macro invocation in, rather than pulling it apart and
|
||||
// marking the tts and the ctxt separately. This also goes
|
||||
// for the other three macro invocation chunks of code
|
||||
// in this file.
|
||||
// Token-tree macros:
|
||||
MacInvocTT(pth, tts, _) => {
|
||||
if pth.segments.len() > 1 {
|
||||
fld.cx.span_err(pth.span,
|
||||
"expected macro name without module \
|
||||
separators");
|
||||
// let compilation continue
|
||||
return None;
|
||||
}
|
||||
let extname = pth.segments[0].identifier.name;
|
||||
match fld.cx.syntax_env.find(&extname) {
|
||||
None => {
|
||||
fld.cx.span_err(
|
||||
pth.span,
|
||||
&format!("macro undefined: '{}!'",
|
||||
&extname));
|
||||
// it would almost certainly be cleaner to pass the whole
|
||||
// macro invocation in, rather than pulling it apart and
|
||||
// marking the tts and the ctxt separately. This also goes
|
||||
// for the other three macro invocation chunks of code
|
||||
// in this file.
|
||||
|
||||
// let compilation continue
|
||||
None
|
||||
}
|
||||
Some(rc) => match *rc {
|
||||
NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
call_site: span,
|
||||
callee: NameAndSpan {
|
||||
format: MacroBang(extname),
|
||||
span: exp_span,
|
||||
allow_internal_unstable: allow_internal_unstable,
|
||||
},
|
||||
});
|
||||
let fm = fresh_mark();
|
||||
let marked_before = mark_tts(&tts[..], fm);
|
||||
let Mac_ { path: pth, tts, .. } = mac.node;
|
||||
if pth.segments.len() > 1 {
|
||||
fld.cx.span_err(pth.span,
|
||||
"expected macro name without module \
|
||||
separators");
|
||||
// let compilation continue
|
||||
return None;
|
||||
}
|
||||
let extname = pth.segments[0].identifier.name;
|
||||
match fld.cx.syntax_env.find(&extname) {
|
||||
None => {
|
||||
fld.cx.span_err(
|
||||
pth.span,
|
||||
&format!("macro undefined: '{}!'",
|
||||
&extname));
|
||||
|
||||
// The span that we pass to the expanders we want to
|
||||
// be the root of the call stack. That's the most
|
||||
// relevant span and it's the actual invocation of
|
||||
// the macro.
|
||||
let mac_span = fld.cx.original_span();
|
||||
// let compilation continue
|
||||
None
|
||||
}
|
||||
Some(rc) => match *rc {
|
||||
NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
call_site: span,
|
||||
callee: NameAndSpan {
|
||||
format: MacroBang(extname),
|
||||
span: exp_span,
|
||||
allow_internal_unstable: allow_internal_unstable,
|
||||
},
|
||||
});
|
||||
let fm = fresh_mark();
|
||||
let marked_before = mark_tts(&tts[..], fm);
|
||||
|
||||
let opt_parsed = {
|
||||
let expanded = expandfun.expand(fld.cx,
|
||||
mac_span,
|
||||
&marked_before[..]);
|
||||
parse_thunk(expanded)
|
||||
};
|
||||
let parsed = match opt_parsed {
|
||||
Some(e) => e,
|
||||
None => {
|
||||
fld.cx.span_err(
|
||||
pth.span,
|
||||
&format!("non-expression macro in expression position: {}",
|
||||
extname
|
||||
));
|
||||
return None;
|
||||
}
|
||||
};
|
||||
Some(mark_thunk(parsed,fm))
|
||||
}
|
||||
_ => {
|
||||
// The span that we pass to the expanders we want to
|
||||
// be the root of the call stack. That's the most
|
||||
// relevant span and it's the actual invocation of
|
||||
// the macro.
|
||||
let mac_span = fld.cx.original_span();
|
||||
|
||||
let opt_parsed = {
|
||||
let expanded = expandfun.expand(fld.cx,
|
||||
mac_span,
|
||||
&marked_before[..]);
|
||||
parse_thunk(expanded)
|
||||
};
|
||||
let parsed = match opt_parsed {
|
||||
Some(e) => e,
|
||||
None => {
|
||||
fld.cx.span_err(
|
||||
pth.span,
|
||||
&format!("'{}' is not a tt-style macro",
|
||||
extname));
|
||||
None
|
||||
&format!("non-expression macro in expression position: {}",
|
||||
extname
|
||||
));
|
||||
return None;
|
||||
}
|
||||
}
|
||||
};
|
||||
Some(mark_thunk(parsed,fm))
|
||||
}
|
||||
_ => {
|
||||
fld.cx.span_err(
|
||||
pth.span,
|
||||
&format!("'{}' is not a tt-style macro",
|
||||
extname));
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -684,15 +681,11 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
|
||||
// logic as for expression-position macro invocations.
|
||||
pub fn expand_item_mac(it: P<ast::Item>,
|
||||
fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
|
||||
let (extname, path_span, tts, span, attrs, ident) = it.and_then(|it| { match it.node {
|
||||
ItemMac(codemap::Spanned {
|
||||
node: MacInvocTT(pth, tts, _),
|
||||
..
|
||||
}) => {
|
||||
(pth.segments[0].identifier.name, pth.span, tts, it.span, it.attrs, it.ident)
|
||||
}
|
||||
let (extname, path_span, tts, span, attrs, ident) = it.and_then(|it| match it.node {
|
||||
ItemMac(codemap::Spanned { node: Mac_ { path, tts, .. }, .. }) =>
|
||||
(path.segments[0].identifier.name, path.span, tts, it.span, it.attrs, it.ident),
|
||||
_ => fld.cx.span_bug(it.span, "invalid item macro invocation")
|
||||
}});
|
||||
});
|
||||
|
||||
let fm = fresh_mark();
|
||||
let items = {
|
||||
@ -1060,11 +1053,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
|
||||
}
|
||||
p.map(|ast::Pat {node, span, ..}| {
|
||||
let (pth, tts) = match node {
|
||||
PatMac(mac) => match mac.node {
|
||||
MacInvocTT(pth, tts, _) => {
|
||||
(pth, tts)
|
||||
}
|
||||
},
|
||||
PatMac(mac) => (mac.node.path, mac.node.tts),
|
||||
_ => unreachable!()
|
||||
};
|
||||
if pth.segments.len() > 1 {
|
||||
@ -1646,12 +1635,10 @@ impl Folder for Marker {
|
||||
}
|
||||
fn fold_mac(&mut self, Spanned {node, span}: ast::Mac) -> ast::Mac {
|
||||
Spanned {
|
||||
node: match node {
|
||||
MacInvocTT(path, tts, ctxt) => {
|
||||
MacInvocTT(self.fold_path(path),
|
||||
self.fold_tts(&tts[..]),
|
||||
mtwt::apply_mark(self.mark, ctxt))
|
||||
}
|
||||
node: Mac_ {
|
||||
path: self.fold_path(node.path),
|
||||
tts: self.fold_tts(&node.tts),
|
||||
ctxt: mtwt::apply_mark(self.mark, node.ctxt),
|
||||
},
|
||||
span: span,
|
||||
}
|
||||
|
@ -666,7 +666,7 @@ struct MacroVisitor<'a> {
|
||||
|
||||
impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
|
||||
fn visit_mac(&mut self, mac: &ast::Mac) {
|
||||
let ast::MacInvocTT(ref path, _, _) = mac.node;
|
||||
let path = &mac.node.path;
|
||||
let id = path.segments.last().unwrap().identifier;
|
||||
|
||||
// Issue 22234: If you add a new case here, make sure to also
|
||||
|
@ -567,10 +567,10 @@ pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fl
|
||||
|
||||
pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
|
||||
Spanned {
|
||||
node: match node {
|
||||
MacInvocTT(p, tts, ctxt) => {
|
||||
MacInvocTT(fld.fold_path(p), fld.fold_tts(&tts), ctxt)
|
||||
}
|
||||
node: Mac_ {
|
||||
path: fld.fold_path(node.path),
|
||||
tts: fld.fold_tts(&node.tts),
|
||||
ctxt: node.ctxt,
|
||||
},
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
|
@ -1090,10 +1090,7 @@ mod tests {
|
||||
"foo!( fn main() { body } )".to_string(), vec![], &sess);
|
||||
|
||||
let tts = match expr.node {
|
||||
ast::ExprMac(ref mac) => {
|
||||
let ast::MacInvocTT(_, ref tts, _) = mac.node;
|
||||
tts.clone()
|
||||
}
|
||||
ast::ExprMac(ref mac) => mac.node.tts.clone(),
|
||||
_ => panic!("not a macro"),
|
||||
};
|
||||
|
||||
|
@ -37,7 +37,7 @@ use ast::{LifetimeDef, Lit, Lit_};
|
||||
use ast::{LitBool, LitChar, LitByte, LitByteStr};
|
||||
use ast::{LitStr, LitInt, Local};
|
||||
use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces};
|
||||
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource};
|
||||
use ast::{MutImmutable, MutMutable, Mac_, MatchSource};
|
||||
use ast::{MutTy, BiMul, Mutability};
|
||||
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
|
||||
use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatQPath, PatMac, PatRange};
|
||||
@ -1381,7 +1381,7 @@ impl<'a> Parser<'a> {
|
||||
seq_sep_none(),
|
||||
|p| p.parse_token_tree()));
|
||||
let hi = self.span.hi;
|
||||
TyMac(spanned(lo, hi, MacInvocTT(path, tts, EMPTY_CTXT)))
|
||||
TyMac(spanned(lo, hi, Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }))
|
||||
} else {
|
||||
// NAMED TYPE
|
||||
TyPath(None, path)
|
||||
@ -2203,9 +2203,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
return Ok(self.mk_mac_expr(lo,
|
||||
hi,
|
||||
MacInvocTT(pth,
|
||||
tts,
|
||||
EMPTY_CTXT)));
|
||||
Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }));
|
||||
}
|
||||
if self.check(&token::OpenDelim(token::Brace)) {
|
||||
// This is a struct literal, unless we're prohibited
|
||||
@ -3289,7 +3287,7 @@ impl<'a> Parser<'a> {
|
||||
let delim = try!(self.expect_open_delim());
|
||||
let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
|
||||
seq_sep_none(), |p| p.parse_token_tree()));
|
||||
let mac = MacInvocTT(path, tts, EMPTY_CTXT);
|
||||
let mac = Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT };
|
||||
pat = PatMac(codemap::Spanned {node: mac, span: self.span});
|
||||
} else {
|
||||
// Parse ident @ pat
|
||||
@ -3557,7 +3555,7 @@ impl<'a> Parser<'a> {
|
||||
spanned(lo, hi,
|
||||
StmtMac(P(spanned(lo,
|
||||
hi,
|
||||
MacInvocTT(pth, tts, EMPTY_CTXT))),
|
||||
Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
|
||||
style))
|
||||
} else {
|
||||
// if it has a special ident, it's definitely an item
|
||||
@ -3576,7 +3574,8 @@ impl<'a> Parser<'a> {
|
||||
P(spanned(lo, hi, DeclItem(
|
||||
self.mk_item(
|
||||
lo, hi, id /*id is good here*/,
|
||||
ItemMac(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))),
|
||||
ItemMac(spanned(lo, hi,
|
||||
Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
|
||||
Inherited, Vec::new(/*no attrs*/))))),
|
||||
ast::DUMMY_NODE_ID))
|
||||
}
|
||||
@ -4524,7 +4523,7 @@ impl<'a> Parser<'a> {
|
||||
let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
|
||||
seq_sep_none(),
|
||||
|p| p.parse_token_tree()));
|
||||
let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT);
|
||||
let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
|
||||
let m: ast::Mac = codemap::Spanned { node: m_,
|
||||
span: mk_sp(self.span.lo,
|
||||
self.span.hi) };
|
||||
@ -5606,7 +5605,7 @@ impl<'a> Parser<'a> {
|
||||
seq_sep_none(),
|
||||
|p| p.parse_token_tree()));
|
||||
// single-variant-enum... :
|
||||
let m = ast::MacInvocTT(pth, tts, EMPTY_CTXT);
|
||||
let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
|
||||
let m: ast::Mac = codemap::Spanned { node: m,
|
||||
span: mk_sp(self.span.lo,
|
||||
self.span.hi) };
|
||||
|
@ -1307,16 +1307,14 @@ impl<'a> State<'a> {
|
||||
}
|
||||
try!(self.bclose(item.span));
|
||||
}
|
||||
// I think it's reasonable to hide the context here:
|
||||
ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
|
||||
..}) => {
|
||||
ast::ItemMac(codemap::Spanned { ref node, .. }) => {
|
||||
try!(self.print_visibility(item.vis));
|
||||
try!(self.print_path(pth, false, 0));
|
||||
try!(self.print_path(&node.path, false, 0));
|
||||
try!(word(&mut self.s, "! "));
|
||||
try!(self.print_ident(item.ident));
|
||||
try!(self.cbox(indent_unit));
|
||||
try!(self.popen());
|
||||
try!(self.print_tts(&tts[..]));
|
||||
try!(self.print_tts(&node.tts[..]));
|
||||
try!(self.pclose());
|
||||
try!(word(&mut self.s, ";"));
|
||||
try!(self.end());
|
||||
@ -1599,14 +1597,13 @@ impl<'a> State<'a> {
|
||||
ast::TypeImplItem(ref ty) => {
|
||||
try!(self.print_associated_type(ii.ident, None, Some(ty)));
|
||||
}
|
||||
ast::MacImplItem(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
|
||||
..}) => {
|
||||
ast::MacImplItem(codemap::Spanned { ref node, .. }) => {
|
||||
// code copied from ItemMac:
|
||||
try!(self.print_path(pth, false, 0));
|
||||
try!(self.print_path(&node.path, false, 0));
|
||||
try!(word(&mut self.s, "! "));
|
||||
try!(self.cbox(indent_unit));
|
||||
try!(self.popen());
|
||||
try!(self.print_tts(&tts[..]));
|
||||
try!(self.print_tts(&node.tts[..]));
|
||||
try!(self.pclose());
|
||||
try!(word(&mut self.s, ";"));
|
||||
try!(self.end())
|
||||
@ -1765,23 +1762,18 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
|
||||
-> io::Result<()> {
|
||||
match m.node {
|
||||
// I think it's reasonable to hide the ctxt here:
|
||||
ast::MacInvocTT(ref pth, ref tts, _) => {
|
||||
try!(self.print_path(pth, false, 0));
|
||||
try!(word(&mut self.s, "!"));
|
||||
match delim {
|
||||
token::Paren => try!(self.popen()),
|
||||
token::Bracket => try!(word(&mut self.s, "[")),
|
||||
token::Brace => try!(self.bopen()),
|
||||
}
|
||||
try!(self.print_tts(tts));
|
||||
match delim {
|
||||
token::Paren => self.pclose(),
|
||||
token::Bracket => word(&mut self.s, "]"),
|
||||
token::Brace => self.bclose(m.span),
|
||||
}
|
||||
}
|
||||
try!(self.print_path(&m.node.path, false, 0));
|
||||
try!(word(&mut self.s, "!"));
|
||||
match delim {
|
||||
token::Paren => try!(self.popen()),
|
||||
token::Bracket => try!(word(&mut self.s, "[")),
|
||||
token::Brace => try!(self.bopen()),
|
||||
}
|
||||
try!(self.print_tts(&m.node.tts));
|
||||
match delim {
|
||||
token::Paren => self.pclose(),
|
||||
token::Bracket => word(&mut self.s, "]"),
|
||||
token::Brace => self.bclose(m.span),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user