about summary refs log tree commit diff
diff options
context:
space:
mode:
authorouz-a <oguz.agcayazi@gmail.com>2022-06-17 16:34:00 +0300
committerouz-a <oguz.agcayazi@gmail.com>2022-06-17 21:38:26 +0300
commit90abfe9ce27c81808e3f74861072df6734f6a45d (patch)
tree61cfcf41bca34020e47d0c1280609bdd3eb7c1d3
parent3a8b0144c82197a70e919ad371d56f82c2282833 (diff)
downloadrust-90abfe9ce27c81808e3f74861072df6734f6a45d.tar.gz
rust-90abfe9ce27c81808e3f74861072df6734f6a45d.zip
expand inner `or` pattern
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs12
-rw-r--r--src/test/ui/or-patterns/inner-or-pat-2.rs13
-rw-r--r--src/test/ui/or-patterns/inner-or-pat-2.stderr11
-rw-r--r--src/test/ui/or-patterns/inner-or-pat-3.rs15
-rw-r--r--src/test/ui/or-patterns/inner-or-pat-4.rs13
-rw-r--r--src/test/ui/or-patterns/inner-or-pat-4.stderr11
-rw-r--r--src/test/ui/or-patterns/inner-or-pat.rs14
7 files changed, 88 insertions, 1 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 9e7a267ecbd..5bb2f00d3cf 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -453,7 +453,17 @@ 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());
+            let pats = row.expand_or_pat();
+            let mut no_inner_or = true;
+            for pat in pats {
+                if !pat.is_empty() && pat.head().is_or_pat() {
+                    self.patterns.extend(pat.expand_or_pat());
+                    no_inner_or = false;
+                }
+            }
+            if no_inner_or {
+                self.patterns.extend(row.expand_or_pat());
+            }
         } else {
             self.patterns.push(row);
         }
diff --git a/src/test/ui/or-patterns/inner-or-pat-2.rs b/src/test/ui/or-patterns/inner-or-pat-2.rs
new file mode 100644
index 00000000000..3053d973453
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat-2.rs
@@ -0,0 +1,13 @@
+#[allow(unused_variables)]
+#[allow(unused_parens)]
+fn main() {
+    let x = "foo";
+    match x {
+        x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
+        //~^ ERROR mismatched types
+        x @ ("black" | "pink") |
+        x @ ("red" | "blue") => {
+        }
+        _ => (),
+    }
+}
diff --git a/src/test/ui/or-patterns/inner-or-pat-2.stderr b/src/test/ui/or-patterns/inner-or-pat-2.stderr
new file mode 100644
index 00000000000..505b6c64a22
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat-2.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/inner-or-pat-2.rs:6: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`.
diff --git a/src/test/ui/or-patterns/inner-or-pat-3.rs b/src/test/ui/or-patterns/inner-or-pat-3.rs
new file mode 100644
index 00000000000..f6fe8a4dd59
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat-3.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#[allow(unreachable_patterns)]
+#[allow(unused_variables)]
+#[allow(unused_parens)]
+fn main() {
+    let x = "foo";
+
+    match x {
+        x @ ("foo" | "bar") |
+        (x @ "red" | (x @ "blue" | x @ "red")) => {
+        }
+        _ => (),
+    }
+}
diff --git a/src/test/ui/or-patterns/inner-or-pat-4.rs b/src/test/ui/or-patterns/inner-or-pat-4.rs
new file mode 100644
index 00000000000..fe771e2e930
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat-4.rs
@@ -0,0 +1,13 @@
+#[allow(unused_variables)]
+#[allow(unused_parens)]
+fn main() {
+    let x = "foo";
+
+    match x {
+        x @ ("foo" | "bar") |
+        (x @ "red" | (x @ "blue" |  "red")) => {
+        //~^ variable `x` is not bound in all patterns
+        }
+        _ => (),
+    }
+}
diff --git a/src/test/ui/or-patterns/inner-or-pat-4.stderr b/src/test/ui/or-patterns/inner-or-pat-4.stderr
new file mode 100644
index 00000000000..177c7f98312
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat-4.stderr
@@ -0,0 +1,11 @@
+error[E0408]: variable `x` is not bound in all patterns
+  --> $DIR/inner-or-pat-4.rs:8: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`.
diff --git a/src/test/ui/or-patterns/inner-or-pat.rs b/src/test/ui/or-patterns/inner-or-pat.rs
new file mode 100644
index 00000000000..c49b04aa65b
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+#[allow(unused_variables)]
+#[allow(unused_parens)]
+fn main() {
+    let x = "foo";
+    match x {
+        x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) |
+        x @ ("black" | "pink") |
+        x @ ("red" | "blue") => {
+        }
+        _ => (),
+    }
+}