Skip to content

Commit 56ba13a

Browse files
authored
Rollup merge of #98200 - ouz-a:issue-98177, r=oli-obk
Expand potential inner `Or` pattern for THIR Code assumed there wouldn't be a deeper `Or` pattern inside expanded `PatStack` this fixes it by looking for the `Or` pattern inside expanded `PatStack`. A more ideal solution would be recursively doing this but I haven't found a good way to do that. _fixes #97898_
2 parents a8a33cf + ddf23cb commit 56ba13a

File tree

4 files changed

+114
-4
lines changed

4 files changed

+114
-4
lines changed

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

+19-4
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,8 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
364364
/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
365365
/// works well.
366366
#[derive(Clone)]
367-
struct PatStack<'p, 'tcx> {
368-
pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
367+
pub(crate) struct PatStack<'p, 'tcx> {
368+
pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
369369
}
370370

371371
impl<'p, 'tcx> PatStack<'p, 'tcx> {
@@ -403,6 +403,21 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
403403
})
404404
}
405405

406+
// Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix.
407+
fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) {
408+
if !self.is_empty() && self.head().is_or_pat() {
409+
for pat in self.head().iter_fields() {
410+
let mut new_patstack = PatStack::from_pattern(pat);
411+
new_patstack.pats.extend_from_slice(&self.pats[1..]);
412+
if !new_patstack.is_empty() && new_patstack.head().is_or_pat() {
413+
new_patstack.expand_and_extend(matrix);
414+
} else if !new_patstack.is_empty() {
415+
matrix.push(new_patstack);
416+
}
417+
}
418+
}
419+
}
420+
406421
/// This computes `S(self.head().ctor(), self)`. See top of the file for explanations.
407422
///
408423
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
@@ -436,7 +451,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
436451
/// A 2D matrix.
437452
#[derive(Clone)]
438453
pub(super) struct Matrix<'p, 'tcx> {
439-
patterns: Vec<PatStack<'p, 'tcx>>,
454+
pub patterns: Vec<PatStack<'p, 'tcx>>,
440455
}
441456

442457
impl<'p, 'tcx> Matrix<'p, 'tcx> {
@@ -453,7 +468,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
453468
/// expands it.
454469
fn push(&mut self, row: PatStack<'p, 'tcx>) {
455470
if !row.is_empty() && row.head().is_or_pat() {
456-
self.patterns.extend(row.expand_or_pat());
471+
row.expand_and_extend(self);
457472
} else {
458473
self.patterns.push(row);
459474
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/inner-or-pat.rs:38:54
3+
|
4+
LL | match x {
5+
| - this expression has type `&str`
6+
LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
7+
| ^^ expected `str`, found `()`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0408]: variable `x` is not bound in all patterns
2+
--> $DIR/inner-or-pat.rs:53:37
3+
|
4+
LL | (x @ "red" | (x @ "blue" | "red")) => {
5+
| - ^^^^^ pattern doesn't bind `x`
6+
| |
7+
| variable not in all patterns
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0408`.
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// revisions: or1 or2 or3 or4 or5
2+
// [or1] run-pass
3+
// [or2] run-pass
4+
// [or5] run-pass
5+
6+
#![allow(unreachable_patterns)]
7+
#![allow(unused_variables)]
8+
#![allow(unused_parens)]
9+
#![allow(dead_code)]
10+
11+
12+
13+
fn foo() {
14+
let x = "foo";
15+
match x {
16+
x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) |
17+
x @ ("black" | "pink") |
18+
x @ ("red" | "blue") => {
19+
}
20+
_ => (),
21+
}
22+
}
23+
24+
fn bar() {
25+
let x = "foo";
26+
match x {
27+
x @ ("foo" | "bar") |
28+
(x @ "red" | (x @ "blue" | x @ "red")) => {
29+
}
30+
_ => (),
31+
}
32+
}
33+
34+
#[cfg(or3)]
35+
fn zot() {
36+
let x = "foo";
37+
match x {
38+
x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
39+
//[or3]~^ ERROR mismatched types
40+
x @ ("black" | "pink") |
41+
x @ ("red" | "blue") => {
42+
}
43+
_ => (),
44+
}
45+
}
46+
47+
48+
#[cfg(or4)]
49+
fn hey() {
50+
let x = "foo";
51+
match x {
52+
x @ ("foo" | "bar") |
53+
(x @ "red" | (x @ "blue" | "red")) => {
54+
//[or4]~^ variable `x` is not bound in all patterns
55+
}
56+
_ => (),
57+
}
58+
}
59+
60+
fn don() {
61+
enum Foo {
62+
A,
63+
B,
64+
C,
65+
}
66+
67+
match Foo::A {
68+
| _foo @ (Foo::A | Foo::B) => {}
69+
Foo::C => {}
70+
};
71+
}
72+
73+
fn main(){}

0 commit comments

Comments
 (0)