about summary refs log tree commit diff
path: root/compiler/rustc_parse/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_parse/src')
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs81
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs6
-rw-r--r--compiler/rustc_parse/src/lib.rs6
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs36
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs68
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs63
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs24
-rw-r--r--compiler/rustc_parse/src/parser/item.rs87
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs6
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs24
-rw-r--r--compiler/rustc_parse/src/parser/path.rs4
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs6
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs21
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs6
14 files changed, 211 insertions, 227 deletions
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 4819ed6021d..a45bc581240 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>(
     let (stream, res, unmatched_delims) =
         tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
     match res {
-        Ok(_open_spacing) if unmatched_delims.is_empty() => Ok(stream),
+        Ok(()) if unmatched_delims.is_empty() => Ok(stream),
         _ => {
             // Return error if there are unmatched delimiters or unclosed delimiters.
             // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
@@ -249,9 +249,9 @@ impl<'a> StringReader<'a> {
                     let lifetime_name = self.str_from(start);
                     if starts_with_number {
                         let span = self.mk_sp(start, self.pos);
-                        let mut diag = self.dcx().struct_err("lifetimes cannot start with a number");
-                        diag.span(span);
-                        diag.stash(span, StashKey::LifetimeIsChar);
+                        self.dcx().struct_err("lifetimes cannot start with a number")
+                            .span_mv(span)
+                            .stash(span, StashKey::LifetimeIsChar);
                     }
                     let ident = Symbol::intern(lifetime_name);
                     token::Lifetime(ident)
@@ -395,51 +395,58 @@ impl<'a> StringReader<'a> {
         match kind {
             rustc_lexer::LiteralKind::Char { terminated } => {
                 if !terminated {
-                    self.dcx().span_fatal_with_code(
-                        self.mk_sp(start, end),
-                        "unterminated character literal",
-                        error_code!(E0762),
-                    )
+                    self.dcx()
+                        .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
+                        .code_mv(error_code!(E0762))
+                        .emit()
                 }
                 self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
             }
             rustc_lexer::LiteralKind::Byte { terminated } => {
                 if !terminated {
-                    self.dcx().span_fatal_with_code(
-                        self.mk_sp(start + BytePos(1), end),
-                        "unterminated byte constant",
-                        error_code!(E0763),
-                    )
+                    self.dcx()
+                        .struct_span_fatal(
+                            self.mk_sp(start + BytePos(1), end),
+                            "unterminated byte constant",
+                        )
+                        .code_mv(error_code!(E0763))
+                        .emit()
                 }
                 self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
             }
             rustc_lexer::LiteralKind::Str { terminated } => {
                 if !terminated {
-                    self.dcx().span_fatal_with_code(
-                        self.mk_sp(start, end),
-                        "unterminated double quote string",
-                        error_code!(E0765),
-                    )
+                    self.dcx()
+                        .struct_span_fatal(
+                            self.mk_sp(start, end),
+                            "unterminated double quote string",
+                        )
+                        .code_mv(error_code!(E0765))
+                        .emit()
                 }
                 self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
             }
             rustc_lexer::LiteralKind::ByteStr { terminated } => {
                 if !terminated {
-                    self.dcx().span_fatal_with_code(
-                        self.mk_sp(start + BytePos(1), end),
-                        "unterminated double quote byte string",
-                        error_code!(E0766),
-                    )
+                    self.dcx()
+                        .struct_span_fatal(
+                            self.mk_sp(start + BytePos(1), end),
+                            "unterminated double quote byte string",
+                        )
+                        .code_mv(error_code!(E0766))
+                        .emit()
                 }
                 self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
             }
             rustc_lexer::LiteralKind::CStr { terminated } => {
                 if !terminated {
-                    self.dcx().span_fatal_with_code(
-                        self.mk_sp(start + BytePos(1), end),
-                        "unterminated C string",
-                        error_code!(E0767),
-                    )
+                    self.dcx()
+                        .struct_span_fatal(
+                            self.mk_sp(start + BytePos(1), end),
+                            "unterminated C string",
+                        )
+                        .code_mv(error_code!(E0767))
+                        .emit()
                 }
                 self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
             }
@@ -573,12 +580,9 @@ impl<'a> StringReader<'a> {
         possible_offset: Option<u32>,
         found_terminators: u32,
     ) -> ! {
-        let mut err = self.dcx().struct_span_fatal_with_code(
-            self.mk_sp(start, start),
-            "unterminated raw string",
-            error_code!(E0748),
-        );
-
+        let mut err =
+            self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string");
+        err.code(error_code!(E0748));
         err.span_label(self.mk_sp(start, start), "unterminated raw string");
 
         if n_hashes > 0 {
@@ -609,11 +613,8 @@ impl<'a> StringReader<'a> {
             None => "unterminated block comment",
         };
         let last_bpos = self.pos;
-        let mut err = self.dcx().struct_span_fatal_with_code(
-            self.mk_sp(start, last_bpos),
-            msg,
-            error_code!(E0758),
-        );
+        let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg);
+        err.code(error_code!(E0758));
         let mut nested_block_comment_open_idxs = vec![];
         let mut last_nested_block_comment_idxs = None;
         let mut content_chars = self.str_from(start).char_indices().peekable();
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index b6cccd275ee..64b3928689a 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -277,9 +277,9 @@ impl<'a> TokenTreesReader<'a> {
             parser.bump();
         }
         if !diff_errs.is_empty() {
-            errs.iter_mut().for_each(|err| {
-                err.delay_as_bug();
-            });
+            for err in errs {
+                err.cancel();
+            }
             return diff_errs;
         }
         return errs;
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 579c3cffcfb..d7604d7cebc 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -245,9 +245,9 @@ pub fn parse_cfg_attr(
             crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim);
             match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
                 Ok(r) => return Some(r),
-                Err(mut e) => {
-                    e.help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
-                        .note(CFG_ATTR_NOTE_REF)
+                Err(e) => {
+                    e.help_mv(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
+                        .note_mv(CFG_ATTR_NOTE_REF)
                         .emit();
                 }
             }
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index c8629069968..cec657f7b67 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -55,11 +55,10 @@ impl<'a> Parser<'a> {
             } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
                 if attr_style != ast::AttrStyle::Outer {
                     let span = self.token.span;
-                    let mut err = self.dcx().struct_span_err_with_code(
-                        span,
-                        fluent::parse_inner_doc_comment_not_permitted,
-                        error_code!(E0753),
-                    );
+                    let mut err = self
+                        .dcx()
+                        .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted);
+                    err.code(error_code!(E0753));
                     if let Some(replacement_span) = self.annotate_following_item_if_applicable(
                         &mut err,
                         span,
@@ -200,23 +199,22 @@ impl<'a> Parser<'a> {
         if let InnerAttrPolicy::Forbidden(reason) = policy {
             let mut diag = match reason.as_ref().copied() {
                 Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
-                    let mut diag = self.dcx().struct_span_err(
-                        attr_sp,
-                        fluent::parse_inner_attr_not_permitted_after_outer_doc_comment,
-                    );
-                    diag.span_label(attr_sp, fluent::parse_label_attr)
-                        .span_label(prev_doc_comment_span, fluent::parse_label_prev_doc_comment);
-                    diag
+                    self.dcx()
+                        .struct_span_err(
+                            attr_sp,
+                            fluent::parse_inner_attr_not_permitted_after_outer_doc_comment,
+                        )
+                        .span_label_mv(attr_sp, fluent::parse_label_attr)
+                        .span_label_mv(prev_doc_comment_span, fluent::parse_label_prev_doc_comment)
                 }
-                Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => {
-                    let mut diag = self.dcx().struct_span_err(
+                Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self
+                    .dcx()
+                    .struct_span_err(
                         attr_sp,
                         fluent::parse_inner_attr_not_permitted_after_outer_attr,
-                    );
-                    diag.span_label(attr_sp, fluent::parse_label_attr)
-                        .span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr);
-                    diag
-                }
+                    )
+                    .span_label_mv(attr_sp, fluent::parse_label_attr)
+                    .span_label_mv(prev_outer_attr_sp, fluent::parse_label_prev_attr),
                 Some(InnerAttrForbiddenReason::InCodeBlock) | None => {
                     self.dcx().struct_span_err(attr_sp, fluent::parse_inner_attr_not_permitted)
                 }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index aed5e11133b..a9cf26d991c 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -34,8 +34,8 @@ use rustc_ast::{
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalError,
-    PResult,
+    pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, FatalError, PErr, PResult,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
@@ -896,7 +896,7 @@ impl<'a> Parser<'a> {
             let struct_expr = snapshot.parse_expr_struct(None, path, false);
             let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
             return Some(match (struct_expr, block_tail) {
-                (Ok(expr), Err(mut err)) => {
+                (Ok(expr), Err(err)) => {
                     // We have encountered the following:
                     // fn foo() -> Foo {
                     //     field: value,
@@ -1049,9 +1049,9 @@ impl<'a> Parser<'a> {
         &mut self,
         segment: &PathSegment,
         end: &[&TokenKind],
-    ) -> bool {
+    ) -> Option<ErrorGuaranteed> {
         if !self.may_recover() {
-            return false;
+            return None;
         }
 
         // This function is intended to be invoked after parsing a path segment where there are two
@@ -1086,7 +1086,7 @@ impl<'a> Parser<'a> {
             parsed_angle_bracket_args,
         );
         if !parsed_angle_bracket_args {
-            return false;
+            return None;
         }
 
         // Keep the span at the start so we can highlight the sequence of `>` characters to be
@@ -1124,7 +1124,7 @@ impl<'a> Parser<'a> {
             number_of_gt, number_of_shr,
         );
         if number_of_gt < 1 && number_of_shr < 1 {
-            return false;
+            return None;
         }
 
         // Finally, double check that we have our end token as otherwise this is the
@@ -1139,10 +1139,9 @@ impl<'a> Parser<'a> {
             let span = lo.until(self.token.span);
 
             let num_extra_brackets = number_of_gt + number_of_shr * 2;
-            self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets });
-            return true;
+            return Some(self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets }));
         }
-        false
+        None
     }
 
     /// Check if a method call with an intended turbofish has been written without surrounding
@@ -1212,29 +1211,32 @@ impl<'a> Parser<'a> {
             match x {
                 Ok((_, _, false)) => {
                     if self.eat(&token::Gt) {
+                        // We made sense of it. Improve the error message.
                         e.span_suggestion_verbose(
                             binop.span.shrink_to_lo(),
                             fluent::parse_sugg_turbofish_syntax,
                             "::",
                             Applicability::MaybeIncorrect,
-                        )
-                        .emit();
+                        );
                         match self.parse_expr() {
                             Ok(_) => {
+                                // The subsequent expression is valid. Mark
+                                // `expr` as erroneous and emit `e` now, but
+                                // return `Ok` so parsing can continue.
+                                e.emit();
                                 *expr = self.mk_expr_err(expr.span.to(self.prev_token.span));
                                 return Ok(());
                             }
                             Err(err) => {
-                                *expr = self.mk_expr_err(expr.span);
                                 err.cancel();
                             }
                         }
                     }
                 }
+                Ok((_, _, true)) => {}
                 Err(err) => {
                     err.cancel();
                 }
-                _ => {}
             }
         }
         Err(e)
@@ -2041,17 +2043,12 @@ impl<'a> Parser<'a> {
         &mut self,
         delim: Delimiter,
         lo: Span,
-        result: PResult<'a, P<Expr>>,
+        err: PErr<'a>,
     ) -> P<Expr> {
-        match result {
-            Ok(x) => x,
-            Err(mut err) => {
-                err.emit();
-                // Recover from parse error, callers expect the closing delim to be consumed.
-                self.consume_block(delim, ConsumeClosingDelim::Yes);
-                self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err)
-            }
-        }
+        err.emit();
+        // Recover from parse error, callers expect the closing delim to be consumed.
+        self.consume_block(delim, ConsumeClosingDelim::Yes);
+        self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err)
     }
 
     /// Eats tokens until we can be relatively sure we reached the end of the
@@ -2470,7 +2467,7 @@ impl<'a> Parser<'a> {
                     return Ok(true); // Continue
                 }
             }
-            Err(mut err) => {
+            Err(err) => {
                 args.push(arg);
                 // We will emit a more generic error later.
                 err.delay_as_bug();
@@ -2848,15 +2845,16 @@ impl<'a> Parser<'a> {
         let label = self.eat_label().expect("just checked if a label exists");
         self.bump(); // eat `:`
         let span = label.ident.span.to(self.prev_token.span);
-        let mut err = self.dcx().struct_span_err(span, "block label not supported here");
-        err.span_label(span, "not supported here");
-        err.tool_only_span_suggestion(
-            label.ident.span.until(self.token.span),
-            "remove this block label",
-            "",
-            Applicability::MachineApplicable,
-        );
-        err.emit();
+        self.dcx()
+            .struct_span_err(span, "block label not supported here")
+            .span_label_mv(span, "not supported here")
+            .tool_only_span_suggestion_mv(
+                label.ident.span.until(self.token.span),
+                "remove this block label",
+                "",
+                Applicability::MachineApplicable,
+            )
+            .emit();
         true
     }
 
@@ -2946,7 +2944,7 @@ impl<'a> Parser<'a> {
     }
 
     pub fn recover_diff_marker(&mut self) {
-        if let Err(mut err) = self.err_diff_marker() {
+        if let Err(err) = self.err_diff_marker() {
             err.emit();
             FatalError.raise();
         }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 880743ddd3c..db777266b59 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -127,7 +127,7 @@ impl<'a> Parser<'a> {
     fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
         match self.parse_expr_res(restrictions, None) {
             Ok(expr) => Ok(expr),
-            Err(mut err) => match self.token.ident() {
+            Err(err) => match self.token.ident() {
                 Some((Ident { name: kw::Underscore, .. }, false))
                     if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) =>
                 {
@@ -1272,15 +1272,13 @@ impl<'a> Parser<'a> {
         };
         let open_paren = self.token.span;
 
-        let mut seq = self
+        let seq = self
             .parse_expr_paren_seq()
             .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
-        if let Some(expr) =
-            self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
-        {
-            return expr;
+        match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) {
+            Ok(expr) => expr,
+            Err(err) => self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err),
         }
-        self.recover_seq_parse_error(Delimiter::Parenthesis, lo, seq)
     }
 
     /// If we encounter a parser state that looks like the user has written a `struct` literal with
@@ -1290,14 +1288,11 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         open_paren: Span,
-        seq: &mut PResult<'a, P<Expr>>,
+        seq: PResult<'a, P<Expr>>,
         snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
-    ) -> Option<P<Expr>> {
-        if !self.may_recover() {
-            return None;
-        }
-        match (seq.as_mut(), snapshot) {
-            (Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
+    ) -> PResult<'a, P<Expr>> {
+        match (self.may_recover(), seq, snapshot) {
+            (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
                 snapshot.bump(); // `(`
                 match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) {
                     Ok((fields, ..))
@@ -1315,11 +1310,13 @@ impl<'a> Parser<'a> {
                         if !fields.is_empty() &&
                             // `token.kind` should not be compared here.
                             // This is because the `snapshot.token.kind` is treated as the same as
-                            // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different.
+                            // that of the open delim in `TokenTreesReader::parse_token_tree`, even
+                            // if they are different.
                             self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")")
                         {
-                            let mut replacement_err =
-                                self.dcx().create_err(errors::ParenthesesWithStructFields {
+                            err.cancel();
+                            self.dcx()
+                                .create_err(errors::ParenthesesWithStructFields {
                                     span,
                                     r#type: path,
                                     braces_for_struct: errors::BracesForStructLiteral {
@@ -1332,23 +1329,22 @@ impl<'a> Parser<'a> {
                                             .map(|field| field.span.until(field.expr.span))
                                             .collect(),
                                     },
-                                });
-                            replacement_err.emit();
-
-                            let old_err = mem::replace(err, replacement_err);
-                            old_err.cancel();
+                                })
+                                .emit();
                         } else {
                             err.emit();
                         }
-                        return Some(self.mk_expr_err(span));
+                        Ok(self.mk_expr_err(span))
+                    }
+                    Ok(_) => Err(err),
+                    Err(err2) => {
+                        err2.cancel();
+                        Err(err)
                     }
-                    Ok(_) => {}
-                    Err(err) => err.cancel(),
                 }
             }
-            _ => {}
+            (_, seq, _) => seq,
         }
-        None
     }
 
     /// Parse an indexing expression `expr[...]`.
@@ -1552,7 +1548,7 @@ impl<'a> Parser<'a> {
         ) {
             Ok(x) => x,
             Err(err) => {
-                return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, Err(err)));
+                return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err));
             }
         };
         let kind = if es.len() == 1 && !trailing_comma {
@@ -1756,9 +1752,8 @@ impl<'a> Parser<'a> {
         mk_lit_char: impl FnOnce(Symbol, Span) -> L,
         err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>,
     ) -> L {
-        if let Some(mut diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
-        {
-            diag.span_suggestion_verbose(
+        if let Some(diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) {
+            diag.span_suggestion_verbose_mv(
                 lifetime.span.shrink_to_hi(),
                 "add `'` to close the char literal",
                 "'",
@@ -1767,7 +1762,7 @@ impl<'a> Parser<'a> {
             .emit();
         } else {
             err(self)
-                .span_suggestion_verbose(
+                .span_suggestion_verbose_mv(
                     lifetime.span.shrink_to_hi(),
                     "add `'` to close the char literal",
                     "'",
@@ -2903,7 +2898,7 @@ impl<'a> Parser<'a> {
         while self.token != token::CloseDelim(Delimiter::Brace) {
             match self.parse_arm() {
                 Ok(arm) => arms.push(arm),
-                Err(mut e) => {
+                Err(e) => {
                     // Recover by skipping to the end of the block.
                     e.emit();
                     self.recover_stmt();
@@ -3437,7 +3432,7 @@ impl<'a> Parser<'a> {
                 }
                 match self.parse_expr() {
                     Ok(e) => base = ast::StructRest::Base(e),
-                    Err(mut e) if recover => {
+                    Err(e) if recover => {
                         e.emit();
                         self.recover_stmt();
                     }
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 7e243c1c32a..66aa8cbcda4 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -77,7 +77,6 @@ impl<'a> Parser<'a> {
                                     Applicability::MachineApplicable,
                                 );
                             }
-                            err.emit();
                             return Err(err);
                         }
                     }
@@ -141,17 +140,18 @@ impl<'a> Parser<'a> {
         // Parse optional const generics default value.
         let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None };
 
-        let mut err = self.dcx().struct_span_err(
-            mistyped_const_ident.span,
-            format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
-        );
-        err.span_suggestion_verbose(
-            mistyped_const_ident.span,
-            "use the `const` keyword",
-            kw::Const.as_str(),
-            Applicability::MachineApplicable,
-        );
-        err.emit();
+        self.dcx()
+            .struct_span_err(
+                mistyped_const_ident.span,
+                format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
+            )
+            .span_suggestion_verbose_mv(
+                mistyped_const_ident.span,
+                "use the `const` keyword",
+                kw::Const.as_str(),
+                Applicability::MachineApplicable,
+            )
+            .emit();
 
         Ok(GenericParam {
             ident,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 2ce27ff66e1..fed3c83a81d 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -739,11 +739,14 @@ impl<'a> Parser<'a> {
                     break;
                 }
                 Ok(Some(item)) => items.extend(item),
-                Err(mut err) => {
+                Err(err) => {
                     self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
-                    err.span_label(open_brace_span, "while parsing this item list starting here")
-                        .span_label(self.prev_token.span, "the item list ends here")
-                        .emit();
+                    err.span_label_mv(
+                        open_brace_span,
+                        "while parsing this item list starting here",
+                    )
+                    .span_label_mv(self.prev_token.span, "the item list ends here")
+                    .emit();
                     break;
                 }
             }
@@ -762,8 +765,8 @@ impl<'a> Parser<'a> {
                     E0584,
                     "found a documentation comment that doesn't document anything",
                 )
-                .span_label(self.token.span, "this doc comment doesn't document anything")
-                .help(
+                .span_label_mv(self.token.span, "this doc comment doesn't document anything")
+                .help_mv(
                     "doc comments must come before what they document, if a comment was \
                     intended use `//`",
                 )
@@ -1106,8 +1109,7 @@ impl<'a> Parser<'a> {
             && self.token.is_keyword(kw::Unsafe)
             && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace))
         {
-            let mut err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err();
-            err.emit();
+            self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit();
             unsafety = Unsafe::Yes(self.token.span);
             self.eat_keyword(kw::Unsafe);
         }
@@ -1198,7 +1200,7 @@ impl<'a> Parser<'a> {
         defaultness: Defaultness,
     ) -> PResult<'a, ItemInfo> {
         let impl_span = self.token.span;
-        let mut err = self.expected_ident_found_err();
+        let err = self.expected_ident_found_err();
 
         // Only try to recover if this is implementing a trait for a type
         let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
@@ -1216,7 +1218,7 @@ impl<'a> Parser<'a> {
 
                 let before_trait = trai.path.span.shrink_to_lo();
                 let const_up_to_impl = const_span.with_hi(impl_span.lo());
-                err.multipart_suggestion(
+                err.multipart_suggestion_mv(
                     "you might have meant to write a const trait impl",
                     vec![(const_up_to_impl, "".to_owned()), (before_trait, "const ".to_owned())],
                     Applicability::MaybeIncorrect,
@@ -1454,8 +1456,8 @@ impl<'a> Parser<'a> {
                 let ident = this.parse_field_ident("enum", vlo)?;
 
                 if this.token == token::Not {
-                    if let Err(mut err) = this.unexpected::<()>() {
-                        err.note(fluent::parse_macro_expands_to_enum_variant).emit();
+                    if let Err(err) = this.unexpected::<()>() {
+                        err.note_mv(fluent::parse_macro_expands_to_enum_variant).emit();
                     }
 
                     this.bump();
@@ -1791,37 +1793,36 @@ impl<'a> Parser<'a> {
             }
             _ => {
                 let sp = self.prev_token.span.shrink_to_hi();
-                let mut err = self.dcx().struct_span_err(
-                    sp,
-                    format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)),
-                );
+                let msg =
+                    format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token));
 
                 // Try to recover extra trailing angle brackets
-                let mut recovered = false;
                 if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind {
                     if let Some(last_segment) = segments.last() {
-                        recovered = self.check_trailing_angle_brackets(
+                        let guar = self.check_trailing_angle_brackets(
                             last_segment,
                             &[&token::Comma, &token::CloseDelim(Delimiter::Brace)],
                         );
-                        if recovered {
+                        if let Some(_guar) = guar {
                             // Handle a case like `Vec<u8>>,` where we can continue parsing fields
                             // after the comma
                             self.eat(&token::Comma);
-                            // `check_trailing_angle_brackets` already emitted a nicer error
-                            // NOTE(eddyb) this was `.cancel()`, but `err`
-                            // gets returned, so we can't fully defuse it.
-                            err.delay_as_bug();
+
+                            // `check_trailing_angle_brackets` already emitted a nicer error, as
+                            // proven by the presence of `_guar`. We can continue parsing.
+                            return Ok(a_var);
                         }
                     }
                 }
 
+                let mut err = self.dcx().struct_span_err(sp, msg);
+
                 if self.token.is_ident()
                     || (self.token.kind == TokenKind::Pound
                         && (self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Bracket))))
                 {
-                    // This is likely another field, TokenKind::Pound is used for `#[..]` attribute for next field,
-                    // emit the diagnostic and keep going
+                    // This is likely another field, TokenKind::Pound is used for `#[..]`
+                    // attribute for next field. Emit the diagnostic and continue parsing.
                     err.span_suggestion(
                         sp,
                         "try adding a comma",
@@ -1829,14 +1830,6 @@ impl<'a> Parser<'a> {
                         Applicability::MachineApplicable,
                     );
                     err.emit();
-                    recovered = true;
-                }
-
-                if recovered {
-                    // Make sure an error was emitted (either by recovering an angle bracket,
-                    // or by finding an identifier as the next token), since we're
-                    // going to continue parsing
-                    assert!(self.dcx().has_errors().is_some());
                 } else {
                     return Err(err);
                 }
@@ -1846,7 +1839,7 @@ impl<'a> Parser<'a> {
     }
 
     fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
-        if let Err(mut err) = self.expect(&token::Colon) {
+        if let Err(err) = self.expect(&token::Colon) {
             let sm = self.sess.source_map();
             let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start());
             let semi_typo = self.token.kind == token::Semi
@@ -1862,7 +1855,7 @@ impl<'a> Parser<'a> {
             if eq_typo || semi_typo {
                 self.bump();
                 // Gracefully handle small typos.
-                err.span_suggestion_short(
+                err.span_suggestion_short_mv(
                     self.prev_token.span,
                     "field names and their types are separated with `:`",
                     ":",
@@ -1938,15 +1931,14 @@ impl<'a> Parser<'a> {
                     Case::Insensitive,
                 ) {
                     Ok(_) => {
-                        let mut err = self.dcx().struct_span_err(
+                        self.dcx().struct_span_err(
                             lo.to(self.prev_token.span),
                             format!("functions are not allowed in {adt_ty} definitions"),
-                        );
-                        err.help(
+                        )
+                        .help_mv(
                             "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
-                        );
-                        err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
-                        err
+                        )
+                        .help_mv("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information")
                     }
                     Err(err) => {
                         err.cancel();
@@ -1956,14 +1948,13 @@ impl<'a> Parser<'a> {
                 }
             } else if self.eat_keyword(kw::Struct) {
                 match self.parse_item_struct() {
-                    Ok((ident, _)) => {
-                        let mut err = self.dcx().struct_span_err(
+                    Ok((ident, _)) => self
+                        .dcx()
+                        .struct_span_err(
                             lo.with_hi(ident.span.hi()),
                             format!("structs are not allowed in {adt_ty} definitions"),
-                        );
-                        err.help("consider creating a new `struct` definition instead of nesting");
-                        err
-                    }
+                        )
+                        .help_mv("consider creating a new `struct` definition instead of nesting"),
                     Err(err) => {
                         err.cancel();
                         self.restore_snapshot(snapshot);
@@ -2598,7 +2589,7 @@ impl<'a> Parser<'a> {
         let (mut params, _) = self.parse_paren_comma_seq(|p| {
             p.recover_diff_marker();
             let snapshot = p.create_snapshot_for_diagnostic();
-            let param = p.parse_param_general(req_name, first_param).or_else(|mut e| {
+            let param = p.parse_param_general(req_name, first_param).or_else(|e| {
                 e.emit();
                 let lo = p.prev_token.span;
                 p.restore_snapshot(snapshot);
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index b201d36455e..c13adfb0532 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -499,7 +499,7 @@ impl<'a> Parser<'a> {
         let (ident, is_raw) = self.ident_or_err(recover)?;
 
         if !is_raw && ident.is_reserved() {
-            let mut err = self.expected_ident_found_err();
+            let err = self.expected_ident_found_err();
             if recover {
                 err.emit();
             } else {
@@ -847,7 +847,7 @@ impl<'a> Parser<'a> {
                                     pprust::token_to_string(&self.prev_token)
                                 );
                                 expect_err
-                                    .span_suggestion_verbose(
+                                    .span_suggestion_verbose_mv(
                                         self.prev_token.span.shrink_to_hi().until(self.token.span),
                                         msg,
                                         " @ ",
@@ -863,7 +863,7 @@ impl<'a> Parser<'a> {
                                     // Parsed successfully, therefore most probably the code only
                                     // misses a separator.
                                     expect_err
-                                        .span_suggestion_short(
+                                        .span_suggestion_short_mv(
                                             sp,
                                             format!("missing `{token_str}`"),
                                             token_str,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 7d17b1d4c4d..00dc307ab60 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -144,7 +144,7 @@ impl<'a> Parser<'a> {
         // Parse the first pattern (`p_0`).
         let mut first_pat = match self.parse_pat_no_top_alt(expected, syntax_loc) {
             Ok(pat) => pat,
-            Err(mut err)
+            Err(err)
                 if self.token.is_reserved_ident()
                     && !self.token.is_keyword(kw::In)
                     && !self.token.is_keyword(kw::If) =>
@@ -242,7 +242,7 @@ impl<'a> Parser<'a> {
                 Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
             };
 
-            let mut err = self.dcx().create_err(match syntax_loc {
+            let err = self.dcx().create_err(match syntax_loc {
                 PatternLocation::LetBinding => {
                     TopLevelOrPatternNotAllowed::LetBinding { span, sub }
                 }
@@ -252,8 +252,9 @@ impl<'a> Parser<'a> {
             });
             if trailing_vert {
                 err.delay_as_bug();
+            } else {
+                err.emit();
             }
-            err.emit();
         }
 
         Ok((pat, colon))
@@ -460,9 +461,10 @@ impl<'a> Parser<'a> {
                         super::token_descr(&self_.token)
                     );
 
-                    let mut err = self_.dcx().struct_span_err(self_.token.span, msg);
-                    err.span_label(self_.token.span, format!("expected {expected}"));
-                    err
+                    self_
+                        .dcx()
+                        .struct_span_err(self_.token.span, msg)
+                        .span_label_mv(self_.token.span, format!("expected {expected}"))
                 });
             PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
         } else {
@@ -1028,7 +1030,7 @@ impl<'a> Parser<'a> {
             let attrs = match self.parse_outer_attributes() {
                 Ok(attrs) => attrs,
                 Err(err) => {
-                    if let Some(mut delayed) = delayed_err {
+                    if let Some(delayed) = delayed_err {
                         delayed.emit();
                     }
                     return Err(err);
@@ -1040,7 +1042,7 @@ impl<'a> Parser<'a> {
             if !ate_comma {
                 let mut err =
                     self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span });
-                if let Some(mut delayed) = delayed_err {
+                if let Some(delayed) = delayed_err {
                     delayed.emit();
                 }
                 self.recover_misplaced_pattern_modifiers(&fields, &mut err);
@@ -1113,14 +1115,14 @@ impl<'a> Parser<'a> {
                     // This way we avoid "pattern missing fields" errors afterwards.
                     // We delay this error until the end in order to have a span for a
                     // suggested fix.
-                    if let Some(mut delayed_err) = delayed_err {
+                    if let Some(delayed_err) = delayed_err {
                         delayed_err.emit();
                         return Err(err);
                     } else {
                         delayed_err = Some(err);
                     }
                 } else {
-                    if let Some(mut err) = delayed_err {
+                    if let Some(err) = delayed_err {
                         err.emit();
                     }
                     return Err(err);
@@ -1132,7 +1134,7 @@ impl<'a> Parser<'a> {
                     let field = match this.parse_pat_field(lo, attrs) {
                         Ok(field) => Ok(field),
                         Err(err) => {
-                            if let Some(mut delayed_err) = delayed_err.take() {
+                            if let Some(delayed_err) = delayed_err.take() {
                                 delayed_err.emit();
                             }
                             return Err(err);
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 4253c0ae421..5ad17a30980 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -128,7 +128,7 @@ impl<'a> Parser<'a> {
                 self.prev_token.span,
                 "found single colon before projection in qualified path",
             )
-            .span_suggestion(
+            .span_suggestion_mv(
                 self.prev_token.span,
                 "use double colon",
                 "::",
@@ -493,7 +493,7 @@ impl<'a> Parser<'a> {
                 self.angle_bracket_nesting -= 1;
                 Ok(args)
             }
-            Err(mut e) if self.angle_bracket_nesting > 10 => {
+            Err(e) if self.angle_bracket_nesting > 10 => {
                 self.angle_bracket_nesting -= 1;
                 // When encountering severely malformed code where there are several levels of
                 // nested unclosed angle args (`f::<f::<f::<f::<...`), we avoid severe O(n^2)
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 831edcd88c1..1a8bbf0a157 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -32,7 +32,7 @@ impl<'a> Parser<'a> {
     /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
     // Public for rustfmt usage.
     pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
-        Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|mut e| {
+        Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| {
             e.emit();
             self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
             None
@@ -663,7 +663,7 @@ impl<'a> Parser<'a> {
                     match expect_result {
                         // Recover from parser, skip type error to avoid extra errors.
                         Ok(true) => true,
-                        Err(mut e) => {
+                        Err(e) => {
                             if self.recover_colon_as_semi() {
                                 // recover_colon_as_semi has already emitted a nicer error.
                                 e.delay_as_bug();
@@ -716,7 +716,7 @@ impl<'a> Parser<'a> {
                                 _ => {}
                             }
 
-                            if let Err(mut e) =
+                            if let Err(e) =
                                 self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
                             {
                                 if recover.no() {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 4be2c662d03..61d72857c36 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -300,7 +300,7 @@ impl<'a> Parser<'a> {
                     let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
                     let kind =
                         self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?;
-                    let mut err = self.dcx().create_err(errors::TransposeDynOrImpl {
+                    let err = self.dcx().create_err(errors::TransposeDynOrImpl {
                         span: kw.span,
                         kw: kw.name.as_str(),
                         sugg: errors::TransposeDynOrImplSugg {
@@ -487,7 +487,7 @@ impl<'a> Parser<'a> {
     fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
         let elt_ty = match self.parse_ty() {
             Ok(ty) => ty,
-            Err(mut err)
+            Err(err)
                 if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket))
                     | self.look_ahead(1, |t| t.kind == token::Semi) =>
             {
@@ -1109,20 +1109,19 @@ impl<'a> Parser<'a> {
         lifetime_defs.append(&mut generic_params);
 
         let generic_args_span = generic_args.span();
-        let mut err = self
-            .dcx()
-            .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
         let snippet = format!(
             "for<{}> ",
             lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
         );
         let before_fn_path = fn_path.span.shrink_to_lo();
-        err.multipart_suggestion(
-            "consider using a higher-ranked trait bound instead",
-            vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
-            Applicability::MaybeIncorrect,
-        )
-        .emit();
+        self.dcx()
+            .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
+            .multipart_suggestion_mv(
+                "consider using a higher-ranked trait bound instead",
+                vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
+                Applicability::MaybeIncorrect,
+            )
+            .emit();
         Ok(())
     }
 
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 4efb1be03be..724d574349a 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -29,7 +29,7 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
         _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
             // All key-value attributes are restricted to meta-item syntax.
             parse_meta(sess, attr)
-                .map_err(|mut err| {
+                .map_err(|err| {
                     err.emit();
                 })
                 .ok();
@@ -139,7 +139,7 @@ pub fn check_builtin_attribute(
 ) {
     match parse_meta(sess, attr) {
         Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template),
-        Err(mut err) => {
+        Err(err) => {
             err.emit();
         }
     }
@@ -208,7 +208,7 @@ fn emit_malformed_attribute(
     } else {
         sess.dcx
             .struct_span_err(span, error_msg)
-            .span_suggestions(
+            .span_suggestions_mv(
                 span,
                 if suggestions.len() == 1 {
                     "must be of the form"