diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index aca1390935ef1..64d1e86704d33 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -640,7 +640,8 @@ impl<'tcx> Pat<'tcx> { | Binding { subpattern: Some(subpattern), .. } | Deref { subpattern } | DerefPattern { subpattern, .. } - | InlineConstant { subpattern, .. } => subpattern.walk_(it), + | InlineConstant { subpattern, .. } + | Guard { subpattern, .. } => subpattern.walk_(it), Leaf { subpatterns } | Variant { subpatterns, .. } => { subpatterns.iter().for_each(|field| field.pattern.walk_(it)) } @@ -823,6 +824,13 @@ pub enum PatKind<'tcx> { pats: Box<[Box>]>, }, + /// 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 e246ecebbec0b..342abf864ad3b 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -256,5 +256,9 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor.visit_pat(pat); } } + Guard { subpattern, condition } => { + visitor.visit_pat(subpattern); + visitor.visit_expr(&visitor.thir()[*condition]); + } }; } diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index ab2bfcbca3aa6..993bacca25363 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -1,4 +1,5 @@ use rustc_middle::mir::*; +use rustc_middle::span_bug; use rustc_middle::thir::{self, *}; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -248,6 +249,10 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { } PatKind::Never => TestCase::Never, + + PatKind::Guard { .. } => { + span_bug!(pattern.span, "MIR lowering is not yet implemented for guard patterns") + } }; MatchPairTree { place, test_case, subpairs, pattern } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index cae4aa7bad3d2..fabd754bf0469 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -936,6 +936,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.visit_primary_bindings(subpattern, pattern_user_ty, f) } + PatKind::Guard { ref subpattern, .. } => { + self.visit_primary_bindings(subpattern, pattern_user_ty, f); + } + PatKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field); diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index b6cf7a40ecd98..c3297d1efe8b8 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -326,6 +326,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { PatKind::Or { .. } | PatKind::InlineConstant { .. } | PatKind::AscribeUserType { .. } | + PatKind::Guard { .. } | PatKind::Error(_) => {} } }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 88d0e0aadd768..5e2066def4769 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -397,7 +397,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) }, hir::PatKind::Guard(..) => { - span_bug!(pat.span, "lowering guard patterns to MIR is not yet implemented"); + span_bug!(pat.span, "lowering guard patterns to THIR is not yet implemented"); } hir::PatKind::Err(guar) => PatKind::Error(guar), diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index ce7774f594882..366454738d195 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -763,6 +763,14 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "]", depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } + PatKind::Guard { subpattern, condition } => { + print_indented!(self, "Guard {", depth_lvl + 1); + print_indented!(self, "subpattern:", depth_lvl + 2); + self.print_pat(subpattern, depth_lvl + 3); + print_indented!(self, "condition:", 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 d7885e05a2ffc..f770c46dddb0d 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -459,7 +459,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } - | PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern), + | PatKind::InlineConstant { subpattern, .. } + | PatKind::Guard { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard;