diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-03-11 10:36:31 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-11 10:36:31 +0100 |
| commit | a05bab59259fb8baec236363d7f40925644e17ec (patch) | |
| tree | f75c028fcd2ffc05672003db33bb2fae66548181 | |
| parent | 62e3daee3f0f239625de5c7fe54d38e624a3eaa5 (diff) | |
| parent | 4d16c217b8074784b1faad07f5a284e4a6999b53 (diff) | |
| download | rust-a05bab59259fb8baec236363d7f40925644e17ec.tar.gz rust-a05bab59259fb8baec236363d7f40925644e17ec.zip | |
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 https://github.com/rust-lang/rust/issues/69875. r? @varkor cc @Nadrieril cc https://github.com/rust-lang/rust/issues/54883
4 files changed, 48 insertions, 1 deletions
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 71aefa85c99..37ad5f5ea4e 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -480,7 +480,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it. crate fn push(&mut self, row: PatStack<'p, 'tcx>) { if let Some(rows) = row.expand_or_pat() { - self.0.extend(rows); + for row in rows { + // We recursively expand the or-patterns of the new rows. + // This is necessary as we might have `0 | (1 | 2)` or e.g., `x @ 0 | x @ (1 | 2)`. + self.push(row) + } } else { self.0.push(row); } diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs new file mode 100644 index 00000000000..59533cefea6 --- /dev/null +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs @@ -0,0 +1,9 @@ +#![feature(or_patterns)] + +fn main() { + let 0 | (1 | 2) = 0; //~ ERROR refutable pattern in local binding + match 0 { + //~^ ERROR non-exhaustive patterns + 0 | (1 | 2) => {} + } +} diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr new file mode 100644 index 00000000000..58286e87869 --- /dev/null +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -0,0 +1,25 @@ +error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9 + | +LL | let 0 | (1 | 2) = 0; + | ^^^^^^^^^^^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let 0 | (1 | 2) = 0 { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0004]: non-exhaustive patterns: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11 + | +LL | match 0 { + | ^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs new file mode 100644 index 00000000000..1de563dedbf --- /dev/null +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs @@ -0,0 +1,9 @@ +// check-pass + +#![feature(or_patterns)] + +fn main() { + let 0 | (1 | _) = 0; + if let 0 | (1 | 2) = 0 {} + if let x @ 0 | x @ (1 | 2) = 0 {} +} |
