about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-12-19 19:14:04 +0000
committerbors <bors@rust-lang.org>2020-12-19 19:14:04 +0000
commit1f5bc176b0e54a8e464704adcd7e571700207fe9 (patch)
tree702ff2b7019b8ed901de779f1125419b4693343e /src/test
parent1b6b06a03a00a7c9f156bff130b72e90b79e1127 (diff)
parentcefcadbe9278cf30175e93309cdd5f1da6714869 (diff)
Auto merge of #80104 - Nadrieril:usefulness-merging, r=varkor
Improve and fix diagnostics of exhaustiveness checking

Primarily, this fixes https://github.com/rust-lang/rust/issues/56379. This also fixes incorrect interactions between or-patterns and slice patterns that I discovered while working on #56379. Those two examples show the incorrect diagnostics:

```rust
match &[][..] {
    [true] => {}
    [true // detected as unreachable but that's not true
        | false, ..] => {}
    _ => {}
}
match (true, None) {
    (true, Some(_)) => {}
    (false, Some(true)) => {}
    (true | false, None | Some(true // should be detected as unreachable
                               | false)) => {}
}
```

I did not measure any perf impact. However, I suspect that [`616ba9f`](https://github.com/rust-lang/rust/pull/80104/commits/616ba9f9f7f5845777a36e1a41a515e6c33a8776) should have a negative impact on large or-patterns. I'll see what the perf run says; I have optimization ideas up my sleeve if needed.

EDIT: I initially had a noticeable perf impact that I thought unavoidable. I then proceeded to avoid it x)

r? `@varkor`
`@rustbot` label +A-exhaustiveness-checking
Diffstat (limited to 'src/test')
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs29
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr22
-rw-r--r--src/test/ui/pattern/usefulness/issue-15129.rs8
-rw-r--r--src/test/ui/pattern/usefulness/issue-15129.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/issue-2111.rs13
-rw-r--r--src/test/ui/pattern/usefulness/issue-2111.stderr8
-rw-r--r--src/test/ui/pattern/usefulness/issue-56379.rs14
-rw-r--r--src/test/ui/pattern/usefulness/issue-56379.stderr22
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.rs2
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.stderr4
10 files changed, 101 insertions, 25 deletions
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
index 512f1e283cb..184ffa85c40 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
@@ -64,6 +64,35 @@ fn main() {
             | 2, ..] => {}
         _ => {}
     }
+    match &[][..] {
+        [true] => {}
+        [true | false, ..] => {}
+        _ => {}
+    }
+    match &[][..] {
+        [false] => {}
+        [true, ..] => {}
+        [true //~ ERROR unreachable
+            | false, ..] => {}
+        _ => {}
+    }
+    match (true, None) {
+        (true, Some(_)) => {}
+        (false, Some(true)) => {}
+        (true | false, None | Some(true //~ ERROR unreachable
+                                   | false)) => {}
+    }
+    macro_rules! t_or_f {
+        () => {
+            (true // FIXME: should be unreachable
+                        | false)
+        };
+    }
+    match (true, None) {
+        (true, Some(_)) => {}
+        (false, Some(true)) => {}
+        (true | false, None | Some(t_or_f!())) => {}
+    }
     match Some(0) {
         Some(0) => {}
         Some(0 //~ ERROR unreachable
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
index e968310d108..8b1003b5514 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
@@ -95,28 +95,40 @@ LL |         [1
    |          ^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:69:14
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:75:10
+   |
+LL |         [true
+   |          ^^^^
+
+error: unreachable pattern
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:82:36
+   |
+LL |         (true | false, None | Some(true
+   |                                    ^^^^
+
+error: unreachable pattern
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:98:14
    |
 LL |         Some(0
    |              ^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:88:19
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:117:19
    |
 LL |                 | false) => {}
    |                   ^^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:96:15
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:125:15
    |
 LL |             | true) => {}
    |               ^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:102:15
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:131:15
    |
 LL |             | true,
    |               ^^^^
 
-error: aborting due to 19 previous errors
+error: aborting due to 21 previous errors
 
diff --git a/src/test/ui/pattern/usefulness/issue-15129.rs b/src/test/ui/pattern/usefulness/issue-15129.rs
index ed134c175ed..d2b72a86b74 100644
--- a/src/test/ui/pattern/usefulness/issue-15129.rs
+++ b/src/test/ui/pattern/usefulness/issue-15129.rs
@@ -1,17 +1,17 @@
 pub enum T {
     T1(()),
-    T2(())
+    T2(()),
 }
 
 pub enum V {
     V1(isize),
-    V2(bool)
+    V2(bool),
 }
 
 fn main() {
     match (T::T1(()), V::V2(true)) {
-    //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` not covered
+        //~^ ERROR non-exhaustive patterns: `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered
         (T::T1(()), V::V1(i)) => (),
-        (T::T2(()), V::V2(b)) => ()
+        (T::T2(()), V::V2(b)) => (),
     }
 }
diff --git a/src/test/ui/pattern/usefulness/issue-15129.stderr b/src/test/ui/pattern/usefulness/issue-15129.stderr
index aa4434e72b5..79a77240937 100644
--- a/src/test/ui/pattern/usefulness/issue-15129.stderr
+++ b/src/test/ui/pattern/usefulness/issue-15129.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` not covered
+error[E0004]: non-exhaustive patterns: `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered
   --> $DIR/issue-15129.rs:12:11
    |
 LL |     match (T::T1(()), V::V2(true)) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `(T1(()), V2(_))` not covered
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T1(()), V2(_))` and `(T2(()), V1(_))` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(T, V)`
diff --git a/src/test/ui/pattern/usefulness/issue-2111.rs b/src/test/ui/pattern/usefulness/issue-2111.rs
index 7e5835e8697..d27beaeffd6 100644
--- a/src/test/ui/pattern/usefulness/issue-2111.rs
+++ b/src/test/ui/pattern/usefulness/issue-2111.rs
@@ -1,12 +1,11 @@
 fn foo(a: Option<usize>, b: Option<usize>) {
-  match (a,b) {
-  //~^ ERROR: non-exhaustive patterns: `(None, None)` not covered
-    (Some(a), Some(b)) if a == b => { }
-    (Some(_), None) |
-    (None, Some(_)) => { }
-  }
+    match (a, b) {
+        //~^ ERROR: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered
+        (Some(a), Some(b)) if a == b => {}
+        (Some(_), None) | (None, Some(_)) => {}
+    }
 }
 
 fn main() {
-  foo(None, None);
+    foo(None, None);
 }
diff --git a/src/test/ui/pattern/usefulness/issue-2111.stderr b/src/test/ui/pattern/usefulness/issue-2111.stderr
index a39a479e078..60d9b8514b7 100644
--- a/src/test/ui/pattern/usefulness/issue-2111.stderr
+++ b/src/test/ui/pattern/usefulness/issue-2111.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `(None, None)` not covered
-  --> $DIR/issue-2111.rs:2:9
+error[E0004]: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered
+  --> $DIR/issue-2111.rs:2:11
    |
-LL |   match (a,b) {
-   |         ^^^^^ pattern `(None, None)` not covered
+LL |     match (a, b) {
+   |           ^^^^^^ patterns `(None, None)` and `(Some(_), Some(_))` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(Option<usize>, Option<usize>)`
diff --git a/src/test/ui/pattern/usefulness/issue-56379.rs b/src/test/ui/pattern/usefulness/issue-56379.rs
new file mode 100644
index 00000000000..9bccccca9c2
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-56379.rs
@@ -0,0 +1,14 @@
+enum Foo {
+    A(bool),
+    B(bool),
+    C(bool),
+}
+
+fn main() {
+    match Foo::A(true) {
+        //~^ ERROR non-exhaustive patterns: `A(false)`, `B(false)` and `C(false)` not covered
+        Foo::A(true) => {}
+        Foo::B(true) => {}
+        Foo::C(true) => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-56379.stderr b/src/test/ui/pattern/usefulness/issue-56379.stderr
new file mode 100644
index 00000000000..6a231b868c8
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-56379.stderr
@@ -0,0 +1,22 @@
+error[E0004]: non-exhaustive patterns: `A(false)`, `B(false)` and `C(false)` not covered
+  --> $DIR/issue-56379.rs:8:11
+   |
+LL | / enum Foo {
+LL | |     A(bool),
+   | |     - not covered
+LL | |     B(bool),
+   | |     - not covered
+LL | |     C(bool),
+   | |     - not covered
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match Foo::A(true) {
+   |             ^^^^^^^^^^^^ patterns `A(false)`, `B(false)` and `C(false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
index a28cfb579f4..4ff12aa2ff5 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
@@ -15,7 +15,7 @@ fn main() {
                       //  and `(_, _, 5_i32..=i32::MAX)` not covered
       (_, _, 4) => {}
     }
-    match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` not covered
+    match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` and `(B, B)` not covered
       (T::A, T::B) => {}
       (T::B, T::A) => {}
     }
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
index 12412743b83..c953cd31440 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -45,11 +45,11 @@ LL |     match (2, 3, 4) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(i32, i32, i32)`
 
-error[E0004]: non-exhaustive patterns: `(A, A)` not covered
+error[E0004]: non-exhaustive patterns: `(A, A)` and `(B, B)` not covered
   --> $DIR/non-exhaustive-match.rs:18:11
    |
 LL |     match (T::A, T::A) {
-   |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
+   |           ^^^^^^^^^^^^ patterns `(A, A)` and `(B, B)` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(T, T)`