Skip to content

Commit 83313e4

Browse files
committed
expand: add recovery for parse_nt
1 parent 5a42b65 commit 83313e4

File tree

5 files changed

+63
-16
lines changed

5 files changed

+63
-16
lines changed

src/librustc_expand/mbe/macro_parser.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
8484
use rustc_session::parse::ParseSess;
8585
use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
8686

87-
use rustc_errors::{FatalError, PResult};
87+
use rustc_errors::PResult;
8888
use rustc_span::Span;
8989
use smallvec::{smallvec, SmallVec};
9090

@@ -271,6 +271,7 @@ crate enum ParseResult<T> {
271271
Failure(Token, &'static str),
272272
/// Fatal error (malformed macro?). Abort compilation.
273273
Error(rustc_span::Span, String),
274+
ErrorReported,
274275
}
275276

276277
/// 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
652653
Success(_) => {}
653654
Failure(token, msg) => return Failure(token, msg),
654655
Error(sp, msg) => return Error(sp, msg),
656+
ErrorReported => return ErrorReported,
655657
}
656658

657659
// 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
735737
let mut item = bb_items.pop().unwrap();
736738
if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
737739
let match_cur = item.match_cur;
738-
item.push_match(
739-
match_cur,
740-
MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))),
741-
);
740+
let nt = match parse_nt(parser.to_mut(), span, ident.name) {
741+
Err(()) => return ErrorReported,
742+
Ok(nt) => nt,
743+
};
744+
item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
742745
item.idx += 1;
743746
item.match_cur += 1;
744747
} else {
@@ -849,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
849852
/// # Returns
850853
///
851854
/// The parsed non-terminal.
852-
fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
855+
fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result<Nonterminal, ()> {
853856
// FIXME(Centril): Consider moving this to `parser.rs` to make
854857
// the visibilities of the methods used below `pub(super)` at most.
855-
856858
if name == sym::tt {
857-
return token::NtTT(p.parse_token_tree());
858-
}
859-
match parse_nt_inner(p, sp, name) {
860-
Ok(nt) => nt,
861-
Err(mut err) => {
862-
err.emit();
863-
FatalError.raise();
864-
}
859+
return Ok(token::NtTT(p.parse_token_tree()));
865860
}
861+
parse_nt_inner(p, sp, name).map_err(|mut err| {
862+
err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name))
863+
.emit()
864+
})
866865
}
867866

868867
fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> {

src/librustc_expand/mbe/macro_rules.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF
44
use crate::mbe;
55
use crate::mbe::macro_check;
66
use crate::mbe::macro_parser::parse_tt;
7-
use crate::mbe::macro_parser::{Error, Failure, Success};
7+
use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success};
88
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
99
use crate::mbe::transcribe::transcribe;
1010

@@ -323,6 +323,7 @@ fn generic_extension<'cx>(
323323
cx.struct_span_err(span, &msg).emit();
324324
return DummyResult::any(span);
325325
}
326+
ErrorReported => return DummyResult::any(sp),
326327
}
327328

328329
// The matcher was not `Success(..)`ful.
@@ -455,6 +456,9 @@ pub fn compile_declarative_macro(
455456
sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit();
456457
return mk_syn_ext(Box::new(MacroRulesDummyExpander));
457458
}
459+
ErrorReported => {
460+
return mk_syn_ext(Box::new(MacroRulesDummyExpander));
461+
}
458462
};
459463

460464
let mut valid = true;

src/test/ui/parser/issue-62894.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
4242
LL |
4343
LL | fn main() {}
4444
| ^^ unexpected token
45+
|
46+
::: $SRC_DIR/libcore/macros/mod.rs:LL:COL
47+
|
48+
LL | ($left:expr, $right:expr) => ({
49+
| ---------- while parsing argument for this `expr` macro fragment
4550

4651
error: aborting due to 4 previous errors
4752

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
macro_rules! foo {
2+
($e:expr) => {}
3+
}
4+
5+
foo!(1 + @); //~ ERROR expected expression, found `@`
6+
foo!(1 + @); //~ ERROR expected expression, found `@`
7+
8+
fn main() {
9+
let _recovery_witness: () = 0; //~ ERROR mismatched types
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error: expected expression, found `@`
2+
--> $DIR/nt-parsing-has-recovery.rs:5:10
3+
|
4+
LL | ($e:expr) => {}
5+
| ------- while parsing argument for this `expr` macro fragment
6+
...
7+
LL | foo!(1 + @);
8+
| ^ expected expression
9+
10+
error: expected expression, found `@`
11+
--> $DIR/nt-parsing-has-recovery.rs:6:10
12+
|
13+
LL | ($e:expr) => {}
14+
| ------- while parsing argument for this `expr` macro fragment
15+
...
16+
LL | foo!(1 + @);
17+
| ^ expected expression
18+
19+
error[E0308]: mismatched types
20+
--> $DIR/nt-parsing-has-recovery.rs:9:33
21+
|
22+
LL | let _recovery_witness: () = 0;
23+
| -- ^ expected `()`, found integer
24+
| |
25+
| expected due to this
26+
27+
error: aborting due to 3 previous errors
28+
29+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)