Skip to content

Commit

Permalink
Rollup merge of #98200 - ouz-a:issue-98177, r=oli-obk
Browse files Browse the repository at this point in the history
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_
  • Loading branch information
Dylan-DPC authored Aug 22, 2022
2 parents a8a33cf + ddf23cb commit 56ba13a
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 4 deletions.
23 changes: 19 additions & 4 deletions compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,8 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
/// works well.
#[derive(Clone)]
struct PatStack<'p, 'tcx> {
pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
pub(crate) struct PatStack<'p, 'tcx> {
pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
}

impl<'p, 'tcx> PatStack<'p, 'tcx> {
Expand Down Expand Up @@ -403,6 +403,21 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
})
}

// Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix.
fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) {
if !self.is_empty() && self.head().is_or_pat() {
for pat in self.head().iter_fields() {
let mut new_patstack = PatStack::from_pattern(pat);
new_patstack.pats.extend_from_slice(&self.pats[1..]);
if !new_patstack.is_empty() && new_patstack.head().is_or_pat() {
new_patstack.expand_and_extend(matrix);
} else if !new_patstack.is_empty() {
matrix.push(new_patstack);
}
}
}
}

/// This computes `S(self.head().ctor(), self)`. See top of the file for explanations.
///
/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
Expand Down Expand Up @@ -436,7 +451,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
/// A 2D matrix.
#[derive(Clone)]
pub(super) struct Matrix<'p, 'tcx> {
patterns: Vec<PatStack<'p, 'tcx>>,
pub patterns: Vec<PatStack<'p, 'tcx>>,
}

impl<'p, 'tcx> Matrix<'p, 'tcx> {
Expand All @@ -453,7 +468,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
/// expands it.
fn push(&mut self, row: PatStack<'p, 'tcx>) {
if !row.is_empty() && row.head().is_or_pat() {
self.patterns.extend(row.expand_or_pat());
row.expand_and_extend(self);
} else {
self.patterns.push(row);
}
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/or-patterns/inner-or-pat.or3.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/inner-or-pat.rs:38:54
|
LL | match x {
| - this expression has type `&str`
LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
| ^^ expected `str`, found `()`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
11 changes: 11 additions & 0 deletions src/test/ui/or-patterns/inner-or-pat.or4.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0408]: variable `x` is not bound in all patterns
--> $DIR/inner-or-pat.rs:53:37
|
LL | (x @ "red" | (x @ "blue" | "red")) => {
| - ^^^^^ pattern doesn't bind `x`
| |
| variable not in all patterns

error: aborting due to previous error

For more information about this error, try `rustc --explain E0408`.
73 changes: 73 additions & 0 deletions src/test/ui/or-patterns/inner-or-pat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// revisions: or1 or2 or3 or4 or5
// [or1] run-pass
// [or2] run-pass
// [or5] run-pass

#![allow(unreachable_patterns)]
#![allow(unused_variables)]
#![allow(unused_parens)]
#![allow(dead_code)]



fn foo() {
let x = "foo";
match x {
x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) |
x @ ("black" | "pink") |
x @ ("red" | "blue") => {
}
_ => (),
}
}

fn bar() {
let x = "foo";
match x {
x @ ("foo" | "bar") |
(x @ "red" | (x @ "blue" | x @ "red")) => {
}
_ => (),
}
}

#[cfg(or3)]
fn zot() {
let x = "foo";
match x {
x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
//[or3]~^ ERROR mismatched types
x @ ("black" | "pink") |
x @ ("red" | "blue") => {
}
_ => (),
}
}


#[cfg(or4)]
fn hey() {
let x = "foo";
match x {
x @ ("foo" | "bar") |
(x @ "red" | (x @ "blue" | "red")) => {
//[or4]~^ variable `x` is not bound in all patterns
}
_ => (),
}
}

fn don() {
enum Foo {
A,
B,
C,
}

match Foo::A {
| _foo @ (Foo::A | Foo::B) => {}
Foo::C => {}
};
}

fn main(){}

0 comments on commit 56ba13a

Please sign in to comment.