Skip to content

Commit 881afdf

Browse files
committed
add guard patterns to HIR and implement lowering
1 parent f586c16 commit 881afdf

File tree

11 files changed

+42
-6
lines changed

11 files changed

+42
-6
lines changed

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
114114
self.lower_range_end(end, e2.is_some()),
115115
);
116116
}
117-
PatKind::Guard(_, _) => todo!("implement lowering to HIR"),
117+
PatKind::Guard(inner, cond) => {
118+
break hir::PatKind::Guard(self.lower_pat(inner), self.lower_expr(cond));
119+
}
118120
PatKind::Slice(pats) => break self.lower_pat_slice(pats),
119121
PatKind::Rest => {
120122
// If we reach here the `..` pattern is not semantically allowed.

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,7 @@ impl<'hir> Pat<'hir> {
11391139
use PatKind::*;
11401140
match self.kind {
11411141
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
1142-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
1142+
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
11431143
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
11441144
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
11451145
Slice(before, slice, after) => {
@@ -1166,7 +1166,7 @@ impl<'hir> Pat<'hir> {
11661166
use PatKind::*;
11671167
match self.kind {
11681168
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
1169-
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
1169+
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
11701170
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
11711171
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
11721172
Slice(before, slice, after) => {
@@ -1318,6 +1318,9 @@ pub enum PatKind<'hir> {
13181318
/// A literal.
13191319
Lit(&'hir Expr<'hir>),
13201320

1321+
/// A guard pattern (e.g., `x if guard(x)`).
1322+
Guard(&'hir Pat<'hir>, &'hir Expr<'hir>),
1323+
13211324
/// A range pattern (e.g., `1..=2` or `1..2`).
13221325
Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
13231326

compiler/rustc_hir/src/intravisit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
700700
visit_opt!(visitor, visit_pat, slice_pattern);
701701
walk_list!(visitor, visit_pat, postpatterns);
702702
}
703+
PatKind::Guard(subpat, condition) => {
704+
try_visit!(visitor.visit_pat(subpat));
705+
try_visit!(visitor.visit_expr(condition));
706+
}
703707
}
704708
V::Result::output()
705709
}

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,9 @@ fn resolve_local<'tcx>(
678678
| PatKind::TupleStruct(_, subpats, _)
679679
| PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(p)),
680680

681-
PatKind::Box(subpat) | PatKind::Deref(subpat) => is_binding_pat(subpat),
681+
PatKind::Box(subpat) | PatKind::Deref(subpat) | PatKind::Guard(subpat, _) => {
682+
is_binding_pat(subpat)
683+
}
682684

683685
PatKind::Ref(_, _)
684686
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,12 @@ impl<'a> State<'a> {
18701870
self.commasep(Inconsistent, after, |s, p| s.print_pat(p));
18711871
self.word("]");
18721872
}
1873+
PatKind::Guard(inner, cond) => {
1874+
self.print_pat(inner);
1875+
self.space();
1876+
self.word_space("if");
1877+
self.print_expr(cond);
1878+
}
18731879
PatKind::Err(_) => {
18741880
self.popen();
18751881
self.word("/*ERROR*/");

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
422422
subpats.iter().all(|pat| self.pat_guaranteed_to_constitute_read_for_never(pat))
423423
}
424424

425+
// Passes through to the sub-pattern.
426+
hir::PatKind::Guard(subpat, _) => {
427+
self.pat_guaranteed_to_constitute_read_for_never(subpat)
428+
}
429+
425430
// Does constitute a read, since it is equivalent to a discriminant read.
426431
hir::PatKind::Never => true,
427432

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
612612
| PatKind::Box(_)
613613
| PatKind::Deref(_)
614614
| PatKind::Ref(..)
615+
| PatKind::Guard(..)
615616
| PatKind::Wild
616617
| PatKind::Err(_) => {
617618
// If the PatKind is Or, Box, or Ref, the decision is made later
@@ -1722,7 +1723,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
17221723
}
17231724
}
17241725

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

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 8 additions & 1 deletion
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

@@ -876,6 +882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
876882
PatKind::Struct(..)
877883
| PatKind::TupleStruct(..)
878884
| PatKind::Or(..)
885+
| PatKind::Guard(..)
879886
| PatKind::Tuple(..)
880887
| PatKind::Slice(..) => "binding",
881888

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
407407

408408
hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
409409

410+
hir::PatKind::Guard(..) => {
411+
span_bug!(pat.span, "lowering guard patterns to MIR is not yet implemented");
412+
}
413+
410414
hir::PatKind::Err(guar) => PatKind::Error(guar),
411415
};
412416

compiler/rustc_passes/src/hir_stats.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
296296
Deref,
297297
Ref,
298298
Lit,
299+
Guard,
299300
Range,
300301
Slice,
301302
Err

0 commit comments

Comments
 (0)