Skip to content

Commit

Permalink
Auto merge of #88950 - Nadrieril:deconstruct-pat, r=oli-obk
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
bors committed Sep 29, 2021
2 parents 8f8092c + b7e358e commit 6df1d82
Show file tree
Hide file tree
Showing 10 changed files with 893 additions and 994 deletions.
208 changes: 89 additions & 119 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Large diffs are not rendered by default.

964 changes: 598 additions & 366 deletions compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

Large diffs are not rendered by default.

599 changes: 107 additions & 492 deletions compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion src/test/ui/consts/const_in_pattern/issue-78057.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ LL | FOO => {},
error: unreachable pattern
--> $DIR/issue-78057.rs:14:9
|
LL | FOO => {},
| --- matches any value
LL |
LL | _ => {}
| ^
| ^ unreachable pattern
|
note: the lint level is defined here
--> $DIR/issue-78057.rs:1:9
Expand Down
30 changes: 30 additions & 0 deletions src/test/ui/pattern/usefulness/const-private-fields.rs
Original file line number Diff line number Diff line change
@@ -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, .. } => {}
_ => {}
}
}
58 changes: 45 additions & 13 deletions src/test/ui/pattern/usefulness/consts-opaque.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/pattern/usefulness/issue-3601.stderr
Original file line number Diff line number Diff line change
@@ -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>`
Expand Down
Original file line number Diff line number Diff line change
@@ -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<()>;
}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 6df1d82

Please sign in to comment.