about summary refs log tree commit diff
diff options
context:
space:
mode:
authormark <markm@cs.wisc.edu>2020-11-07 15:22:52 -0600
committermark <markm@cs.wisc.edu>2020-11-07 23:22:47 -0600
commit459dae94a1c5ea658e78dbe99d88108d9cacc51d (patch)
treecfd68c0de18cd4f398740ea282796adc4d5931ef
parentb2d115f6db5172c961dfeb50de15f35784dbc7c9 (diff)
downloadrust-459dae94a1c5ea658e78dbe99d88108d9cacc51d.tar.gz
rust-459dae94a1c5ea658e78dbe99d88108d9cacc51d.zip
fix #72680 by explicitly checking for or-pattern before test
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs10
-rw-r--r--src/test/ui/match/issue-72680.rs65
2 files changed, 75 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..e4bc4c07432 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -671,6 +671,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             (&TestKind::Range { .. }, _) => None,
 
             (&TestKind::Eq { .. } | &TestKind::Len { .. }, _) => {
+                // We do call `test()` below to see what kind of test `match_pair` would require.
+                // If it is the same test as `test`, then we can just use `test`.
+                //
+                // However, `test()` assumes that there won't be any or-patterns, so we need to
+                // specially handle that here and return `None` (since the `test` clearly doesn't
+                // apply to an or-pattern).
+                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..3e8febb63ad
--- /dev/null
+++ b/src/test/ui/match/issue-72680.rs
@@ -0,0 +1,65 @@
+// run-pass
+
+#![feature(or_patterns)]
+
+fn main() {
+    assert_eq!(f("", 0), true);
+    assert_eq!(f("a", 1), true);
+    assert_eq!(f("b", 1), true);
+
+    assert_eq!(f("", 1), false);
+    assert_eq!(f("a", 0), false);
+    assert_eq!(f("b", 0), false);
+
+    assert_eq!(f("asdf", 032), false);
+
+    ////
+
+    assert_eq!(g(true, true, true), false);
+    assert_eq!(g(false, true, true), false);
+    assert_eq!(g(true, false, true), false);
+    assert_eq!(g(false, false, true), false);
+    assert_eq!(g(true, true, false), false);
+
+    assert_eq!(g(false, true, false), true);
+    assert_eq!(g(true, false, false), true);
+    assert_eq!(g(false, false, false), true);
+
+    ////
+
+    assert_eq!(h(true, true, true), false);
+    assert_eq!(h(false, true, true), false);
+    assert_eq!(h(true, false, true), false);
+    assert_eq!(h(false, false, true), false);
+    assert_eq!(h(true, true, false), false);
+
+    assert_eq!(h(false, true, false), true);
+    assert_eq!(h(true, false, false), true);
+    assert_eq!(h(false, false, false), true);
+}
+
+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,
+    }
+}