about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs52
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs39
-rw-r--r--compiler/rustc_parse/src/parser/path.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-guard-patterns.rs46
-rw-r--r--tests/ui/feature-gates/feature-gate-guard-patterns.stderr119
-rw-r--r--tests/ui/parser/issues/issue-72373.rs2
-rw-r--r--tests/ui/parser/issues/issue-72373.stderr4
-rw-r--r--tests/ui/parser/misspelled-keywords/ref.stderr4
-rw-r--r--tests/ui/parser/pat-lt-bracket-7.rs2
-rw-r--r--tests/ui/parser/pat-lt-bracket-7.stderr4
-rw-r--r--tests/ui/parser/recover/recover-pat-exprs.rs6
-rw-r--r--tests/ui/parser/recover/recover-pat-exprs.stderr12
-rw-r--r--tests/ui/parser/recover/recover-pat-wildcards.rs4
-rw-r--r--tests/ui/parser/recover/recover-pat-wildcards.stderr8
-rw-r--r--tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr4
17 files changed, 248 insertions, 63 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 8a392e4407b..6379cf69283 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -551,6 +551,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
     gate_all!(explicit_tail_calls, "`become` expression is experimental");
     gate_all!(generic_const_items, "generic const items are experimental");
+    gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
     gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
     gate_all!(postfix_match, "postfix match is experimental");
     gate_all!(mut_ref, "mutable by-reference bindings are experimental");
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 3b49d1b90d6..cbaf67ef2ab 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -990,7 +990,7 @@ pub fn parse_ast_fragment<'a>(
             }
         }
         AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
-        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_no_top_guard(
+        AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat_allow_top_guard(
             None,
             RecoverComma::No,
             RecoverColon::Yes,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a6c7c4e3bba..adbb6b44104 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2776,7 +2776,7 @@ impl<'a> Parser<'a> {
         };
         // Try to parse the pattern `for ($PAT) in $EXPR`.
         let pat = match (
-            self.parse_pat_no_top_guard(
+            self.parse_pat_allow_top_guard(
                 None,
                 RecoverComma::Yes,
                 RecoverColon::Yes,
@@ -3313,39 +3313,33 @@ impl<'a> Parser<'a> {
 
     fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> {
         if self.token == token::OpenDelim(Delimiter::Parenthesis) {
-            // Detect and recover from `($pat if $cond) => $arm`.
             let left = self.token.span;
-            match self.parse_pat_no_top_guard(
+            let pat = self.parse_pat_no_top_guard(
                 None,
                 RecoverComma::Yes,
                 RecoverColon::Yes,
                 CommaRecoveryMode::EitherTupleOrPipe,
-            ) {
-                Ok(pat) => Ok((pat, self.parse_match_arm_guard()?)),
-                Err(err)
-                    if let prev_sp = self.prev_token.span
-                        && let true = self.eat_keyword(kw::If) =>
-                {
-                    // We know for certain we've found `($pat if` so far.
-                    let mut cond = match self.parse_match_guard_condition() {
-                        Ok(cond) => cond,
-                        Err(cond_err) => {
-                            cond_err.cancel();
-                            return Err(err);
-                        }
-                    };
-                    err.cancel();
-                    CondChecker::new(self).visit_expr(&mut cond);
-                    self.eat_to_tokens(&[&token::CloseDelim(Delimiter::Parenthesis)]);
-                    self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
-                    let right = self.prev_token.span;
-                    self.dcx().emit_err(errors::ParenthesesInMatchPat {
-                        span: vec![left, right],
-                        sugg: errors::ParenthesesInMatchPatSugg { left, right },
-                    });
-                    Ok((self.mk_pat(left.to(prev_sp), ast::PatKind::Wild), Some(cond)))
-                }
-                Err(err) => Err(err),
+            )?;
+            if let ast::PatKind::Paren(subpat) = &pat.kind
+                && let ast::PatKind::Guard(..) = &subpat.kind
+            {
+                // Detect and recover from `($pat if $cond) => $arm`.
+                // FIXME(guard_patterns): convert this to a normal guard instead
+                let span = pat.span;
+                let ast::PatKind::Paren(subpat) = pat.into_inner().kind else { unreachable!() };
+                let ast::PatKind::Guard(_, mut cond) = subpat.into_inner().kind else {
+                    unreachable!()
+                };
+                self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
+                CondChecker::new(self).visit_expr(&mut cond);
+                let right = self.prev_token.span;
+                self.dcx().emit_err(errors::ParenthesesInMatchPat {
+                    span: vec![left, right],
+                    sugg: errors::ParenthesesInMatchPatSugg { left, right },
+                });
+                Ok((self.mk_pat(span, ast::PatKind::Wild), Some(cond)))
+            } else {
+                Ok((pat, self.parse_match_arm_guard()?))
             }
         } else {
             // Regular parser flow:
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index a33960d0277..d0d0d8124d1 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -97,6 +97,31 @@ pub enum PatternLocation {
 impl<'a> Parser<'a> {
     /// Parses a pattern.
     ///
+    /// Corresponds to `Pattern` in RFC 3637 and admits guard patterns at the top level.
+    /// Used when parsing patterns in all cases where neither `PatternNoTopGuard` nor
+    /// `PatternNoTopAlt` (see below) are used.
+    pub fn parse_pat_allow_top_guard(
+        &mut self,
+        expected: Option<Expected>,
+        rc: RecoverComma,
+        ra: RecoverColon,
+        rt: CommaRecoveryMode,
+    ) -> PResult<'a, P<Pat>> {
+        let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?;
+
+        if self.eat_keyword(kw::If) {
+            let cond = self.parse_expr()?;
+            // Feature-gate guard patterns
+            self.psess.gated_spans.gate(sym::guard_patterns, cond.span);
+            let span = pat.span.to(cond.span);
+            Ok(self.mk_pat(span, PatKind::Guard(pat, cond)))
+        } else {
+            Ok(pat)
+        }
+    }
+
+    /// Parses a pattern.
+    ///
     /// Corresponds to `PatternNoTopAlt` in RFC 3637 and does not admit or-patterns
     /// or guard patterns at the top level. Used when parsing the parameters of lambda
     /// expressions, functions, function pointers, and `pat_param` macro fragments.
@@ -111,8 +136,8 @@ impl<'a> Parser<'a> {
     /// Parses a pattern.
     ///
     /// Corresponds to `PatternNoTopGuard` in RFC 3637 and allows or-patterns, but not
-    /// guard patterns, at the top level. Used for parsing patterns in `pat` fragments and
-    /// `let`, `if let`, and `while let` expressions.
+    /// guard patterns, at the top level. Used for parsing patterns in `pat` fragments (until
+    /// the next edition) and `let`, `if let`, and `while let` expressions.
     ///
     /// Note that after the FCP in <https://github.com/rust-lang/rust/issues/81415>,
     /// a leading vert is allowed in nested or-patterns, too. This allows us to
@@ -697,7 +722,7 @@ impl<'a> Parser<'a> {
         } else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
             // Parse `[pat, pat,...]` as a slice pattern.
             let (pats, _) = self.parse_delim_comma_seq(Delimiter::Bracket, |p| {
-                p.parse_pat_no_top_guard(
+                p.parse_pat_allow_top_guard(
                     None,
                     RecoverComma::No,
                     RecoverColon::No,
@@ -945,7 +970,7 @@ impl<'a> Parser<'a> {
         let open_paren = self.token.span;
 
         let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
-            p.parse_pat_no_top_guard(
+            p.parse_pat_allow_top_guard(
                 None,
                 RecoverComma::No,
                 RecoverColon::No,
@@ -1360,7 +1385,7 @@ impl<'a> Parser<'a> {
         path: Path,
     ) -> PResult<'a, PatKind> {
         let (fields, _) = self.parse_paren_comma_seq(|p| {
-            p.parse_pat_no_top_guard(
+            p.parse_pat_allow_top_guard(
                 None,
                 RecoverComma::No,
                 RecoverColon::No,
@@ -1395,7 +1420,7 @@ impl<'a> Parser<'a> {
         self.parse_builtin(|self_, _lo, ident| {
             Ok(match ident.name {
                 // builtin#deref(PAT)
-                sym::deref => Some(ast::PatKind::Deref(self_.parse_pat_no_top_guard(
+                sym::deref => Some(ast::PatKind::Deref(self_.parse_pat_allow_top_guard(
                     None,
                     RecoverComma::Yes,
                     RecoverColon::Yes,
@@ -1670,7 +1695,7 @@ impl<'a> Parser<'a> {
             // Parsing a pattern of the form `fieldname: pat`.
             let fieldname = self.parse_field_name()?;
             self.bump();
-            let pat = self.parse_pat_no_top_guard(
+            let pat = self.parse_pat_allow_top_guard(
                 None,
                 RecoverComma::No,
                 RecoverColon::No,
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 9587b53a44b..6a7029a8f1c 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -469,7 +469,7 @@ impl<'a> Parser<'a> {
             PathStyle::Pat
                 if let Ok(_) = self
                     .parse_paren_comma_seq(|p| {
-                        p.parse_pat_no_top_guard(
+                        p.parse_pat_allow_top_guard(
                             None,
                             RecoverComma::No,
                             RecoverColon::No,
diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.rs b/tests/ui/feature-gates/feature-gate-guard-patterns.rs
new file mode 100644
index 00000000000..929e8ef3181
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-guard-patterns.rs
@@ -0,0 +1,46 @@
+fn match_guards_still_work() {
+    match 0 {
+        0 if guard(0) => {},
+        _ => {},
+    }
+}
+
+fn other_guards_dont() {
+    match 0 {
+        (0 if guard(0)) => {},
+        //~^ ERROR unexpected parentheses surrounding `match` arm pattern
+        _ => {},
+    }
+
+    match 0 {
+        (0 if guard(0)) | 1 => {},
+        //~^ ERROR: guard patterns are experimental
+        _ => {},
+    }
+
+    let ((x if guard(x)) | x) = 0;
+    //~^ ERROR: guard patterns are experimental
+    //~| ERROR: cannot find value `x`
+
+    if let (x if guard(x)) = 0 {}
+    //~^ ERROR: guard patterns are experimental
+    //~| WARN: irrefutable
+
+    while let (x if guard(x)) = 0 {}
+    //~^ ERROR: guard patterns are experimental
+    //~| WARN: irrefutable
+
+    #[cfg(FALSE)]
+    while let (x if guard(x)) = 0 {}
+    //~^ ERROR: guard patterns are experimental
+}
+
+fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {}
+//~^ ERROR: guard patterns are experimental
+//~| ERROR: cannot find value `x`
+
+fn guard<T>(x: T) -> bool {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.stderr b/tests/ui/feature-gates/feature-gate-guard-patterns.stderr
new file mode 100644
index 00000000000..0613b5c95a4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-guard-patterns.stderr
@@ -0,0 +1,119 @@
+error: unexpected parentheses surrounding `match` arm pattern
+  --> $DIR/feature-gate-guard-patterns.rs:10:9
+   |
+LL |         (0 if guard(0)) => {},
+   |         ^             ^
+   |
+help: remove parentheses surrounding the pattern
+   |
+LL -         (0 if guard(0)) => {},
+LL +         0 if guard(0) => {},
+   |
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/feature-gate-guard-patterns.rs:21:22
+   |
+LL |     let ((x if guard(x)) | x) = 0;
+   |                      ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/feature-gate-guard-patterns.rs:38:45
+   |
+LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {}
+   |                                             ^
+   |
+help: the binding `x` is available in a different scope in the same function
+  --> $DIR/feature-gate-guard-patterns.rs:21:11
+   |
+LL |     let ((x if guard(x)) | x) = 0;
+   |           ^
+
+error[E0658]: guard patterns are experimental
+  --> $DIR/feature-gate-guard-patterns.rs:16:15
+   |
+LL |         (0 if guard(0)) | 1 => {},
+   |               ^^^^^^^^
+   |
+   = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
+   = help: add `#![feature(guard_patterns)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider using match arm guards
+
+error[E0658]: guard patterns are experimental
+  --> $DIR/feature-gate-guard-patterns.rs:21:16
+   |
+LL |     let ((x if guard(x)) | x) = 0;
+   |                ^^^^^^^^
+   |
+   = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
+   = help: add `#![feature(guard_patterns)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider using match arm guards
+
+error[E0658]: guard patterns are experimental
+  --> $DIR/feature-gate-guard-patterns.rs:25:18
+   |
+LL |     if let (x if guard(x)) = 0 {}
+   |                  ^^^^^^^^
+   |
+   = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
+   = help: add `#![feature(guard_patterns)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider using match arm guards
+
+error[E0658]: guard patterns are experimental
+  --> $DIR/feature-gate-guard-patterns.rs:29:21
+   |
+LL |     while let (x if guard(x)) = 0 {}
+   |                     ^^^^^^^^
+   |
+   = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
+   = help: add `#![feature(guard_patterns)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider using match arm guards
+
+error[E0658]: guard patterns are experimental
+  --> $DIR/feature-gate-guard-patterns.rs:34:21
+   |
+LL |     while let (x if guard(x)) = 0 {}
+   |                     ^^^^^^^^
+   |
+   = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
+   = help: add `#![feature(guard_patterns)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider using match arm guards
+
+error[E0658]: guard patterns are experimental
+  --> $DIR/feature-gate-guard-patterns.rs:38:39
+   |
+LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {}
+   |                                       ^^^^^^^^
+   |
+   = note: see issue #129967 <https://github.com/rust-lang/rust/issues/129967> for more information
+   = help: add `#![feature(guard_patterns)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: consider using match arm guards
+
+warning: irrefutable `if let` pattern
+  --> $DIR/feature-gate-guard-patterns.rs:25:8
+   |
+LL |     if let (x if guard(x)) = 0 {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this pattern will always match, so the `if let` is useless
+   = help: consider replacing the `if let` with a `let`
+   = note: `#[warn(irrefutable_let_patterns)]` on by default
+
+warning: irrefutable `while let` pattern
+  --> $DIR/feature-gate-guard-patterns.rs:29:11
+   |
+LL |     while let (x if guard(x)) = 0 {}
+   |           ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this pattern will always match, so the loop will never exit
+   = help: consider instead using a `loop { ... }` with a `let` inside it
+
+error: aborting due to 9 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0425, E0658.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/issues/issue-72373.rs b/tests/ui/parser/issues/issue-72373.rs
index 4da6061c27f..ed88d53539b 100644
--- a/tests/ui/parser/issues/issue-72373.rs
+++ b/tests/ui/parser/issues/issue-72373.rs
@@ -3,7 +3,7 @@ fn foo(c: &[u32], n: u32) -> u32 {
         [h, ..] if h > n => 0,
         [h, ..] if h == n => 1,
         [h, ref ts..] => foo(c, n - h) + foo(ts, n),
-        //~^ ERROR expected one of `,`, `@`, `]`, or `|`, found `..`
+        //~^ ERROR expected one of `,`, `@`, `]`, `if`, or `|`, found `..`
         [] => 0,
     }
 }
diff --git a/tests/ui/parser/issues/issue-72373.stderr b/tests/ui/parser/issues/issue-72373.stderr
index c596c6abda5..d566d6f5fd1 100644
--- a/tests/ui/parser/issues/issue-72373.stderr
+++ b/tests/ui/parser/issues/issue-72373.stderr
@@ -1,8 +1,8 @@
-error: expected one of `,`, `@`, `]`, or `|`, found `..`
+error: expected one of `,`, `@`, `]`, `if`, or `|`, found `..`
   --> $DIR/issue-72373.rs:5:19
    |
 LL |         [h, ref ts..] => foo(c, n - h) + foo(ts, n),
-   |                   ^^ expected one of `,`, `@`, `]`, or `|`
+   |                   ^^ expected one of `,`, `@`, `]`, `if`, or `|`
    |
 help: if you meant to bind the contents of the rest of the array pattern into `ts`, use `@`
    |
diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr
index b8b52702314..398d9d6bb99 100644
--- a/tests/ui/parser/misspelled-keywords/ref.stderr
+++ b/tests/ui/parser/misspelled-keywords/ref.stderr
@@ -1,8 +1,8 @@
-error: expected one of `)`, `,`, `@`, or `|`, found `list`
+error: expected one of `)`, `,`, `@`, `if`, or `|`, found `list`
   --> $DIR/ref.rs:4:19
    |
 LL |         Some(refe list) => println!("{list:?}"),
-   |                   ^^^^ expected one of `)`, `,`, `@`, or `|`
+   |                   ^^^^ expected one of `)`, `,`, `@`, `if`, or `|`
    |
 help: there is a keyword `ref` with a similar name
    |
diff --git a/tests/ui/parser/pat-lt-bracket-7.rs b/tests/ui/parser/pat-lt-bracket-7.rs
index 327aef5ad15..abaeb4c83c0 100644
--- a/tests/ui/parser/pat-lt-bracket-7.rs
+++ b/tests/ui/parser/pat-lt-bracket-7.rs
@@ -3,7 +3,7 @@ fn main() {
     let foo = core::iter::empty();
 
     for Thing(x[]) in foo {}
-    //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[`
+    //~^ ERROR: expected one of `)`, `,`, `@`, `if`, or `|`, found `[`
 }
 
 const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/tests/ui/parser/pat-lt-bracket-7.stderr b/tests/ui/parser/pat-lt-bracket-7.stderr
index 004dcfb2a7b..cc457a4e64e 100644
--- a/tests/ui/parser/pat-lt-bracket-7.stderr
+++ b/tests/ui/parser/pat-lt-bracket-7.stderr
@@ -1,10 +1,10 @@
-error: expected one of `)`, `,`, `@`, or `|`, found `[`
+error: expected one of `)`, `,`, `@`, `if`, or `|`, found `[`
   --> $DIR/pat-lt-bracket-7.rs:5:16
    |
 LL |     for Thing(x[]) in foo {}
    |                ^
    |                |
-   |                expected one of `)`, `,`, `@`, or `|`
+   |                expected one of `)`, `,`, `@`, `if`, or `|`
    |                help: missing `,`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/parser/recover/recover-pat-exprs.rs b/tests/ui/parser/recover/recover-pat-exprs.rs
index e5e25df0c01..a78bb82828d 100644
--- a/tests/ui/parser/recover/recover-pat-exprs.rs
+++ b/tests/ui/parser/recover/recover-pat-exprs.rs
@@ -27,7 +27,7 @@ fn array_indexing() {
     { let x[0, 1, 2]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
     { let x[0; 20]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
     { let x[]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
-    { let (x[]); } //~ error: expected one of `)`, `,`, `@`, or `|`, found `[`
+    { let (x[]); } //~ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `[`
     //~^ missing `,`
 }
 
@@ -95,12 +95,12 @@ fn main() {
         f?() => (),
         //~^ error: expected a pattern, found an expression
         (_ + 1) => (),
-        //~^ error: expected one of `)`, `,`, or `|`, found `+`
+        //~^ error: expected one of `)`, `,`, `if`, or `|`, found `+`
     }
 
     let 1 + 1 = 2;
     //~^ error: expected a pattern, found an expression
 
     let b = matches!(x, (x * x | x.f()) | x[0]);
-    //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*`
+    //~^ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `*`
 }
diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr
index 041dfd647ad..281eeced402 100644
--- a/tests/ui/parser/recover/recover-pat-exprs.stderr
+++ b/tests/ui/parser/recover/recover-pat-exprs.stderr
@@ -213,13 +213,13 @@ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
 LL |     { let x[]; }
    |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
 
-error: expected one of `)`, `,`, `@`, or `|`, found `[`
+error: expected one of `)`, `,`, `@`, `if`, or `|`, found `[`
   --> $DIR/recover-pat-exprs.rs:30:13
    |
 LL |     { let (x[]); }
    |             ^
    |             |
-   |             expected one of `)`, `,`, `@`, or `|`
+   |             expected one of `)`, `,`, `@`, `if`, or `|`
    |             help: missing `,`
 
 error: expected a pattern, found an expression
@@ -611,11 +611,11 @@ LL |         x.sqrt() @ .. => (),
    |
    = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
 
-error: expected one of `)`, `,`, or `|`, found `+`
+error: expected one of `)`, `,`, `if`, or `|`, found `+`
   --> $DIR/recover-pat-exprs.rs:97:12
    |
 LL |         (_ + 1) => (),
-   |            ^ expected one of `)`, `,`, or `|`
+   |            ^ expected one of `)`, `,`, `if`, or `|`
 
 error: expected a pattern, found an expression
   --> $DIR/recover-pat-exprs.rs:81:9
@@ -772,11 +772,11 @@ LL |     let 1 + 1 = 2;
    |
    = note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
 
-error: expected one of `)`, `,`, `@`, or `|`, found `*`
+error: expected one of `)`, `,`, `@`, `if`, or `|`, found `*`
   --> $DIR/recover-pat-exprs.rs:104:28
    |
 LL |     let b = matches!(x, (x * x | x.f()) | x[0]);
-   |                            ^ expected one of `)`, `,`, `@`, or `|`
+   |                            ^ expected one of `)`, `,`, `@`, `if`, or `|`
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
    = note: while parsing argument for this `pat` macro fragment
diff --git a/tests/ui/parser/recover/recover-pat-wildcards.rs b/tests/ui/parser/recover/recover-pat-wildcards.rs
index f506e2223d6..d4d28ce6358 100644
--- a/tests/ui/parser/recover/recover-pat-wildcards.rs
+++ b/tests/ui/parser/recover/recover-pat-wildcards.rs
@@ -8,7 +8,7 @@ fn a() {
 
 fn b() {
     match 2 {
-        (_ % 4) => () //~ error: expected one of `)`, `,`, or `|`, found `%`
+        (_ % 4) => () //~ error: expected one of `)`, `,`, `if`, or `|`, found `%`
     }
 }
 
@@ -40,7 +40,7 @@ fn f() {
 
 fn g() {
     match 7 {
-        (_ * 0)..5 => () //~ error: expected one of `)`, `,`, or `|`, found `*`
+        (_ * 0)..5 => () //~ error: expected one of `)`, `,`, `if`, or `|`, found `*`
     }
 }
 
diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr
index 81a9920f6a2..f939e513370 100644
--- a/tests/ui/parser/recover/recover-pat-wildcards.stderr
+++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr
@@ -4,11 +4,11 @@ error: expected one of `=>`, `if`, or `|`, found `+`
 LL |         _ + 1 => ()
    |           ^ expected one of `=>`, `if`, or `|`
 
-error: expected one of `)`, `,`, or `|`, found `%`
+error: expected one of `)`, `,`, `if`, or `|`, found `%`
   --> $DIR/recover-pat-wildcards.rs:11:12
    |
 LL |         (_ % 4) => ()
-   |            ^ expected one of `)`, `,`, or `|`
+   |            ^ expected one of `)`, `,`, `if`, or `|`
 
 error: expected one of `=>`, `if`, or `|`, found `.`
   --> $DIR/recover-pat-wildcards.rs:17:10
@@ -47,11 +47,11 @@ error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
 LL |         0..._ => ()
    |             ^ expected one of `=>`, `if`, or `|`
 
-error: expected one of `)`, `,`, or `|`, found `*`
+error: expected one of `)`, `,`, `if`, or `|`, found `*`
   --> $DIR/recover-pat-wildcards.rs:43:12
    |
 LL |         (_ * 0)..5 => ()
-   |            ^ expected one of `)`, `,`, or `|`
+   |            ^ expected one of `)`, `,`, `if`, or `|`
 
 error: expected one of `=>`, `if`, or `|`, found `(`
   --> $DIR/recover-pat-wildcards.rs:49:11
diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
index da8f4ca5f0c..6ce8f6d31a0 100644
--- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
+++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr
@@ -6,11 +6,11 @@ LL |     let a: u8 @ b = 0;
    |          |
    |          while parsing the type for `a`
 
-error: expected one of `)`, `,`, `@`, or `|`, found `:`
+error: expected one of `)`, `,`, `@`, `if`, or `|`, found `:`
   --> $DIR/nested-type-ascription-syntactically-invalid.rs:24:15
    |
 LL |     let a @ (b: u8);
-   |               ^ expected one of `)`, `,`, `@`, or `|`
+   |               ^ expected one of `)`, `,`, `@`, `if`, or `|`
    |
    = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>