diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 0d42035e74b..8921c1c6a03 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -11,12 +11,12 @@ use crate::errors::{
     DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
     GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
     HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon,
-    IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg,
-    PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
-    StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens,
-    StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
-    TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
-    UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
+    IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg,
+    SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg,
+    StructLiteralNeedingParens, StructLiteralNeedingParensSugg, SuggAddMissingLetStmt,
+    SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, UnexpectedConstInGenericParam,
+    UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
+    UseEqInstead, WrapType,
 };
 
 use crate::fluent_generated as fluent;
@@ -1994,37 +1994,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Recovers a situation like `for ( $pat in $expr )`
-    /// and suggest writing `for $pat in $expr` instead.
-    ///
-    /// This should be called before parsing the `$block`.
-    pub(super) fn recover_parens_around_for_head(
-        &mut self,
-        pat: P<Pat>,
-        begin_paren: Option<(Span, Span)>,
-    ) -> P<Pat> {
-        match (&self.token.kind, begin_paren) {
-            (token::CloseDelim(Delimiter::Parenthesis), Some((begin_par_sp, left))) => {
-                let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
-                self.bump();
-                self.sess.emit_err(ParenthesesInForHead {
-                    span: vec![begin_par_sp, self.prev_token.span],
-                    // With e.g. `for (x) in y)` this would replace `(x) in y)`
-                    // with `x) in y)` which is syntactically invalid.
-                    // However, this is prevented before we get here.
-                    sugg: ParenthesesInForHeadSugg { left, right },
-                });
-
-                // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
-                pat.and_then(|pat| match pat.kind {
-                    PatKind::Paren(pat) => pat,
-                    _ => P(pat),
-                })
-            }
-            _ => pat,
-        }
-    }
-
     pub(super) fn recover_seq_parse_error(
         &mut self,
         delim: Delimiter,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 8a4b7b5b99e..88c0c9703db 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2609,33 +2609,66 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
-    fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
-        // Record whether we are about to parse `for (`.
-        // This is used below for recovery in case of `for ( $stuff ) $block`
-        // in which case we will suggest `for $stuff $block`.
-        let begin_paren = match self.token.kind {
-            token::OpenDelim(Delimiter::Parenthesis) => Some((
-                self.token.span,
-                self.prev_token.span.between(self.look_ahead(1, |t| t.span)),
-            )),
-            _ => None,
+    fn parse_for_head(&mut self) -> PResult<'a, (P<Pat>, P<Expr>)> {
+        let pat = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis) {
+            // Record whether we are about to parse `for (`.
+            // This is used below for recovery in case of `for ( $stuff ) $block`
+            // in which case we will suggest `for $stuff $block`.
+            let start_span = self.token.span;
+            let left = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
+            match self.parse_pat_allow_top_alt(
+                None,
+                RecoverComma::Yes,
+                RecoverColon::Yes,
+                CommaRecoveryMode::LikelyTuple,
+            ) {
+                Ok(pat) => pat,
+                Err(err) if self.eat_keyword(kw::In) => {
+                    let expr = match self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None) {
+                        Ok(expr) => expr,
+                        Err(expr_err) => {
+                            expr_err.cancel();
+                            return Err(err);
+                        }
+                    };
+                    return if self.token.kind == token::CloseDelim(Delimiter::Parenthesis) {
+                        let span = vec![start_span, self.token.span];
+                        let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span));
+                        self.bump(); // )
+                        err.cancel();
+                        self.sess.emit_err(errors::ParenthesesInForHead {
+                            span,
+                            // With e.g. `for (x) in y)` this would replace `(x) in y)`
+                            // with `x) in y)` which is syntactically invalid.
+                            // However, this is prevented before we get here.
+                            sugg: errors::ParenthesesInForHeadSugg { left, right },
+                        });
+                        Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr))
+                    } else {
+                        Err(err)
+                    };
+                }
+                Err(err) => return Err(err),
+            }
+        } else {
+            self.parse_pat_allow_top_alt(
+                None,
+                RecoverComma::Yes,
+                RecoverColon::Yes,
+                CommaRecoveryMode::LikelyTuple,
+            )?
         };
-
-        let pat = self.parse_pat_allow_top_alt(
-            None,
-            RecoverComma::Yes,
-            RecoverColon::Yes,
-            CommaRecoveryMode::LikelyTuple,
-        )?;
         if !self.eat_keyword(kw::In) {
             self.error_missing_in_for_loop();
         }
         self.check_for_for_in_in_typo(self.prev_token.span);
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
+        Ok((pat, expr))
+    }
 
-        let pat = self.recover_parens_around_for_head(pat, begin_paren);
-
+    /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
+    fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+        let (pat, expr) = self.parse_for_head()?;
         // Recover from missing expression in `for` loop
         if matches!(expr.kind, ExprKind::Block(..))
             && !matches!(self.token.kind, token::OpenDelim(Delimiter::Brace))
diff --git a/tests/ui/lint/issue-103435-extra-parentheses.fixed b/tests/ui/lint/issue-103435-extra-parentheses.fixed
index 3c23ec3b8b9..74b5aa06e35 100644
--- a/tests/ui/lint/issue-103435-extra-parentheses.fixed
+++ b/tests/ui/lint/issue-103435-extra-parentheses.fixed
@@ -12,7 +12,6 @@ fn main() {
     //~^ ERROR unnecessary parentheses around `if` condition
 
     // reported by parser
-    for(_x in 1..10){}
-    //~^ ERROR expected one of
-    //~| ERROR unexpected parentheses surrounding
+    for _x in 1..10 {}
+    //~^ ERROR unexpected parentheses surrounding
 }
diff --git a/tests/ui/lint/issue-103435-extra-parentheses.rs b/tests/ui/lint/issue-103435-extra-parentheses.rs
index 8261610cf56..cc81a64f217 100644
--- a/tests/ui/lint/issue-103435-extra-parentheses.rs
+++ b/tests/ui/lint/issue-103435-extra-parentheses.rs
@@ -8,11 +8,10 @@ fn main() {
     for(_x)in 1..10 {}
     //~^ ERROR unnecessary parentheses around pattern
 
-    if(2 == 1){}
+    if(2 == 1) {}
     //~^ ERROR unnecessary parentheses around `if` condition
 
     // reported by parser
-    for(_x in 1..10){}
-    //~^ ERROR expected one of
-    //~| ERROR unexpected parentheses surrounding
+    for(_x in 1..10) {}
+    //~^ ERROR unexpected parentheses surrounding
 }
diff --git a/tests/ui/lint/issue-103435-extra-parentheses.stderr b/tests/ui/lint/issue-103435-extra-parentheses.stderr
index 15b906f256e..5a166eb5008 100644
--- a/tests/ui/lint/issue-103435-extra-parentheses.stderr
+++ b/tests/ui/lint/issue-103435-extra-parentheses.stderr
@@ -1,8 +1,14 @@
-error: expected one of `)`, `,`, `@`, or `|`, found keyword `in`
-  --> $DIR/issue-103435-extra-parentheses.rs:15:12
+error: unexpected parentheses surrounding `for` loop head
+  --> $DIR/issue-103435-extra-parentheses.rs:15:8
+   |
+LL |     for(_x in 1..10) {}
+   |        ^           ^
+   |
+help: remove parentheses in `for` loop
+   |
+LL -     for(_x in 1..10) {}
+LL +     for _x in 1..10 {}
    |
-LL |     for(_x in 1..10){}
-   |            ^^ expected one of `)`, `,`, `@`, or `|`
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-103435-extra-parentheses.rs:5:11
@@ -36,12 +42,12 @@ LL +     for _x in 1..10 {}
 error: unnecessary parentheses around `if` condition
   --> $DIR/issue-103435-extra-parentheses.rs:11:7
    |
-LL |     if(2 == 1){}
+LL |     if(2 == 1) {}
    |       ^      ^
    |
 help: remove these parentheses
    |
-LL -     if(2 == 1){}
+LL -     if(2 == 1) {}
 LL +     if 2 == 1 {}
    |
 
diff --git a/tests/ui/parser/recover/recover-enum2.rs b/tests/ui/parser/recover/recover-enum2.rs
index 0c942088955..56b57f625ba 100644
--- a/tests/ui/parser/recover/recover-enum2.rs
+++ b/tests/ui/parser/recover/recover-enum2.rs
@@ -8,7 +8,7 @@ fn main() {
     }
 
     // recover...
-    let a = 1;
+    let () = 1; //~ ERROR mismatched types
     enum Test2 {
         Fine,
     }
@@ -24,5 +24,6 @@ fn main() {
         enum Test4 {
             Nope(i32 {}) //~ ERROR: found `{`
         }
+        let () = 1; //~ ERROR mismatched types
     }
 }
diff --git a/tests/ui/parser/recover/recover-enum2.stderr b/tests/ui/parser/recover/recover-enum2.stderr
index 71c2804c3a7..eb921450124 100644
--- a/tests/ui/parser/recover/recover-enum2.stderr
+++ b/tests/ui/parser/recover/recover-enum2.stderr
@@ -14,5 +14,22 @@ LL |         enum Test4 {
 LL |             Nope(i32 {})
    |                      ^ expected one of 7 possible tokens
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/recover-enum2.rs:11:9
+   |
+LL |     let () = 1;
+   |         ^^   - this expression has type `{integer}`
+   |         |
+   |         expected integer, found `()`
 
+error[E0308]: mismatched types
+  --> $DIR/recover-enum2.rs:27:13
+   |
+LL |         let () = 1;
+   |             ^^   - this expression has type `{integer}`
+   |             |
+   |             expected integer, found `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/recover/recover-for-loop-parens-around-head.fixed b/tests/ui/parser/recover/recover-for-loop-parens-around-head.fixed
new file mode 100644
index 00000000000..6afc2d99355
--- /dev/null
+++ b/tests/ui/parser/recover/recover-for-loop-parens-around-head.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+// Here we test that the parser is able to recover in a situation like
+// `for ( $pat in $expr )` since that is familiar syntax in other languages.
+// Instead we suggest that the user writes `for $pat in $expr`.
+
+#![deny(unused)] // Make sure we don't trigger `unused_parens`.
+
+fn main() {
+    let vec = vec![1, 2, 3];
+
+    for _elem in vec {
+        //~^ ERROR unexpected parentheses surrounding `for` loop head
+        const _RECOVERY_WITNESS: u32 = 0u32; //~ ERROR mismatched types
+    }
+}
diff --git a/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs b/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs
index 053b428bd12..b1716900c49 100644
--- a/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs
+++ b/tests/ui/parser/recover/recover-for-loop-parens-around-head.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 // Here we test that the parser is able to recover in a situation like
 // `for ( $pat in $expr )` since that is familiar syntax in other languages.
 // Instead we suggest that the user writes `for $pat in $expr`.
@@ -7,9 +8,8 @@
 fn main() {
     let vec = vec![1, 2, 3];
 
-    for ( elem in vec ) {
-        //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in`
-        //~| ERROR unexpected parentheses surrounding `for` loop head
-        const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
+    for ( _elem in vec ) {
+        //~^ ERROR unexpected parentheses surrounding `for` loop head
+        const _RECOVERY_WITNESS: u32 = 0u8; //~ ERROR mismatched types
     }
 }
diff --git a/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr b/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr
index b1540e19f44..beaa346e76c 100644
--- a/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr
+++ b/tests/ui/parser/recover/recover-for-loop-parens-around-head.stderr
@@ -1,8 +1,26 @@
-error: expected one of `)`, `,`, `@`, or `|`, found keyword `in`
-  --> $DIR/recover-for-loop-parens-around-head.rs:10:16
+error: unexpected parentheses surrounding `for` loop head
+  --> $DIR/recover-for-loop-parens-around-head.rs:11:9
+   |
+LL |     for ( _elem in vec ) {
+   |         ^              ^
+   |
+help: remove parentheses in `for` loop
+   |
+LL -     for ( _elem in vec ) {
+LL +     for _elem in vec {
    |
-LL |     for ( elem in vec ) {
-   |                ^^ expected one of `)`, `,`, `@`, or `|`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/recover-for-loop-parens-around-head.rs:13:40
+   |
+LL |         const _RECOVERY_WITNESS: u32 = 0u8;
+   |                                        ^^^ expected `u32`, found `u8`
+   |
+help: change the type of the numeric literal from `u8` to `u32`
+   |
+LL |         const _RECOVERY_WITNESS: u32 = 0u32;
+   |                                         ~~~
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.