diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 792de77e9d4c..ab1605a92cb5 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -632,9 +632,11 @@ impl Pat { | PatKind::Or(s) => s.iter().for_each(|p| p.walk(it)), // Trivial wrappers over inner patterns. - PatKind::Box(s) | PatKind::Deref(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => { - s.walk(it) - } + PatKind::Box(s) + | PatKind::Deref(s) + | PatKind::Ref(s, _) + | PatKind::Paren(s) + | PatKind::Guard(s, _) => s.walk(it), // These patterns do not contain subpatterns, skip. PatKind::Wild @@ -844,6 +846,9 @@ pub enum PatKind { // A never pattern `!`. Never, + /// A guard pattern (e.g., `x if guard(x)`). + Guard(P, P), + /// Parentheses in patterns used for grouping (i.e., `(PAT)`). Paren(P), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 198e1bca7744..ae0664239dd9 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1520,6 +1520,10 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) { visit_opt(e2, |e| vis.visit_expr(e)); vis.visit_span(span); } + PatKind::Guard(p, e) => { + vis.visit_pat(p); + vis.visit_expr(e); + } PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { visit_thin_vec(elems, |elem| vis.visit_pat(elem)) } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 20ac9fa02bb5..4dca4c78aef1 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -679,6 +679,10 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res visit_opt!(visitor, visit_expr, lower_bound); visit_opt!(visitor, visit_expr, upper_bound); } + PatKind::Guard(subpattern, guard_condition) => { + try_visit!(visitor.visit_pat(subpattern)); + try_visit!(visitor.visit_expr(guard_condition)); + } PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Err(_guar) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index ace7bfb5c73f..c4bae084a3f8 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -114,6 +114,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_range_end(end, e2.is_some()), ); } + // FIXME(guard_patterns): lower pattern guards to HIR + PatKind::Guard(inner, _) => pattern = inner, PatKind::Slice(pats) => break self.lower_pat_slice(pats), PatKind::Rest => { // If we reach here the `..` pattern is not semantically allowed. diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d7c531f37608..32eea2befbfd 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1709,6 +1709,12 @@ impl<'a> State<'a> { self.print_expr(e, FixupContext::default()); } } + PatKind::Guard(subpat, condition) => { + self.print_pat(subpat); + self.space(); + self.word_space("if"); + self.print_expr(condition, FixupContext::default()); + } PatKind::Slice(elts) => { self.word("["); self.commasep(Inconsistent, elts, |s, p| s.print_pat(p)); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 5ec920d39f49..adf157fd0bf5 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1235,7 +1235,7 @@ impl EarlyLintPass for UnusedParens { self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space); }, // Avoid linting on `i @ (p0 | .. | pn)` and `box (p0 | .. | pn)`, #64106. - Ident(.., Some(p)) | Box(p) | Deref(p) => self.check_unused_parens_pat(cx, p, true, false, keep_space), + Ident(.., Some(p)) | Box(p) | Deref(p) | Guard(p, _) => self.check_unused_parens_pat(cx, p, true, false, keep_space), // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. Ref(p, m) => self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space), diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index db34189be2a9..dcc36334248b 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -556,6 +556,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Slice, Rest, Never, + Guard, Paren, MacCall, Err