Skip to content

Commit c63e01e

Browse files
committed
implement or-patterns
1 parent b4cba1f commit c63e01e

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

compiler/rustc_mir_build/src/builder/expr/into.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
330330
);
331331
}
332332

333+
// handle patterns like `None | None` or two different arms that
334+
// have the same pattern.
335+
//
336+
// NOTE: why this works is a bit subtle: we always want to pick the
337+
// first arm for a pattern, and because this is a stable sort that
338+
// works out.
339+
arm_blocks.sort_by_key(|(_, discr, _, _)| discr.val);
340+
arm_blocks.dedup_by_key(|(_, discr, _, _)| discr.val);
341+
333342
// if we're matching on an enum, the discriminant order in the `SwitchInt`
334343
// targets should match the order yielded by `AdtDef::discriminants`.
335344
if state_ty.is_enum() {
@@ -378,6 +387,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
378387
.chain(otherwise);
379388

380389
for (mut block, arm) in it {
390+
if this.cfg.block_data(block).terminator.is_some() {
391+
continue; // this can occur with or-patterns
392+
}
393+
381394
let empty_place = this.get_unit_temp();
382395
unpack!(
383396
block = this.expr_into_dest(
@@ -850,8 +863,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
850863
result.push((VariantIdx::ZERO, discr, block, arm_id));
851864
}
852865
Constructor::Wildcard => {
866+
// the first wildcard wins
867+
if otherwise.is_none() {
868+
let block = current_block.unwrap_or_else(|| self.cfg.start_new_block());
869+
*otherwise = Some((block, arm_id))
870+
}
871+
}
872+
Constructor::Or => {
853873
let block = current_block.unwrap_or_else(|| self.cfg.start_new_block());
854-
*otherwise = Some((block, arm_id))
874+
875+
for indexed in pat.iter_fields() {
876+
self.loop_match_patterns(arm_id, &indexed.pat, Some(block), result, otherwise);
877+
}
855878
}
856879
other => todo!("{:?}", other),
857880
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//@ run-pass
2+
3+
#![feature(loop_match)]
4+
5+
enum State {
6+
A,
7+
B,
8+
C,
9+
D,
10+
}
11+
12+
fn main() {
13+
let mut state = State::A;
14+
#[loop_match]
15+
'a: loop {
16+
state = 'blk: {
17+
match state {
18+
State::A => {
19+
if true {
20+
#[const_continue]
21+
break 'blk State::B;
22+
} else {
23+
#[const_continue]
24+
break 'blk State::D;
25+
}
26+
}
27+
State::B | State::D => {
28+
if true {
29+
#[const_continue]
30+
break 'blk State::C;
31+
} else {
32+
// No drops allowed at this point
33+
#[const_continue]
34+
break 'blk State::A;
35+
}
36+
}
37+
State::C => break 'a,
38+
}
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)