Auto merge of #28552 - apasel422:issue-28527, r=Manishearth

Closes #28527.

r? @Manishearth
This commit is contained in:
bors 2015-09-21 02:40:40 +00:00
commit d2faba28c0
7 changed files with 112 additions and 137 deletions

View File

@ -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)]

View File

@ -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,
}

View File

@ -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

View File

@ -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)
}

View File

@ -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"),
};

View File

@ -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) };

View File

@ -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),
}
}