Skip to content

Commit 94df5ce

Browse files
committed
Auto merge of #154545 - Human9000-bit:guard-patterns-mir, r=<try>
Guard patterns: MIR lowering
2 parents 584d32e + 1d0134e commit 94df5ce

4 files changed

Lines changed: 59 additions & 46 deletions

File tree

compiler/rustc_mir_build/src/builder/matches/match_pair.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,10 @@ impl<'tcx> MatchPairTree<'tcx> {
360360
Some(TestableCase::Deref { temp, mutability })
361361
}
362362

363-
PatKind::Guard { .. } => {
364-
// FIXME(guard_patterns)
365-
None
363+
PatKind::Guard { ref subpattern, condition } => {
364+
extra_data.guard_patterns.push(condition);
365+
MatchPairTree::for_pattern(place_builder, subpattern, cx, match_pairs, extra_data);
366+
return;
366367
}
367368

368369
PatKind::Never => Some(TestableCase::Never),

compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,9 @@ struct PatternExtraData<'tcx> {
966966

967967
/// Whether this corresponds to a never pattern.
968968
is_never: bool,
969+
970+
/// [`ExprId`]s of subpattern conditions
971+
guard_patterns: Vec<ExprId>,
969972
}
970973

971974
impl<'tcx> PatternExtraData<'tcx> {
@@ -1010,6 +1013,7 @@ impl<'tcx> FlatPat<'tcx> {
10101013
bindings: Vec::new(),
10111014
ascriptions: Vec::new(),
10121015
is_never: pattern.is_never_pattern(),
1016+
guard_patterns: Vec::new(),
10131017
};
10141018
MatchPairTree::for_pattern(place, pattern, cx, &mut match_pairs, &mut extra_data);
10151019

@@ -1422,6 +1426,8 @@ struct MatchTreeSubBranch<'tcx> {
14221426
bindings: Vec<Binding<'tcx>>,
14231427
/// The ascriptions to set up in this sub-branch.
14241428
ascriptions: Vec<Ascription<'tcx>>,
1429+
/// The guard patterns present in this sub-branch
1430+
guard_patterns: Vec<ExprId>,
14251431
/// Whether the sub-branch corresponds to a never pattern.
14261432
is_never: bool,
14271433
}
@@ -1473,6 +1479,7 @@ impl<'tcx> MatchTreeSubBranch<'tcx> {
14731479
.cloned()
14741480
.chain(candidate.extra_data.ascriptions)
14751481
.collect(),
1482+
guard_patterns: candidate.extra_data.guard_patterns,
14761483
is_never: candidate.extra_data.is_never,
14771484
}
14781485
}
@@ -2428,11 +2435,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
24282435

24292436
// Lower an instance of the arm guard (if present) for this candidate,
24302437
// and then perform bindings for the arm body.
2431-
if let Some((arm, match_scope)) = arm_match_scope
2432-
&& let Some(guard) = arm.guard
2433-
{
2438+
if let Some((arm, match_scope)) = arm_match_scope {
24342439
let tcx = self.tcx;
24352440

2441+
let mut guards = sub_branch.guard_patterns;
2442+
if let Some(guard) = arm.guard {
2443+
guards.push(guard);
2444+
};
2445+
2446+
if guards.is_empty() {
2447+
self.bind_matched_candidate_for_arm_body(
2448+
block,
2449+
schedule_drops,
2450+
sub_branch.bindings.iter(),
2451+
);
2452+
2453+
return block;
2454+
};
2455+
24362456
// Bindings for guards require some extra handling to automatically
24372457
// insert implicit references/dereferences.
24382458
// This always schedules storage drops, so we may need to unschedule them below.
@@ -2458,14 +2478,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
24582478

24592479
let (post_guard_block, otherwise_post_guard_block) =
24602480
self.in_if_then_scope(match_scope, guard_span, |this| {
2461-
guard_span = this.thir[guard].span;
2462-
this.then_else_break(
2463-
block,
2464-
guard,
2465-
None, // Use `self.local_scope()` as the temp scope
2466-
this.source_info(arm.span),
2467-
DeclareLetBindings::No, // For guards, `let` bindings are declared separately
2468-
)
2481+
guards.into_iter().fold(BlockAnd(block, ()), |block, guard| {
2482+
guard_span = this.thir[guard].span;
2483+
this.then_else_break(
2484+
block.0,
2485+
guard,
2486+
None, // Use `self.local_scope()` as the temp scope
2487+
this.source_info(arm.span),
2488+
DeclareLetBindings::No, // For guards, `let` bindings are declared separately
2489+
)
2490+
})
24692491
});
24702492

24712493
// If this isn't the final sub-branch being lowered, we need to unschedule drops of

tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#![expect(incomplete_features)]
77

88
fn good_fn_item(((x if x) | x): bool) -> bool { x }
9-
//~^ ERROR: used binding `x` is possibly-uninitialized [E0381]
109

1110
fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
1211
//~^ ERROR cannot find value `x` in this scope

tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0408]: variable `y` is not bound in all patterns
2-
--> $DIR/name-resolution.rs:38:10
2+
--> $DIR/name-resolution.rs:37:10
33
|
44
LL | ((Ok(x) if y) | (Err(y) if x),) => x && y,
55
| ^^^^^^^^^^^^ - variable not in all patterns
@@ -13,7 +13,7 @@ LL + ((Ok(x) if y) | (Err(x) if x),) => x && y,
1313
|
1414

1515
error[E0408]: variable `x` is not bound in all patterns
16-
--> $DIR/name-resolution.rs:38:25
16+
--> $DIR/name-resolution.rs:37:25
1717
|
1818
LL | ((Ok(x) if y) | (Err(y) if x),) => x && y,
1919
| - ^^^^^^^^^^^^^ pattern doesn't bind `x`
@@ -27,15 +27,15 @@ LL + ((Ok(y) if y) | (Err(y) if x),) => x && y,
2727
|
2828

2929
error[E0408]: variable `x` is not bound in all patterns
30-
--> $DIR/name-resolution.rs:64:28
30+
--> $DIR/name-resolution.rs:63:28
3131
|
3232
LL | Some(x if x > 0) | None => {}
3333
| - ^^^^ pattern doesn't bind `x`
3434
| |
3535
| variable not in all patterns
3636

3737
error[E0425]: cannot find value `x` in this scope
38-
--> $DIR/name-resolution.rs:11:34
38+
--> $DIR/name-resolution.rs:10:34
3939
|
4040
LL | fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
4141
| ^
@@ -47,7 +47,7 @@ LL + fn bad_fn_item_1(x: bool, ((y if y) | y): bool) {}
4747
|
4848

4949
error[E0425]: cannot find value `y` in this scope
50-
--> $DIR/name-resolution.rs:13:25
50+
--> $DIR/name-resolution.rs:12:25
5151
|
5252
LL | fn bad_fn_item_2(((x if y) | x): bool, y: bool) {}
5353
| ^
@@ -59,7 +59,7 @@ LL + fn bad_fn_item_2(((x if x) | x): bool, y: bool) {}
5959
|
6060

6161
error[E0425]: cannot find value `x` in this scope
62-
--> $DIR/name-resolution.rs:21:18
62+
--> $DIR/name-resolution.rs:20:18
6363
|
6464
LL | (x, y if x) => x && y,
6565
| ^
@@ -71,7 +71,7 @@ LL + (x, y if y) => x && y,
7171
|
7272

7373
error[E0425]: cannot find value `y` in this scope
74-
--> $DIR/name-resolution.rs:23:15
74+
--> $DIR/name-resolution.rs:22:15
7575
|
7676
LL | (x if y, y) => x && y,
7777
| ^
@@ -83,7 +83,7 @@ LL + (x if x, y) => x && y,
8383
|
8484

8585
error[E0425]: cannot find value `x` in this scope
86-
--> $DIR/name-resolution.rs:30:20
86+
--> $DIR/name-resolution.rs:29:20
8787
|
8888
LL | (x @ (y if x),) => x && y,
8989
| ^
@@ -95,7 +95,7 @@ LL + (x @ (y if y),) => x && y,
9595
|
9696

9797
error[E0425]: cannot find value `y` in this scope
98-
--> $DIR/name-resolution.rs:38:20
98+
--> $DIR/name-resolution.rs:37:20
9999
|
100100
LL | ((Ok(x) if y) | (Err(y) if x),) => x && y,
101101
| ^
@@ -107,7 +107,7 @@ LL + ((Ok(x) if x) | (Err(y) if x),) => x && y,
107107
|
108108

109109
error[E0425]: cannot find value `x` in this scope
110-
--> $DIR/name-resolution.rs:38:36
110+
--> $DIR/name-resolution.rs:37:36
111111
|
112112
LL | ((Ok(x) if y) | (Err(y) if x),) => x && y,
113113
| ^
@@ -119,13 +119,13 @@ LL + ((Ok(x) if y) | (Err(y) if y),) => x && y,
119119
|
120120

121121
error[E0425]: cannot find value `nonexistent` in this scope
122-
--> $DIR/name-resolution.rs:45:15
122+
--> $DIR/name-resolution.rs:44:15
123123
|
124124
LL | let (_ if nonexistent) = true;
125125
| ^^^^^^^^^^^ not found in this scope
126126

127127
error[E0425]: cannot find value `x` in this scope
128-
--> $DIR/name-resolution.rs:47:22
128+
--> $DIR/name-resolution.rs:46:22
129129
|
130130
LL | if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
131131
| ^
@@ -137,7 +137,7 @@ LL + if let ((x, y if y) | (x if y, y)) = (true, true) { x && y; }
137137
|
138138

139139
error[E0425]: cannot find value `y` in this scope
140-
--> $DIR/name-resolution.rs:47:33
140+
--> $DIR/name-resolution.rs:46:33
141141
|
142142
LL | if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
143143
| ^
@@ -149,7 +149,7 @@ LL + if let ((x, y if x) | (x if x, y)) = (true, true) { x && y; }
149149
|
150150

151151
error[E0425]: cannot find value `x` in this scope
152-
--> $DIR/name-resolution.rs:50:25
152+
--> $DIR/name-resolution.rs:49:25
153153
|
154154
LL | while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
155155
| ^
@@ -161,7 +161,7 @@ LL + while let ((x, y if y) | (x if y, y)) = (true, true) { x && y; }
161161
|
162162

163163
error[E0425]: cannot find value `y` in this scope
164-
--> $DIR/name-resolution.rs:50:36
164+
--> $DIR/name-resolution.rs:49:36
165165
|
166166
LL | while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
167167
| ^
@@ -173,7 +173,7 @@ LL + while let ((x, y if x) | (x if x, y)) = (true, true) { x && y; }
173173
|
174174

175175
error[E0425]: cannot find value `x` in this scope
176-
--> $DIR/name-resolution.rs:53:19
176+
--> $DIR/name-resolution.rs:52:19
177177
|
178178
LL | for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
179179
| ^
@@ -185,7 +185,7 @@ LL + for ((x, y if y) | (x if y, y)) in [(true, true)] { x && y; }
185185
|
186186

187187
error[E0425]: cannot find value `y` in this scope
188-
--> $DIR/name-resolution.rs:53:30
188+
--> $DIR/name-resolution.rs:52:30
189189
|
190190
LL | for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
191191
| ^
@@ -197,7 +197,7 @@ LL + for ((x, y if x) | (x if x, y)) in [(true, true)] { x && y; }
197197
|
198198

199199
error[E0425]: cannot find value `y` in this scope
200-
--> $DIR/name-resolution.rs:58:13
200+
--> $DIR/name-resolution.rs:57:13
201201
|
202202
LL | (|(x if y), (y if x)| x && y)(true, true);
203203
| ^
@@ -209,7 +209,7 @@ LL + (|(x if x), (y if x)| x && y)(true, true);
209209
|
210210

211211
error[E0425]: cannot find value `x` in this scope
212-
--> $DIR/name-resolution.rs:58:23
212+
--> $DIR/name-resolution.rs:57:23
213213
|
214214
LL | (|(x if y), (y if x)| x && y)(true, true);
215215
| ^
@@ -221,24 +221,15 @@ LL + (|(x if y), (y if y)| x && y)(true, true);
221221
|
222222

223223
error[E0308]: mismatched types
224-
--> $DIR/name-resolution.rs:76:18
224+
--> $DIR/name-resolution.rs:75:18
225225
|
226226
LL | local if local => 0,
227227
| ^^^^^ expected `bool`, found `({integer}, {integer})`
228228
|
229229
= note: expected type `bool`
230230
found tuple `({integer}, {integer})`
231231

232-
error[E0381]: used binding `x` is possibly-uninitialized
233-
--> $DIR/name-resolution.rs:8:49
234-
|
235-
LL | fn good_fn_item(((x if x) | x): bool) -> bool { x }
236-
| - - ^ `x` used here but it is possibly-uninitialized
237-
| | |
238-
| | binding initialized here in some conditions
239-
| binding declared here but left uninitialized
240-
241-
error: aborting due to 21 previous errors
232+
error: aborting due to 20 previous errors
242233

243-
Some errors have detailed explanations: E0308, E0381, E0408, E0425.
234+
Some errors have detailed explanations: E0308, E0408, E0425.
244235
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)