Skip to content

Commit c6f3c07

Browse files
committedSep 22, 2024
add guard patterns to HIR and implement lowering
1 parent 20a26ad commit c6f3c07

File tree

10 files changed

+37
-6
lines changed

10 files changed

+37
-6
lines changed
 

‎compiler/rustc_ast_lowering/src/pat.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
104104
self.lower_range_end(end, e2.is_some()),
105105
);
106106
}
107-
PatKind::Guard(_, _) => todo!("implement lowering to HIR"),
107+
PatKind::Guard(inner, cond) => {
108+
break hir::PatKind::Guard(self.lower_pat(inner), self.lower_expr(cond));
109+
}
108110
PatKind::Slice(pats) => break self.lower_pat_slice(pats),
109111
PatKind::Rest => {
110112
// If we reach here the `..` pattern is not semantically allowed.

‎compiler/rustc_hir/src/hir.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ impl<'hir> Pat<'hir> {
11441144
use PatKind::*;
11451145
match self.kind {
11461146
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
1147-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
1147+
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
11481148
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
11491149
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
11501150
Slice(before, slice, after) => {
@@ -1171,7 +1171,7 @@ impl<'hir> Pat<'hir> {
11711171
use PatKind::*;
11721172
match self.kind {
11731173
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
1174-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
1174+
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
11751175
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
11761176
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
11771177
Slice(before, slice, after) => {
@@ -1323,6 +1323,9 @@ pub enum PatKind<'hir> {
13231323
/// A literal.
13241324
Lit(&'hir Expr<'hir>),
13251325

1326+
/// A guard pattern (e.g., `x if guard(x)`).
1327+
Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
1328+
13261329
/// A range pattern (e.g., `1..=2` or `1..2`).
13271330
Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
13281331

‎compiler/rustc_hir/src/intravisit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
698698
visit_opt!(visitor, visit_pat, slice_pattern);
699699
walk_list!(visitor, visit_pat, postpatterns);
700700
}
701+
PatKind::Guard(subpat, condition) => {
702+
try_visit!(visitor.visit_pat(subpat));
703+
try_visit!(visitor.visit_expr(condition));
704+
}
701705
}
702706
V::Result::output()
703707
}

‎compiler/rustc_hir_analysis/src/check/region.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,9 @@ fn resolve_local<'tcx>(
680680
| PatKind::TupleStruct(_, subpats, _)
681681
| PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(p)),
682682

683-
PatKind::Box(subpat) | PatKind::Deref(subpat) => is_binding_pat(subpat),
683+
PatKind::Box(subpat) | PatKind::Deref(subpat) | PatKind::Guard(subpat, _) => {
684+
is_binding_pat(subpat)
685+
}
684686

685687
PatKind::Ref(_, _)
686688
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)

‎compiler/rustc_hir_pretty/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,12 @@ impl<'a> State<'a> {
18581858
self.commasep(Inconsistent, after, |s, p| s.print_pat(p));
18591859
self.word("]");
18601860
}
1861+
PatKind::Guard(inner, cond) => {
1862+
self.print_pat(inner);
1863+
self.space();
1864+
self.word_space("if");
1865+
self.print_expr(cond);
1866+
}
18611867
PatKind::Err(_) => {
18621868
self.popen();
18631869
self.word("/*ERROR*/");

‎compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
610610
| PatKind::Box(_)
611611
| PatKind::Deref(_)
612612
| PatKind::Ref(..)
613+
| PatKind::Guard(..)
613614
| PatKind::Wild
614615
| PatKind::Err(_) => {
615616
// If the PatKind is Or, Box, or Ref, the decision is made later
@@ -1723,7 +1724,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
17231724
}
17241725
}
17251726

1726-
PatKind::Binding(.., Some(subpat)) => {
1727+
PatKind::Binding(.., Some(subpat)) | PatKind::Guard(subpat, _) => {
17271728
self.cat_pattern(place_with_id, subpat, op)?;
17281729
}
17291730

‎compiler/rustc_hir_typeck/src/pat.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259259
PatKind::Struct(ref qpath, fields, has_rest_pat) => {
260260
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
261261
}
262+
PatKind::Guard(pat, _) => {
263+
self.check_pat(pat, expected, pat_info);
264+
expected
265+
}
262266
PatKind::Or(pats) => {
263267
for pat in pats {
264268
self.check_pat(pat, expected, pat_info);
@@ -397,7 +401,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
397401
// An OR-pattern just propagates to each individual alternative.
398402
// This is maximally flexible, allowing e.g., `Some(mut x) | &Some(mut x)`.
399403
// In that example, `Some(mut x)` results in `Peel` whereas `&Some(mut x)` in `Reset`.
400-
| PatKind::Or(_) => AdjustMode::Pass,
404+
| PatKind::Or(_)
405+
// Like or-patterns, guard patterns just propogate to their subpatterns.
406+
| PatKind::Guard(..) => AdjustMode::Pass,
401407
}
402408
}
403409

@@ -862,6 +868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
862868
PatKind::Struct(..)
863869
| PatKind::TupleStruct(..)
864870
| PatKind::Or(..)
871+
| PatKind::Guard(..)
865872
| PatKind::Tuple(..)
866873
| PatKind::Slice(..) => "binding",
867874

‎compiler/rustc_mir_build/src/thir/pattern/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
396396

397397
hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
398398

399+
hir::PatKind::Guard(..) => {
400+
span_bug!(pat.span, "lowering guard patterns to MIR is not yet implemented");
401+
}
402+
399403
hir::PatKind::Err(guar) => PatKind::Error(guar),
400404
};
401405

‎compiler/rustc_passes/src/hir_stats.rs

+1
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
301301
Deref,
302302
Ref,
303303
Lit,
304+
Guard,
304305
Range,
305306
Slice,
306307
Err

‎src/librustdoc/clean/utils.rs

+1
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
331331
);
332332
return Symbol::intern("()");
333333
}
334+
PatKind::Guard(p, _) => return name_from_pat(&*p),
334335
PatKind::Range(..) => return kw::Underscore,
335336
PatKind::Slice(begin, ref mid, end) => {
336337
let begin = begin.iter().map(|p| name_from_pat(p).to_string());

0 commit comments

Comments
 (0)