expand: add recovery for parse_nt
This commit is contained in:
parent
3979964200
commit
21944b3a10
@ -84,7 +84,7 @@ use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
|
|||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
|
||||||
|
|
||||||
use rustc_errors::{FatalError, PResult};
|
use rustc_errors::PResult;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
@ -271,6 +271,7 @@ crate enum ParseResult<T> {
|
|||||||
Failure(Token, &'static str),
|
Failure(Token, &'static str),
|
||||||
/// Fatal error (malformed macro?). Abort compilation.
|
/// Fatal error (malformed macro?). Abort compilation.
|
||||||
Error(rustc_span::Span, String),
|
Error(rustc_span::Span, String),
|
||||||
|
ErrorReported,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `ParseResult` where the `Success` variant contains a mapping of
|
/// A `ParseResult` where the `Success` variant contains a mapping of
|
||||||
@ -652,6 +653,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
|
|||||||
Success(_) => {}
|
Success(_) => {}
|
||||||
Failure(token, msg) => return Failure(token, msg),
|
Failure(token, msg) => return Failure(token, msg),
|
||||||
Error(sp, msg) => return Error(sp, msg),
|
Error(sp, msg) => return Error(sp, msg),
|
||||||
|
ErrorReported => return ErrorReported,
|
||||||
}
|
}
|
||||||
|
|
||||||
// inner parse loop handled all cur_items, so it's empty
|
// inner parse loop handled all cur_items, so it's empty
|
||||||
@ -735,10 +737,11 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
|
|||||||
let mut item = bb_items.pop().unwrap();
|
let mut item = bb_items.pop().unwrap();
|
||||||
if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
|
if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
|
||||||
let match_cur = item.match_cur;
|
let match_cur = item.match_cur;
|
||||||
item.push_match(
|
let nt = match parse_nt(parser.to_mut(), span, ident.name) {
|
||||||
match_cur,
|
Err(()) => return ErrorReported,
|
||||||
MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))),
|
Ok(nt) => nt,
|
||||||
);
|
};
|
||||||
|
item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
|
||||||
item.idx += 1;
|
item.idx += 1;
|
||||||
item.match_cur += 1;
|
item.match_cur += 1;
|
||||||
} else {
|
} else {
|
||||||
@ -849,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// The parsed non-terminal.
|
/// The parsed non-terminal.
|
||||||
fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
|
fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result<Nonterminal, ()> {
|
||||||
// FIXME(Centril): Consider moving this to `parser.rs` to make
|
// FIXME(Centril): Consider moving this to `parser.rs` to make
|
||||||
// the visibilities of the methods used below `pub(super)` at most.
|
// the visibilities of the methods used below `pub(super)` at most.
|
||||||
|
|
||||||
if name == sym::tt {
|
if name == sym::tt {
|
||||||
return token::NtTT(p.parse_token_tree());
|
return Ok(token::NtTT(p.parse_token_tree()));
|
||||||
}
|
|
||||||
match parse_nt_inner(p, sp, name) {
|
|
||||||
Ok(nt) => nt,
|
|
||||||
Err(mut err) => {
|
|
||||||
err.emit();
|
|
||||||
FatalError.raise();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
parse_nt_inner(p, sp, name).map_err(|mut err| {
|
||||||
|
err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name))
|
||||||
|
.emit()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> {
|
fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> {
|
||||||
|
@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF
|
|||||||
use crate::mbe;
|
use crate::mbe;
|
||||||
use crate::mbe::macro_check;
|
use crate::mbe::macro_check;
|
||||||
use crate::mbe::macro_parser::parse_tt;
|
use crate::mbe::macro_parser::parse_tt;
|
||||||
use crate::mbe::macro_parser::{Error, Failure, Success};
|
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success};
|
||||||
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
|
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
|
||||||
use crate::mbe::transcribe::transcribe;
|
use crate::mbe::transcribe::transcribe;
|
||||||
|
|
||||||
@ -317,6 +317,7 @@ fn generic_extension<'cx>(
|
|||||||
cx.struct_span_err(span, &msg).emit();
|
cx.struct_span_err(span, &msg).emit();
|
||||||
return DummyResult::any(span);
|
return DummyResult::any(span);
|
||||||
}
|
}
|
||||||
|
ErrorReported => return DummyResult::any(sp),
|
||||||
}
|
}
|
||||||
|
|
||||||
// The matcher was not `Success(..)`ful.
|
// The matcher was not `Success(..)`ful.
|
||||||
@ -448,6 +449,9 @@ pub fn compile_declarative_macro(
|
|||||||
sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit();
|
sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit();
|
||||||
return mk_syn_ext(Box::new(MacroRulesDummyExpander));
|
return mk_syn_ext(Box::new(MacroRulesDummyExpander));
|
||||||
}
|
}
|
||||||
|
ErrorReported => {
|
||||||
|
return mk_syn_ext(Box::new(MacroRulesDummyExpander));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut valid = true;
|
let mut valid = true;
|
||||||
|
@ -42,6 +42,11 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
|
|||||||
LL |
|
LL |
|
||||||
LL | fn main() {}
|
LL | fn main() {}
|
||||||
| ^^ unexpected token
|
| ^^ unexpected token
|
||||||
|
|
|
||||||
|
::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | ($left:expr, $right:expr) => ({
|
||||||
|
| ---------- while parsing argument for this `expr` macro fragment
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
10
src/test/ui/parser/nt-parsing-has-recovery.rs
Normal file
10
src/test/ui/parser/nt-parsing-has-recovery.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
macro_rules! foo {
|
||||||
|
($e:expr) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
foo!(1 + @); //~ ERROR expected expression, found `@`
|
||||||
|
foo!(1 + @); //~ ERROR expected expression, found `@`
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||||
|
}
|
29
src/test/ui/parser/nt-parsing-has-recovery.stderr
Normal file
29
src/test/ui/parser/nt-parsing-has-recovery.stderr
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
error: expected expression, found `@`
|
||||||
|
--> $DIR/nt-parsing-has-recovery.rs:5:10
|
||||||
|
|
|
||||||
|
LL | ($e:expr) => {}
|
||||||
|
| ------- while parsing argument for this `expr` macro fragment
|
||||||
|
...
|
||||||
|
LL | foo!(1 + @);
|
||||||
|
| ^ expected expression
|
||||||
|
|
||||||
|
error: expected expression, found `@`
|
||||||
|
--> $DIR/nt-parsing-has-recovery.rs:6:10
|
||||||
|
|
|
||||||
|
LL | ($e:expr) => {}
|
||||||
|
| ------- while parsing argument for this `expr` macro fragment
|
||||||
|
...
|
||||||
|
LL | foo!(1 + @);
|
||||||
|
| ^ expected expression
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/nt-parsing-has-recovery.rs:9:33
|
||||||
|
|
|
||||||
|
LL | let _recovery_witness: () = 0;
|
||||||
|
| -- ^ expected `()`, found integer
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user