Skip to content

Commit 63464c2

Browse files
authored
Rollup merge of #69891 - Centril:fix-69875, r=varkor
Exhaustiveness checking, `Matrix::push`: recursively expand or-patterns > There's an implicit invariant that there should be no or-patterns directly in the first column of the matrix, but this invariant is broken exactly when an or-pattern has a child that is itself an or-pattern. Here we preserve this broken invariant by recursively expanding `PatKind::Or`s in `Matrix::push`. Fixes #69875. r? @varkor cc @Nadrieril cc #54883
2 parents 8e011e8 + 4d16c21 commit 63464c2

4 files changed

+48
-1
lines changed

src/librustc_mir_build/hair/pattern/_match.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
480480
/// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
481481
crate fn push(&mut self, row: PatStack<'p, 'tcx>) {
482482
if let Some(rows) = row.expand_or_pat() {
483-
self.0.extend(rows);
483+
for row in rows {
484+
// We recursively expand the or-patterns of the new rows.
485+
// This is necessary as we might have `0 | (1 | 2)` or e.g., `x @ 0 | x @ (1 | 2)`.
486+
self.push(row)
487+
}
484488
} else {
485489
self.0.push(row);
486490
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![feature(or_patterns)]
2+
3+
fn main() {
4+
let 0 | (1 | 2) = 0; //~ ERROR refutable pattern in local binding
5+
match 0 {
6+
//~^ ERROR non-exhaustive patterns
7+
0 | (1 | 2) => {}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
2+
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9
3+
|
4+
LL | let 0 | (1 | 2) = 0;
5+
| ^^^^^^^^^^^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
6+
|
7+
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
8+
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
9+
help: you might want to use `if let` to ignore the variant that isn't matched
10+
|
11+
LL | if let 0 | (1 | 2) = 0 { /* */ }
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
14+
error[E0004]: non-exhaustive patterns: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
15+
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11
16+
|
17+
LL | match 0 {
18+
| ^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
19+
|
20+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
21+
22+
error: aborting due to 2 previous errors
23+
24+
Some errors have detailed explanations: E0004, E0005.
25+
For more information about an error, try `rustc --explain E0004`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// check-pass
2+
3+
#![feature(or_patterns)]
4+
5+
fn main() {
6+
let 0 | (1 | _) = 0;
7+
if let 0 | (1 | 2) = 0 {}
8+
if let x @ 0 | x @ (1 | 2) = 0 {}
9+
}

0 commit comments

Comments
 (0)