mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 07:03:45 +00:00
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_
This commit is contained in:
commit
56ba13ac7f
@ -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]`
|
/// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
|
||||||
/// works well.
|
/// works well.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct PatStack<'p, 'tcx> {
|
pub(crate) struct PatStack<'p, 'tcx> {
|
||||||
pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
|
pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p, 'tcx> PatStack<'p, 'tcx> {
|
impl<'p, 'tcx> PatStack<'p, 'tcx> {
|
||||||
@ -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.
|
/// 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
|
/// 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> {
|
|||||||
/// A 2D matrix.
|
/// A 2D matrix.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(super) struct Matrix<'p, 'tcx> {
|
pub(super) struct Matrix<'p, 'tcx> {
|
||||||
patterns: Vec<PatStack<'p, 'tcx>>,
|
pub patterns: Vec<PatStack<'p, 'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p, 'tcx> Matrix<'p, 'tcx> {
|
impl<'p, 'tcx> Matrix<'p, 'tcx> {
|
||||||
@ -453,7 +468,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
|
|||||||
/// expands it.
|
/// expands it.
|
||||||
fn push(&mut self, row: PatStack<'p, 'tcx>) {
|
fn push(&mut self, row: PatStack<'p, 'tcx>) {
|
||||||
if !row.is_empty() && row.head().is_or_pat() {
|
if !row.is_empty() && row.head().is_or_pat() {
|
||||||
self.patterns.extend(row.expand_or_pat());
|
row.expand_and_extend(self);
|
||||||
} else {
|
} else {
|
||||||
self.patterns.push(row);
|
self.patterns.push(row);
|
||||||
}
|
}
|
||||||
|
11
src/test/ui/or-patterns/inner-or-pat.or3.stderr
Normal file
11
src/test/ui/or-patterns/inner-or-pat.or3.stderr
Normal file
@ -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
src/test/ui/or-patterns/inner-or-pat.or4.stderr
Normal file
11
src/test/ui/or-patterns/inner-or-pat.or4.stderr
Normal file
@ -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
src/test/ui/or-patterns/inner-or-pat.rs
Normal file
73
src/test/ui/or-patterns/inner-or-pat.rs
Normal file
@ -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(){}
|
Loading…
Reference in New Issue
Block a user