about summary refs log tree commit diff
path: root/src/librustc_parse
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-31 19:19:38 +0100
committerGitHub <noreply@github.com>2019-12-31 19:19:38 +0100
commit3cca3c6acef10201c6ff419979620ed8132a3965 (patch)
tree44cab948bf6c0ab0b991c99bf3894f60d3f7f539 /src/librustc_parse
parent50fb8480dbe65b14b48502c937eea66c4b5a6c31 (diff)
parent2e7806146c008742919124bf6ac9a37c3ece51bb (diff)
downloadrust-3cca3c6acef10201c6ff419979620ed8132a3965.tar.gz
rust-3cca3c6acef10201c6ff419979620ed8132a3965.zip
Rollup merge of #67744 - Centril:reduce-diversity, r=petrochenkov
parser: reduce diversity in error handling mechanisms

Instead of having e.g. `span_err`, `fatal`, etc., we prefer to move towards uniformly using `struct_span_err` thus making it harder to emit fatal and/or unstructured diagnostics.

This PR also de-fatalizes some diagnostics.

r? @estebank
Diffstat (limited to 'src/librustc_parse')
-rw-r--r--src/librustc_parse/parser/attr.rs13
-rw-r--r--src/librustc_parse/parser/diagnostics.rs47
-rw-r--r--src/librustc_parse/parser/expr.rs17
-rw-r--r--src/librustc_parse/parser/item.rs41
-rw-r--r--src/librustc_parse/parser/mod.rs6
-rw-r--r--src/librustc_parse/parser/module.rs12
-rw-r--r--src/librustc_parse/parser/pat.rs56
-rw-r--r--src/librustc_parse/parser/path.rs45
-rw-r--r--src/librustc_parse/parser/stmt.rs18
-rw-r--r--src/librustc_parse/parser/ty.rs4
10 files changed, 125 insertions, 134 deletions
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs
index 4b7f1e9a4d8..26df4f1c090 100644
--- a/src/librustc_parse/parser/attr.rs
+++ b/src/librustc_parse/parser/attr.rs
@@ -46,7 +46,8 @@ impl<'a> Parser<'a> {
                 token::DocComment(s) => {
                     let attr = self.mk_doc_comment(s);
                     if attr.style != ast::AttrStyle::Outer {
-                        let mut err = self.fatal("expected outer doc comment");
+                        let span = self.token.span;
+                        let mut err = self.struct_span_err(span, "expected outer doc comment");
                         err.note(
                             "inner doc comments like this (starting with \
                                   `//!` or `/*!`) can only appear before items",
@@ -133,7 +134,7 @@ impl<'a> Parser<'a> {
                             "previous outer attribute"
                         };
 
-                        let mut diagnostic = self.diagnostic().struct_span_err(attr_sp, reason);
+                        let mut diagnostic = self.struct_span_err(attr_sp, reason);
 
                         if let Some(prev_attr_sp) = prev_attr_sp {
                             diagnostic
@@ -156,7 +157,8 @@ impl<'a> Parser<'a> {
             }
             _ => {
                 let token_str = pprust::token_to_string(&self.token);
-                return Err(self.fatal(&format!("expected `#`, found `{}`", token_str)));
+                let msg = &format!("expected `#`, found `{}`", token_str);
+                return Err(self.struct_span_err(self.token.span, msg));
             }
         };
 
@@ -231,8 +233,7 @@ impl<'a> Parser<'a> {
 
         if !lit.kind.is_unsuffixed() {
             let msg = "suffixed literals are not allowed in attributes";
-            self.diagnostic()
-                .struct_span_err(lit.span, msg)
+            self.struct_span_err(lit.span, msg)
                 .help(
                     "instead of using a suffixed literal \
                                     (1u8, 1.0f32, etc.), use an unsuffixed version \
@@ -332,6 +333,6 @@ impl<'a> Parser<'a> {
 
         let found = pprust::token_to_string(&self.token);
         let msg = format!("expected unsuffixed literal or identifier, found `{}`", found);
-        Err(self.diagnostic().struct_span_err(self.token.span, &msg))
+        Err(self.struct_span_err(self.token.span, &msg))
     }
 }
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 578f816be58..05754357bc8 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -157,14 +157,6 @@ crate enum ConsumeClosingDelim {
 }
 
 impl<'a> Parser<'a> {
-    pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
-        self.span_fatal(self.token.span, m)
-    }
-
-    crate fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
-        self.sess.span_diagnostic.struct_span_fatal(sp, m)
-    }
-
     pub(super) fn span_fatal_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -173,14 +165,6 @@ impl<'a> Parser<'a> {
         err.span_err(sp, self.diagnostic())
     }
 
-    pub(super) fn bug(&self, m: &str) -> ! {
-        self.sess.span_diagnostic.span_bug(self.token.span, m)
-    }
-
-    pub(super) fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
-        self.sess.span_diagnostic.span_err(sp, m)
-    }
-
     pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
         self.sess.span_diagnostic.struct_span_err(sp, m)
     }
@@ -298,7 +282,7 @@ impl<'a> Parser<'a> {
             )
         };
         self.last_unexpected_token_span = Some(self.token.span);
-        let mut err = self.fatal(&msg_exp);
+        let mut err = self.struct_span_err(self.token.span, &msg_exp);
         let sp = if self.token == token::Eof {
             // This is EOF; don't want to point at the following char, but rather the last token.
             self.prev_span
@@ -502,18 +486,17 @@ impl<'a> Parser<'a> {
             let span = lo.until(self.token.span);
 
             let total_num_of_gt = number_of_gt + number_of_shr * 2;
-            self.diagnostic()
-                .struct_span_err(
-                    span,
-                    &format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
-                )
-                .span_suggestion(
-                    span,
-                    &format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
-                    String::new(),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+            self.struct_span_err(
+                span,
+                &format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
+            )
+            .span_suggestion(
+                span,
+                &format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
+                String::new(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
         }
     }
 
@@ -762,8 +745,7 @@ impl<'a> Parser<'a> {
         path.span = ty_span.to(self.prev_span);
 
         let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty));
-        self.diagnostic()
-            .struct_span_err(path.span, "missing angle brackets in associated item path")
+        self.struct_span_err(path.span, "missing angle brackets in associated item path")
             .span_suggestion(
                 // This is a best-effort recovery.
                 path.span,
@@ -1271,7 +1253,8 @@ impl<'a> Parser<'a> {
 
     pub(super) fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> {
         let token_str = super::token_descr(&self.token);
-        let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
+        let msg = &format!("expected `;` or `{{`, found {}", token_str);
+        let mut err = self.struct_span_err(self.token.span, msg);
         err.span_label(self.token.span, "expected `;` or `{`");
         Err(err)
     }
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index b51a4465b15..ab7c156e370 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -283,7 +283,7 @@ impl<'a> Parser<'a> {
                     self.mk_expr(span, aopexpr, AttrVec::new())
                 }
                 AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
-                    self.bug("AssocOp should have been handled by special case")
+                    self.span_bug(span, "AssocOp should have been handled by special case")
                 }
             };
 
@@ -822,7 +822,11 @@ impl<'a> Parser<'a> {
         } else {
             // Field access `expr.f`
             if let Some(args) = segment.args {
-                self.span_err(args.span(), "field expressions may not have generic arguments");
+                self.struct_span_err(
+                    args.span(),
+                    "field expressions may not have generic arguments",
+                )
+                .emit();
             }
 
             let span = lo.to(self.prev_span);
@@ -1133,7 +1137,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
         self.parse_opt_lit().ok_or_else(|| {
             let msg = format!("unexpected token: {}", super::token_descr(&self.token));
-            self.span_fatal(self.token.span, &msg)
+            self.struct_span_err(self.token.span, &msg)
         })
     }
 
@@ -1446,9 +1450,7 @@ impl<'a> Parser<'a> {
         self.struct_span_err(sp, "missing condition for `if` expression")
             .span_label(sp, "expected if condition here")
             .emit();
-        let expr = self.mk_expr_err(span);
-        let stmt = self.mk_stmt(span, ast::StmtKind::Expr(expr));
-        self.mk_block(vec![stmt], BlockCheckMode::Default, span)
+        self.mk_block_err(span)
     }
 
     /// Parses the condition of a `if` or `while` expression.
@@ -1915,8 +1917,7 @@ impl<'a> Parser<'a> {
             return;
         }
 
-        self.diagnostic()
-            .struct_span_err(self.token.span, "expected `:`, found `=`")
+        self.struct_span_err(self.token.span, "expected `:`, found `=`")
             .span_suggestion(
                 field_name.span.shrink_to_hi().to(self.token.span),
                 "replace equals symbol with a colon",
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 343c6667d47..e5a7361b12a 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -306,8 +306,7 @@ impl<'a> Parser<'a> {
                 // possible public struct definition where `struct` was forgotten
                 let ident = self.parse_ident().unwrap();
                 let msg = format!("add `struct` here to parse `{}` as a public struct", ident);
-                let mut err =
-                    self.diagnostic().struct_span_err(sp, "missing `struct` for struct definition");
+                let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
                 err.span_suggestion_short(
                     sp,
                     &msg,
@@ -335,7 +334,7 @@ impl<'a> Parser<'a> {
                 };
 
                 let msg = format!("missing `{}` for {} definition", kw, kw_name);
-                let mut err = self.diagnostic().struct_span_err(sp, &msg);
+                let mut err = self.struct_span_err(sp, &msg);
                 if !ambiguous {
                     self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
                     let suggestion =
@@ -375,7 +374,7 @@ impl<'a> Parser<'a> {
                     ("fn` or `struct", "function or struct", true)
                 };
                 let msg = format!("missing `{}` for {} definition", kw, kw_name);
-                let mut err = self.diagnostic().struct_span_err(sp, &msg);
+                let mut err = self.struct_span_err(sp, &msg);
                 if !ambiguous {
                     err.span_suggestion_short(
                         sp,
@@ -446,9 +445,7 @@ impl<'a> Parser<'a> {
         // FAILURE TO PARSE ITEM
         match visibility.node {
             VisibilityKind::Inherited => {}
-            _ => {
-                return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`"));
-            }
+            _ => return Err(self.struct_span_err(self.prev_span, "unmatched visibility `pub`")),
         }
 
         if !attributes_allowed && !attrs.is_empty() {
@@ -466,7 +463,7 @@ impl<'a> Parser<'a> {
             _ => "expected item after attributes",
         };
 
-        let mut err = self.diagnostic().struct_span_err(self.prev_span, message);
+        let mut err = self.struct_span_err(self.prev_span, message);
         if attrs.last().unwrap().is_doc_comment() {
             err.span_label(self.prev_span, "this doc comment doesn't document anything");
         }
@@ -536,7 +533,6 @@ impl<'a> Parser<'a> {
         //        ^^ `sp` below will point to this
         let sp = prev_span.between(self.prev_span);
         let mut err = self
-            .diagnostic()
             .struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type));
         err.span_label(sp, expected_kinds);
         err
@@ -619,7 +615,7 @@ impl<'a> Parser<'a> {
                     // This notably includes paths passed through `ty` macro fragments (#46438).
                     TyKind::Path(None, path) => path,
                     _ => {
-                        self.span_err(ty_first.span, "expected a trait, found type");
+                        self.struct_span_err(ty_first.span, "expected a trait, found type").emit();
                         err_path(ty_first.span)
                     }
                 };
@@ -1349,10 +1345,11 @@ impl<'a> Parser<'a> {
             body
         } else {
             let token_str = super::token_descr(&self.token);
-            let mut err = self.fatal(&format!(
+            let msg = &format!(
                 "expected `where`, `{{`, `(`, or `;` after struct name, found {}",
                 token_str
-            ));
+            );
+            let mut err = self.struct_span_err(self.token.span, msg);
             err.span_label(self.token.span, "expected `where`, `{`, `(`, or `;` after struct name");
             return Err(err);
         };
@@ -1375,8 +1372,8 @@ impl<'a> Parser<'a> {
             VariantData::Struct(fields, recovered)
         } else {
             let token_str = super::token_descr(&self.token);
-            let mut err = self
-                .fatal(&format!("expected `where` or `{{` after union name, found {}", token_str));
+            let msg = &format!("expected `where` or `{{` after union name, found {}", token_str);
+            let mut err = self.struct_span_err(self.token.span, msg);
             err.span_label(self.token.span, "expected `where` or `{` after union name");
             return Err(err);
         };
@@ -1412,10 +1409,8 @@ impl<'a> Parser<'a> {
             self.eat(&token::CloseDelim(token::Brace));
         } else {
             let token_str = super::token_descr(&self.token);
-            let mut err = self.fatal(&format!(
-                "expected `where`, or `{{` after struct name, found {}",
-                token_str
-            ));
+            let msg = &format!("expected `where`, or `{{` after struct name, found {}", token_str);
+            let mut err = self.struct_span_err(self.token.span, msg);
             err.span_label(self.token.span, "expected `where`, or `{` after struct name");
             return Err(err);
         }
@@ -1603,9 +1598,8 @@ impl<'a> Parser<'a> {
             VisibilityKind::Inherited => {}
             _ => {
                 let mut err = if self.token.is_keyword(sym::macro_rules) {
-                    let mut err = self
-                        .diagnostic()
-                        .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
+                    let mut err =
+                        self.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
                     err.span_suggestion(
                         sp,
                         "try exporting the macro",
@@ -1614,9 +1608,8 @@ impl<'a> Parser<'a> {
                     );
                     err
                 } else {
-                    let mut err = self
-                        .diagnostic()
-                        .struct_span_err(sp, "can't qualify macro invocation with `pub`");
+                    let mut err =
+                        self.struct_span_err(sp, "can't qualify macro invocation with `pub`");
                     err.help("try adjusting the macro to put `pub` inside the invocation");
                     err
                 };
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index 103bbe5dd76..ec6468f4f0a 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -884,7 +884,8 @@ impl<'a> Parser<'a> {
     pub fn bump(&mut self) {
         if self.prev_token_kind == PrevTokenKind::Eof {
             // Bumping after EOF is a bad sign, usually an infinite loop.
-            self.bug("attempted to bump the parser past EOF (may be stuck in a loop)");
+            let msg = "attempted to bump the parser past EOF (may be stuck in a loop)";
+            self.span_bug(self.token.span, msg);
         }
 
         self.prev_span = self.meta_var_span.take().unwrap_or(self.token.span);
@@ -1056,8 +1057,7 @@ impl<'a> Parser<'a> {
                     _ => unreachable!(),
                 };
                 let span = self.prev_span.to(self.token.span);
-                self.diagnostic()
-                    .struct_span_fatal(span, &format!("unknown macro variable `{}`", name))
+                self.struct_span_err(span, &format!("unknown macro variable `{}`", name))
                     .span_label(span, "unknown macro variable")
                     .emit();
                 self.bump();
diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs
index 3f54e0b6de0..84ffa6f7fcd 100644
--- a/src/librustc_parse/parser/module.rs
+++ b/src/librustc_parse/parser/module.rs
@@ -81,7 +81,8 @@ impl<'a> Parser<'a> {
         if !self.eat(term) {
             let token_str = super::token_descr(&self.token);
             if !self.maybe_consume_incorrect_semicolon(&items) {
-                let mut err = self.fatal(&format!("expected item, found {}", token_str));
+                let msg = &format!("expected item, found {}", token_str);
+                let mut err = self.struct_span_err(self.token.span, msg);
                 err.span_label(self.token.span, "expected item");
                 return Err(err);
             }
@@ -129,7 +130,7 @@ impl<'a> Parser<'a> {
             DirectoryOwnership::UnownedViaBlock => {
                 let msg = "Cannot declare a non-inline module inside a block \
                     unless it has a path attribute";
-                let mut err = self.diagnostic().struct_span_err(id_sp, msg);
+                let mut err = self.struct_span_err(id_sp, msg);
                 if paths.path_exists {
                     let msg = format!(
                         "Maybe `use` the module `{}` instead of redeclaring it",
@@ -140,9 +141,8 @@ impl<'a> Parser<'a> {
                 Err(err)
             }
             DirectoryOwnership::UnownedViaMod => {
-                let mut err = self
-                    .diagnostic()
-                    .struct_span_err(id_sp, "cannot declare a new module at this location");
+                let mut err =
+                    self.struct_span_err(id_sp, "cannot declare a new module at this location");
                 if !id_sp.is_dummy() {
                     let src_path = self.sess.source_map().span_to_filename(id_sp);
                     if let FileName::Real(src_path) = src_path {
@@ -263,7 +263,7 @@ impl<'a> Parser<'a> {
                 err.push_str(" -> ");
             }
             err.push_str(&path.to_string_lossy());
-            return Err(self.span_fatal(id_sp, &err[..]));
+            return Err(self.struct_span_err(id_sp, &err[..]));
         }
         included_mod_stack.push(path.clone());
         drop(included_mod_stack);
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index d2288b27a0c..e608b86c76a 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -673,7 +673,7 @@ impl<'a> Parser<'a> {
         let expected = expected.unwrap_or("pattern");
         let msg = format!("expected {}, found {}", expected, super::token_descr(&self.token));
 
-        let mut err = self.fatal(&msg);
+        let mut err = self.struct_span_err(self.token.span, &msg);
         err.span_label(self.token.span, format!("expected {}", expected));
 
         let sp = self.sess.source_map().start_point(self.token.span);
@@ -699,8 +699,7 @@ impl<'a> Parser<'a> {
         let range_span = lo.to(end.span);
         let begin = self.mk_expr(range_span, ExprKind::Err, AttrVec::new());
 
-        self.diagnostic()
-            .struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
+        self.struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
             .span_suggestion(
                 range_span,
                 "try using the minimum value for the type",
@@ -722,18 +721,17 @@ impl<'a> Parser<'a> {
             // Parsing e.g. `X..`.
             let range_span = begin.span.to(self.prev_span);
 
-            self.diagnostic()
-                .struct_span_err(
-                    range_span,
-                    &format!("`X{}` range patterns are not supported", form),
-                )
-                .span_suggestion(
-                    range_span,
-                    "try using the maximum value for the type",
-                    format!("{}{}MAX", pprust::expr_to_string(&begin), form),
-                    Applicability::HasPlaceholders,
-                )
-                .emit();
+            self.struct_span_err(
+                range_span,
+                &format!("`X{}` range patterns are not supported", form),
+            )
+            .span_suggestion(
+                range_span,
+                "try using the maximum value for the type",
+                format!("{}{}MAX", pprust::expr_to_string(&begin), form),
+                Applicability::HasPlaceholders,
+            )
+            .emit();
 
             Ok(self.mk_expr(range_span, ExprKind::Err, AttrVec::new()))
         }
@@ -798,7 +796,9 @@ impl<'a> Parser<'a> {
         // binding mode then we do not end up here, because the lookahead
         // will direct us over to `parse_enum_variant()`.
         if self.token == token::OpenDelim(token::Paren) {
-            return Err(self.span_fatal(self.prev_span, "expected identifier, found enum pattern"));
+            return Err(
+                self.struct_span_err(self.prev_span, "expected identifier, found enum pattern")
+            );
         }
 
         Ok(PatKind::Ident(binding_mode, ident, sub))
@@ -807,12 +807,8 @@ impl<'a> Parser<'a> {
     /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
     fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
         if qself.is_some() {
-            let msg = "unexpected `{` after qualified path";
-            let mut err = self.fatal(msg);
-            err.span_label(self.token.span, msg);
-            return Err(err);
+            return self.error_qpath_before_pat(&path, "{");
         }
-
         self.bump();
         let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
             e.emit();
@@ -826,15 +822,22 @@ impl<'a> Parser<'a> {
     /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
     fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
         if qself.is_some() {
-            let msg = "unexpected `(` after qualified path";
-            let mut err = self.fatal(msg);
-            err.span_label(self.token.span, msg);
-            return Err(err);
+            return self.error_qpath_before_pat(&path, "(");
         }
         let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?;
         Ok(PatKind::TupleStruct(path, fields))
     }
 
+    /// Error when there's a qualified path, e.g. `<Foo as Bar>::Baz`
+    /// as the path of e.g., a tuple or record struct pattern.
+    fn error_qpath_before_pat(&mut self, path: &Path, token: &str) -> PResult<'a, PatKind> {
+        let msg = &format!("unexpected `{}` after qualified path", token);
+        let mut err = self.struct_span_err(self.token.span, msg);
+        err.span_label(self.token.span, msg);
+        err.span_label(path.span, "the qualified path");
+        Err(err)
+    }
+
     /// Parses the fields of a struct-like pattern.
     fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<FieldPat>, bool)> {
         let mut fields = Vec::new();
@@ -877,7 +880,8 @@ impl<'a> Parser<'a> {
                     break;
                 }
                 let token_str = super::token_descr(&self.token);
-                let mut err = self.fatal(&format!("expected `}}`, found {}", token_str));
+                let msg = &format!("expected `}}`, found {}", token_str);
+                let mut err = self.struct_span_err(self.token.span, msg);
 
                 err.span_label(self.token.span, "expected `}`");
                 let mut comma_sp = None;
diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs
index e6c7d50fb4c..325ad56cd2a 100644
--- a/src/librustc_parse/parser/path.rs
+++ b/src/librustc_parse/parser/path.rs
@@ -93,7 +93,7 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtPath, |path| {
             if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
             {
-                self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
+                self.struct_span_err(path.span, "unexpected generic arguments in path").emit();
             }
             path
         });
@@ -325,24 +325,23 @@ impl<'a> Parser<'a> {
 
                 // Make a span over ${unmatched angle bracket count} characters.
                 let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
-                self.diagnostic()
-                    .struct_span_err(
-                        span,
-                        &format!(
-                            "unmatched angle bracket{}",
-                            pluralize!(snapshot.unmatched_angle_bracket_count)
-                        ),
-                    )
-                    .span_suggestion(
-                        span,
-                        &format!(
-                            "remove extra angle bracket{}",
-                            pluralize!(snapshot.unmatched_angle_bracket_count)
-                        ),
-                        String::new(),
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.struct_span_err(
+                    span,
+                    &format!(
+                        "unmatched angle bracket{}",
+                        pluralize!(snapshot.unmatched_angle_bracket_count)
+                    ),
+                )
+                .span_suggestion(
+                    span,
+                    &format!(
+                        "remove extra angle bracket{}",
+                        pluralize!(snapshot.unmatched_angle_bracket_count)
+                    ),
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
 
                 // Try again without unmatched angle bracket characters.
                 self.parse_generic_args()
@@ -407,9 +406,11 @@ impl<'a> Parser<'a> {
                     if self.token.is_bool_lit() {
                         self.parse_literal_maybe_minus()?
                     } else {
-                        return Err(
-                            self.fatal("identifiers may currently not be used for const generics")
-                        );
+                        let span = self.token.span;
+                        let msg = "identifiers may currently not be used for const generics";
+                        self.struct_span_err(span, msg).emit();
+                        let block = self.mk_block_err(span);
+                        self.mk_expr(span, ast::ExprKind::Block(block, None), ast::AttrVec::new())
                     }
                 } else {
                     self.parse_literal_maybe_minus()?
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 8270da6c023..bf092ed14e3 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -193,7 +193,8 @@ impl<'a> Parser<'a> {
             if self.prev_token_kind == PrevTokenKind::DocComment {
                 self.span_fatal_err(self.prev_span, Error::UselessDocComment).emit();
             } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
-                self.span_err(self.token.span, "expected statement after outer attribute");
+                self.struct_span_err(self.token.span, "expected statement after outer attribute")
+                    .emit();
             }
         }
     }
@@ -324,7 +325,7 @@ impl<'a> Parser<'a> {
     fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
         let sp = self.token.span;
         let tok = super::token_descr(&self.token);
-        let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok));
+        let mut e = self.struct_span_err(sp, &format!("expected `{{`, found {}", tok));
         let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;
 
         // Check to see if the user has written something like
@@ -397,10 +398,7 @@ impl<'a> Parser<'a> {
                     self.maybe_annotate_with_ascription(&mut err, false);
                     err.emit();
                     self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
-                    Some(self.mk_stmt(
-                        self.token.span,
-                        StmtKind::Expr(self.mk_expr_err(self.token.span)),
-                    ))
+                    Some(self.mk_stmt_err(self.token.span))
                 }
                 Ok(stmt) => stmt,
             };
@@ -478,4 +476,12 @@ impl<'a> Parser<'a> {
     pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
         Stmt { id: DUMMY_NODE_ID, kind, span }
     }
+
+    fn mk_stmt_err(&self, span: Span) -> Stmt {
+        self.mk_stmt(span, StmtKind::Expr(self.mk_expr_err(span)))
+    }
+
+    pub(super) fn mk_block_err(&self, span: Span) -> P<Block> {
+        self.mk_block(vec![self.mk_stmt_err(span)], BlockCheckMode::Default, span)
+    }
 }
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 049c077c3ce..4f7bcf01e1b 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -175,7 +175,9 @@ impl<'a> Parser<'a> {
                 {
                     let path = match bounds.remove(0) {
                         GenericBound::Trait(pt, ..) => pt.trait_ref.path,
-                        GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"),
+                        GenericBound::Outlives(..) => {
+                            self.span_bug(ty.span, "unexpected lifetime bound")
+                        }
                     };
                     self.parse_remaining_bounds(Vec::new(), path, lo, true)
                 }