about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-03-17 14:13:32 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-03-24 06:28:56 +0100
commit21944b3a108784eda5d27f2ca3b6d3769fe51a57 (patch)
treef1b7a21076ef80174b4a69815c2799083ee86c0c /src
parent397996420040fb7245f1f5e09a8ec441522183c0 (diff)
downloadrust-21944b3a108784eda5d27f2ca3b6d3769fe51a57.tar.gz
rust-21944b3a108784eda5d27f2ca3b6d3769fe51a57.zip
expand: add recovery for parse_nt
Diffstat (limited to 'src')
-rw-r--r--src/librustc_expand/mbe/macro_parser.rs29
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs6
-rw-r--r--src/test/ui/parser/issue-62894.stderr5
-rw-r--r--src/test/ui/parser/nt-parsing-has-recovery.rs10
-rw-r--r--src/test/ui/parser/nt-parsing-has-recovery.stderr29
5 files changed, 63 insertions, 16 deletions
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index 0d777d88cad..e868b7e36aa 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -84,7 +84,7 @@ use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol};
 
-use rustc_errors::{FatalError, PResult};
+use rustc_errors::PResult;
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 
@@ -271,6 +271,7 @@ crate enum ParseResult<T> {
     Failure(Token, &'static str),
     /// Fatal error (malformed macro?). Abort compilation.
     Error(rustc_span::Span, String),
+    ErrorReported,
 }
 
 /// 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(_) => {}
             Failure(token, msg) => return Failure(token, msg),
             Error(sp, msg) => return Error(sp, msg),
+            ErrorReported => return ErrorReported,
         }
 
         // 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();
             if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
                 let match_cur = item.match_cur;
-                item.push_match(
-                    match_cur,
-                    MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))),
-                );
+                let nt = match parse_nt(parser.to_mut(), span, ident.name) {
+                    Err(()) => return ErrorReported,
+                    Ok(nt) => nt,
+                };
+                item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt)));
                 item.idx += 1;
                 item.match_cur += 1;
             } else {
@@ -849,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
 /// # Returns
 ///
 /// 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
     // the visibilities of the methods used below `pub(super)` at most.
-
     if name == sym::tt {
-        return token::NtTT(p.parse_token_tree());
-    }
-    match parse_nt_inner(p, sp, name) {
-        Ok(nt) => nt,
-        Err(mut err) => {
-            err.emit();
-            FatalError.raise();
-        }
+        return Ok(token::NtTT(p.parse_token_tree()));
     }
+    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> {
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index 6377347585c..43bc72090bc 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF
 use crate::mbe;
 use crate::mbe::macro_check;
 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::transcribe::transcribe;
 
@@ -317,6 +317,7 @@ fn generic_extension<'cx>(
                 cx.struct_span_err(span, &msg).emit();
                 return DummyResult::any(span);
             }
+            ErrorReported => return DummyResult::any(sp),
         }
 
         // 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();
             return mk_syn_ext(Box::new(MacroRulesDummyExpander));
         }
+        ErrorReported => {
+            return mk_syn_ext(Box::new(MacroRulesDummyExpander));
+        }
     };
 
     let mut valid = true;
diff --git a/src/test/ui/parser/issue-62894.stderr b/src/test/ui/parser/issue-62894.stderr
index 6db380f7a7f..73e3552e3ec 100644
--- a/src/test/ui/parser/issue-62894.stderr
+++ b/src/test/ui/parser/issue-62894.stderr
@@ -42,6 +42,11 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
 LL | 
 LL | fn main() {}
    | ^^ 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
 
diff --git a/src/test/ui/parser/nt-parsing-has-recovery.rs b/src/test/ui/parser/nt-parsing-has-recovery.rs
new file mode 100644
index 00000000000..ccbeb398af5
--- /dev/null
+++ b/src/test/ui/parser/nt-parsing-has-recovery.rs
@@ -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
+}
diff --git a/src/test/ui/parser/nt-parsing-has-recovery.stderr b/src/test/ui/parser/nt-parsing-has-recovery.stderr
new file mode 100644
index 00000000000..263c4ad5361
--- /dev/null
+++ b/src/test/ui/parser/nt-parsing-has-recovery.stderr
@@ -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`.