Replace the String
in ParseResult::Failure
with Token
.
This lets us delay creation of failure messages until they are needed, which avoids ~1.6M allocations in html5ever.
This commit is contained in:
parent
e382267cfb
commit
b817cf8b57
src
libsyntax/ext/tt
test/run-pass-fulldeps/auxiliary
@ -251,14 +251,22 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
|
||||
|
||||
pub enum ParseResult<T> {
|
||||
Success(T),
|
||||
/// Arm failed to match
|
||||
Failure(syntax_pos::Span, String),
|
||||
/// Arm failed to match. If the second parameter is `token::Eof`, it
|
||||
/// indicates an unexpected end of macro invocation. Otherwise, it
|
||||
/// indicates that no rules expected the given token.
|
||||
Failure(syntax_pos::Span, Token),
|
||||
/// Fatal error (malformed macro?). Abort compilation.
|
||||
Error(syntax_pos::Span, String)
|
||||
}
|
||||
|
||||
pub fn parse_failure_msg(tok: Token) -> String {
|
||||
match tok {
|
||||
token::Eof => "unexpected end of macro invocation".to_string(),
|
||||
_ => format!("no rules expected the token `{}`", pprust::token_to_string(&tok)),
|
||||
}
|
||||
}
|
||||
|
||||
pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
|
||||
pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>;
|
||||
|
||||
/// Perform a token equality check, ignoring syntax context (that is, an
|
||||
/// unhygienic comparison)
|
||||
@ -446,7 +454,7 @@ pub fn parse(sess: &ParseSess,
|
||||
} else if eof_eis.len() > 1 {
|
||||
return Error(sp, "ambiguity: multiple successful parses".to_string());
|
||||
} else {
|
||||
return Failure(sp, "unexpected end of macro invocation".to_string());
|
||||
return Failure(sp, token::Eof);
|
||||
}
|
||||
} else {
|
||||
if (!bb_eis.is_empty() && !next_eis.is_empty())
|
||||
@ -467,8 +475,7 @@ pub fn parse(sess: &ParseSess,
|
||||
}
|
||||
))
|
||||
} else if bb_eis.is_empty() && next_eis.is_empty() {
|
||||
return Failure(sp, format!("no rules expected the token `{}`",
|
||||
pprust::token_to_string(&tok)));
|
||||
return Failure(sp, tok);
|
||||
} else if !next_eis.is_empty() {
|
||||
/* Now process the next token */
|
||||
while !next_eis.is_empty() {
|
||||
|
@ -16,7 +16,7 @@ use ext::expand::{Expansion, ExpansionKind};
|
||||
use ext::placeholders;
|
||||
use ext::tt::macro_parser::{Success, Error, Failure};
|
||||
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||
use ext::tt::macro_parser::parse;
|
||||
use ext::tt::macro_parser::{parse, parse_failure_msg};
|
||||
use parse::ParseSess;
|
||||
use parse::lexer::new_tt_reader;
|
||||
use parse::parser::{Parser, Restrictions};
|
||||
@ -100,7 +100,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
|
||||
|
||||
// Which arm's failure should we report? (the one furthest along)
|
||||
let mut best_fail_spot = DUMMY_SP;
|
||||
let mut best_fail_msg = "internal error: ran no matchers".to_string();
|
||||
let mut best_fail_tok = None;
|
||||
|
||||
for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
|
||||
let lhs_tt = match *lhs {
|
||||
@ -139,9 +139,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
|
||||
macro_ident: name
|
||||
})
|
||||
}
|
||||
Failure(sp, msg) => if sp.lo >= best_fail_spot.lo {
|
||||
Failure(sp, tok) => if sp.lo >= best_fail_spot.lo {
|
||||
best_fail_spot = sp;
|
||||
best_fail_msg = msg;
|
||||
best_fail_tok = Some(tok);
|
||||
},
|
||||
Error(err_sp, ref msg) => {
|
||||
cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])
|
||||
@ -149,7 +149,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..]);
|
||||
let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers"));
|
||||
cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
|
||||
}
|
||||
|
||||
pub struct MacroRulesExpander;
|
||||
@ -227,8 +228,12 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
|
||||
|
||||
let argument_map = match parse(sess, &Vec::new(), arg_reader, &argument_gram) {
|
||||
Success(m) => m,
|
||||
Failure(sp, str) | Error(sp, str) => {
|
||||
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &str));
|
||||
Failure(sp, tok) => {
|
||||
let s = parse_failure_msg(tok);
|
||||
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
|
||||
}
|
||||
Error(sp, s) => {
|
||||
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@ use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||
use syntax::ext::tt::macro_parser::{Success, Failure, Error};
|
||||
use syntax::ext::tt::macro_parser::parse_failure_msg;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::Span;
|
||||
use rustc_plugin::Registry;
|
||||
@ -58,8 +59,11 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
Failure(_, s) | Error(_, s) => {
|
||||
panic!("expected Success, but got Error/Failure: {}", s);
|
||||
Failure(_, tok) => {
|
||||
panic!("expected Success, but got Failure: {}", parse_failure_msg(tok));
|
||||
}
|
||||
Error(_, s) => {
|
||||
panic!("expected Success, but got Error: {}", s);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user