about summary refs log tree commit diff
path: root/src/test/ui/pattern/usefulness
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-09-29 00:16:17 +0000
committerbors <bors@rust-lang.org>2021-09-29 00:16:17 +0000
commit6df1d82869d06b88ff413e63a1e8efbb311e3b5c (patch)
tree22d0ccf49286fc65743e82737db0f731b8f504af /src/test/ui/pattern/usefulness
parent8f8092cc32ec171becef8ceacec7dbb06c5d7d7e (diff)
parentb7e358ee17a5794603b2324858de078c4586acfc (diff)
downloadrust-6df1d82869d06b88ff413e63a1e8efbb311e3b5c.tar.gz
rust-6df1d82869d06b88ff413e63a1e8efbb311e3b5c.zip
Auto merge of #88950 - Nadrieril:deconstruct-pat, r=oli-obk
Add an intermediate representation to exhaustiveness checking

The exhaustiveness checking algorithm keeps deconstructing patterns into a `Constructor` and some `Fields`, but does so a bit all over the place. This PR introduces a new representation for patterns that already has that information, so we only compute it once at the start.
I find this makes code easier to follow. In particular `DeconstructedPat::specialize` is a lot simpler than what happened before, and more closely matches the description of the algorithm. I'm also hoping this could help for the project of librarifying exhaustiveness for rust_analyzer since it decouples the algorithm from `rustc_middle::Pat`.
Diffstat (limited to 'src/test/ui/pattern/usefulness')
-rw-r--r--src/test/ui/pattern/usefulness/const-private-fields.rs30
-rw-r--r--src/test/ui/pattern/usefulness/consts-opaque.stderr58
-rw-r--r--src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/issue-3601.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs6
-rw-r--r--src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr9
6 files changed, 95 insertions, 16 deletions
diff --git a/src/test/ui/pattern/usefulness/const-private-fields.rs b/src/test/ui/pattern/usefulness/const-private-fields.rs
new file mode 100644
index 00000000000..06c832ca46a
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/const-private-fields.rs
@@ -0,0 +1,30 @@
+// check-pass
+//
+// Check that we don't ignore private fields in usefulness checking
+#![deny(unreachable_patterns)]
+
+mod inner {
+    #[derive(PartialEq, Eq)]
+    pub struct PrivateField {
+        pub x: bool,
+        y: bool,
+    }
+
+    pub const FOO: PrivateField = PrivateField { x: true, y: true };
+    pub const BAR: PrivateField = PrivateField { x: true, y: false };
+}
+use inner::*;
+
+fn main() {
+    match FOO {
+        FOO => {}
+        BAR => {}
+        _ => {}
+    }
+
+    match FOO {
+        FOO => {}
+        PrivateField { x: true, .. } => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/consts-opaque.stderr b/src/test/ui/pattern/usefulness/consts-opaque.stderr
index 68451043cf5..05c009a6f3f 100644
--- a/src/test/ui/pattern/usefulness/consts-opaque.stderr
+++ b/src/test/ui/pattern/usefulness/consts-opaque.stderr
@@ -7,8 +7,11 @@ LL |         FOO => {}
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:32:9
    |
+LL |         FOO => {}
+   |         --- matches any value
+LL |
 LL |         _ => {} // should not be emitting unreachable warning
-   |         ^
+   |         ^ unreachable pattern
    |
 note: the lint level is defined here
   --> $DIR/consts-opaque.rs:6:9
@@ -25,8 +28,11 @@ LL |         FOO_REF => {}
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:39:9
    |
+LL |         FOO_REF => {}
+   |         ------- matches any value
+LL |
 LL |         Foo(_) => {} // should not be emitting unreachable warning
-   |         ^^^^^^
+   |         ^^^^^^ unreachable pattern
 
 warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
   --> $DIR/consts-opaque.rs:45:9
@@ -70,15 +76,18 @@ LL |         BAR => {}
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:63:9
    |
+LL |         BAR => {}
+   |         --- matches any value
+LL |
 LL |         Bar => {} // should not be emitting unreachable warning
-   |         ^^^
+   |         ^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:65:9
    |
-LL |         Bar => {} // should not be emitting unreachable warning
+LL |         BAR => {}
    |         --- matches any value
-LL |
+...
 LL |         _ => {}
    |         ^ unreachable pattern
 
@@ -97,14 +106,20 @@ LL |         BAR => {} // should not be emitting unreachable warning
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:72:9
    |
+LL |         BAR => {}
+   |         --- matches any value
+LL |
 LL |         BAR => {} // should not be emitting unreachable warning
-   |         ^^^
+   |         ^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:75:9
    |
+LL |         BAR => {}
+   |         --- matches any value
+...
 LL |         _ => {} // should not be emitting unreachable warning
-   |         ^
+   |         ^ unreachable pattern
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
   --> $DIR/consts-opaque.rs:80:9
@@ -115,14 +130,20 @@ LL |         BAZ => {}
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:82:9
    |
+LL |         BAZ => {}
+   |         --- matches any value
+LL |
 LL |         Baz::Baz1 => {} // should not be emitting unreachable warning
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:84:9
    |
+LL |         BAZ => {}
+   |         --- matches any value
+...
 LL |         _ => {}
-   |         ^
+   |         ^ unreachable pattern
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
   --> $DIR/consts-opaque.rs:90:9
@@ -133,8 +154,11 @@ LL |         BAZ => {}
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:92:9
    |
+LL |         BAZ => {}
+   |         --- matches any value
+LL |
 LL |         _ => {}
-   |         ^
+   |         ^ unreachable pattern
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
   --> $DIR/consts-opaque.rs:97:9
@@ -145,20 +169,28 @@ LL |         BAZ => {}
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:99:9
    |
+LL |         BAZ => {}
+   |         --- matches any value
+LL |
 LL |         Baz::Baz2 => {} // should not be emitting unreachable warning
-   |         ^^^^^^^^^
+   |         ^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:101:9
    |
+LL |         BAZ => {}
+   |         --- matches any value
+...
 LL |         _ => {} // should not be emitting unreachable warning
-   |         ^
+   |         ^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:127:9
    |
+LL |         Wrap(_) => {}
+   |         ------- matches any value
 LL |         WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
-   |         ^^^^^^^^
+   |         ^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:141:9
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr
index 9a02fac6a75..0ffb0ffd82a 100644
--- a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr
+++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr
@@ -133,8 +133,10 @@ LL |         5..15 => {},
 error: unreachable pattern
   --> $DIR/reachability.rs:83:9
    |
+LL |         _ => {},
+   |         - matches any value
 LL |         '\u{D7FF}'..='\u{E000}' => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
   --> $DIR/reachability.rs:104:9
diff --git a/src/test/ui/pattern/usefulness/issue-3601.stderr b/src/test/ui/pattern/usefulness/issue-3601.stderr
index c873c20cca8..48ed1491508 100644
--- a/src/test/ui/pattern/usefulness/issue-3601.stderr
+++ b/src/test/ui/pattern/usefulness/issue-3601.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `Box(_, _)` not covered
+error[E0004]: non-exhaustive patterns: `box _` not covered
   --> $DIR/issue-3601.rs:30:44
    |
 LL |         box NodeKind::Element(ed) => match ed.kind {
-   |                                            ^^^^^^^ pattern `Box(_, _)` not covered
+   |                                            ^^^^^^^ pattern `box _` 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 `Box<ElementKind>`
diff --git a/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs
new file mode 100644
index 00000000000..c1bfcc73402
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs
@@ -0,0 +1,6 @@
+// This used to ICE in exhaustiveness checking. Explanation here:
+// https://github.com/rust-lang/rust/issues/82772#issuecomment-905946768
+fn main() {
+    let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of
+    let Box { .. }: Box<()>;
+}
diff --git a/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr
new file mode 100644
index 00000000000..2c8c85bb1e0
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr
@@ -0,0 +1,9 @@
+error[E0451]: field `1` of struct `Box` is private
+  --> $DIR/issue-82772-match-box-as-struct.rs:4:15
+   |
+LL |     let Box { 1: _, .. }: Box<()>;
+   |               ^^^^ private field
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0451`.