about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-11-15 03:02:40 +0100
committerGitHub <noreply@github.com>2020-11-15 03:02:40 +0100
commita29b68f326acc8df3bdba3a0cce6f4eea11d82f8 (patch)
tree5e2ca41fa1c834d24505de89783a18b479436688
parentae7020fcb4254714d8dbe6246cc0a11fdf9c9de7 (diff)
parentb825ae7d28294de48297cb2e426f68c2331b3fdc (diff)
downloadrust-a29b68f326acc8df3bdba3a0cce6f4eea11d82f8.tar.gz
rust-a29b68f326acc8df3bdba3a0cce6f4eea11d82f8.zip
Rollup merge of #78856 - mark-i-m:fix-or-pat-ice, r=matthewjasper
Explicitly checking for or-pattern before test

Fixes https://github.com/rust-lang/rust/issues/72680

cc https://github.com/rust-lang/rust/issues/54883

r? ````@varkor````
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs11
-rw-r--r--src/test/ui/match/issue-72680.rs65
2 files changed, 76 insertions, 0 deletions
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 7bea8220ada..07173f41cd6 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -671,6 +671,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             (&TestKind::Range { .. }, _) => None,
 
             (&TestKind::Eq { .. } | &TestKind::Len { .. }, _) => {
+                // The call to `self.test(&match_pair)` below is not actually used to generate any
+                // MIR. Instead, we just want to compare with `test` (the parameter of the method)
+                // to see if it is the same.
+                //
+                // However, at this point we can still encounter or-patterns that were extracted
+                // from previous calls to `sort_candidate`, so we need to manually address that
+                // case to avoid panicking in `self.test()`.
+                if let PatKind::Or { .. } = &*match_pair.pattern.kind {
+                    return None;
+                }
+
                 // These are all binary tests.
                 //
                 // FIXME(#29623) we can be more clever here
diff --git a/src/test/ui/match/issue-72680.rs b/src/test/ui/match/issue-72680.rs
new file mode 100644
index 00000000000..5b933edc820
--- /dev/null
+++ b/src/test/ui/match/issue-72680.rs
@@ -0,0 +1,65 @@
+// run-pass
+
+#![feature(or_patterns)]
+
+fn main() {
+    assert!(f("", 0));
+    assert!(f("a", 1));
+    assert!(f("b", 1));
+
+    assert!(!f("", 1));
+    assert!(!f("a", 0));
+    assert!(!f("b", 0));
+
+    assert!(!f("asdf", 32));
+
+    ////
+
+    assert!(!g(true, true, true));
+    assert!(!g(false, true, true));
+    assert!(!g(true, false, true));
+    assert!(!g(false, false, true));
+    assert!(!g(true, true, false));
+
+    assert!(g(false, true, false));
+    assert!(g(true, false, false));
+    assert!(g(false, false, false));
+
+    ////
+
+    assert!(!h(true, true, true));
+    assert!(!h(false, true, true));
+    assert!(!h(true, false, true));
+    assert!(!h(false, false, true));
+    assert!(!h(true, true, false));
+
+    assert!(h(false, true, false));
+    assert!(h(true, false, false));
+    assert!(h(false, false, false));
+}
+
+fn f(s: &str, num: usize) -> bool {
+    match (s, num) {
+        ("", 0) | ("a" | "b", 1) => true,
+
+        _ => false,
+    }
+}
+
+fn g(x: bool, y: bool, z: bool) -> bool {
+    match (x, y, x, z) {
+        (true | false, false, true, false) => true,
+        (false, true | false, true | false, false) => true,
+        (true | false, true | false, true | false, true) => false,
+        (true, true | false, true | false, false) => false,
+    }
+}
+
+fn h(x: bool, y: bool, z: bool) -> bool {
+    match (x, (y, (x, (z,)))) {
+        (true | false, (false, (true, (false,)))) => true,
+        (false, (true | false, (true | false, (false,)))) => true,
+        (true | false, (true | false, (true | false, (true,)))) => false,
+        (true, (true | false, (true | false, (false,)))) => false,
+    }
+}