From 8a57f3d8441a62ecda9aa3e537b2ca82e8b40e23 Mon Sep 17 00:00:00 2001 From: human9000 Date: Fri, 13 Mar 2026 18:22:43 +0500 Subject: [PATCH] Introduce guard pattern to THIR Co-authored-by: Max Niederman --- compiler/rustc_middle/src/thir.rs | 7 +++++++ compiler/rustc_middle/src/thir/visit.rs | 10 ++++++++++ .../rustc_mir_build/src/builder/matches/match_pair.rs | 5 +++++ compiler/rustc_mir_build/src/builder/matches/mod.rs | 3 +++ compiler/rustc_mir_build/src/check_unsafety.rs | 1 + compiler/rustc_mir_build/src/thir/print.rs | 8 ++++++++ compiler/rustc_pattern_analysis/src/rustc.rs | 3 ++- 7 files changed, 36 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 881165706a03..51f33691bb7d 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -866,6 +866,13 @@ pub enum PatKind<'tcx> { pats: Box<[Pat<'tcx>]>, }, + /// A guard pattern, e.g. `x if guard(x)` + Guard { + subpattern: Box>, + #[type_visitable(ignore)] + condition: ExprId, + }, + /// A never pattern `!`. Never, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index c17e15513cdf..aa1b6b1663bf 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -247,6 +247,12 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor: &mut V, pat: &'thir Pat<'tcx>, ) { + if let PatKind::Guard { subpattern, condition } = &pat.kind { + visitor.visit_pat(subpattern); + visitor.visit_expr(&visitor.thir()[*condition]); + return; + }; + for_each_immediate_subpat(pat, |p| visitor.visit_pat(p)); } @@ -287,5 +293,9 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( callback(pat); } } + + PatKind::Guard { subpattern, .. } => { + callback(subpattern); + } } } diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 7698af4cd38b..cbe31fd7d132 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -360,6 +360,11 @@ pub(super) fn for_pattern( Some(TestableCase::Deref { temp, mutability }) } + PatKind::Guard { .. } => { + // FIXME(guard_patterns) + None + } + PatKind::Never => Some(TestableCase::Never), }; diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index d7edf82ae4af..d4f5fe84e0ff 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -944,6 +944,9 @@ fn visit_primary_bindings_special( visit_subpat(self, subpattern, user_tys, f); } } + PatKind::Guard { ref subpattern, .. } => { + visit_subpat(self, subpattern, user_tys, f); + } } } } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index ee35539221e6..aed0c6e6085d 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -315,6 +315,7 @@ fn visit_pat(&mut self, pat: &'a Pat<'tcx>) { | PatKind::Range { .. } | PatKind::Slice { .. } | PatKind::Array { .. } + | PatKind::Guard { .. } // Never constitutes a witness of uninhabitedness. | PatKind::Never => { self.requires_unsafe(pat.span, AccessToUnionField); diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 27dec99696f5..ea34e5f4d97d 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -844,6 +844,14 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) { print_indented!(self, "]", depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } + PatKind::Guard { subpattern, condition } => { + print_indented!(self, "Guard pattern: {", depth_lvl + 1); + print_indented!(self, "subpattern: ", depth_lvl + 2); + self.print_pat(subpattern, depth_lvl + 3); + print_indented!(self, "guard: ", depth_lvl + 2); + self.print_expr(*condition, depth_lvl + 3); + print_indented!(self, "}", depth_lvl + 1); + } PatKind::Error(_) => { print_indented!(self, "Error", depth_lvl + 1); } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index dc38f2d8bc70..0226c54db58c 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -462,7 +462,8 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> { let arity; let fields: Vec<_>; match &pat.kind { - PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), + PatKind::Binding { subpattern: Some(subpat), .. } + | PatKind::Guard { subpattern: subpat, .. } => return self.lower_pat(subpat), PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = vec![];