Skip to content

Commit 6df1d82

Browse files
committed
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`.
2 parents 8f8092c + b7e358e commit 6df1d82

File tree

10 files changed

+893
-994
lines changed

10 files changed

+893
-994
lines changed

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+89-119
Large diffs are not rendered by default.

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+598-366
Large diffs are not rendered by default.

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+107-492
Large diffs are not rendered by default.

src/test/ui/consts/const_in_pattern/issue-78057.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ LL | FOO => {},
77
error: unreachable pattern
88
--> $DIR/issue-78057.rs:14:9
99
|
10+
LL | FOO => {},
11+
| --- matches any value
12+
LL |
1013
LL | _ => {}
11-
| ^
14+
| ^ unreachable pattern
1215
|
1316
note: the lint level is defined here
1417
--> $DIR/issue-78057.rs:1:9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// check-pass
2+
//
3+
// Check that we don't ignore private fields in usefulness checking
4+
#![deny(unreachable_patterns)]
5+
6+
mod inner {
7+
#[derive(PartialEq, Eq)]
8+
pub struct PrivateField {
9+
pub x: bool,
10+
y: bool,
11+
}
12+
13+
pub const FOO: PrivateField = PrivateField { x: true, y: true };
14+
pub const BAR: PrivateField = PrivateField { x: true, y: false };
15+
}
16+
use inner::*;
17+
18+
fn main() {
19+
match FOO {
20+
FOO => {}
21+
BAR => {}
22+
_ => {}
23+
}
24+
25+
match FOO {
26+
FOO => {}
27+
PrivateField { x: true, .. } => {}
28+
_ => {}
29+
}
30+
}

src/test/ui/pattern/usefulness/consts-opaque.stderr

+45-13
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ LL | FOO => {}
77
error: unreachable pattern
88
--> $DIR/consts-opaque.rs:32:9
99
|
10+
LL | FOO => {}
11+
| --- matches any value
12+
LL |
1013
LL | _ => {} // should not be emitting unreachable warning
11-
| ^
14+
| ^ unreachable pattern
1215
|
1316
note: the lint level is defined here
1417
--> $DIR/consts-opaque.rs:6:9
@@ -25,8 +28,11 @@ LL | FOO_REF => {}
2528
error: unreachable pattern
2629
--> $DIR/consts-opaque.rs:39:9
2730
|
31+
LL | FOO_REF => {}
32+
| ------- matches any value
33+
LL |
2834
LL | Foo(_) => {} // should not be emitting unreachable warning
29-
| ^^^^^^
35+
| ^^^^^^ unreachable pattern
3036

3137
warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
3238
--> $DIR/consts-opaque.rs:45:9
@@ -70,15 +76,18 @@ LL | BAR => {}
7076
error: unreachable pattern
7177
--> $DIR/consts-opaque.rs:63:9
7278
|
79+
LL | BAR => {}
80+
| --- matches any value
81+
LL |
7382
LL | Bar => {} // should not be emitting unreachable warning
74-
| ^^^
83+
| ^^^ unreachable pattern
7584

7685
error: unreachable pattern
7786
--> $DIR/consts-opaque.rs:65:9
7887
|
79-
LL | Bar => {} // should not be emitting unreachable warning
88+
LL | BAR => {}
8089
| --- matches any value
81-
LL |
90+
...
8291
LL | _ => {}
8392
| ^ unreachable pattern
8493

@@ -97,14 +106,20 @@ LL | BAR => {} // should not be emitting unreachable warning
97106
error: unreachable pattern
98107
--> $DIR/consts-opaque.rs:72:9
99108
|
109+
LL | BAR => {}
110+
| --- matches any value
111+
LL |
100112
LL | BAR => {} // should not be emitting unreachable warning
101-
| ^^^
113+
| ^^^ unreachable pattern
102114

103115
error: unreachable pattern
104116
--> $DIR/consts-opaque.rs:75:9
105117
|
118+
LL | BAR => {}
119+
| --- matches any value
120+
...
106121
LL | _ => {} // should not be emitting unreachable warning
107-
| ^
122+
| ^ unreachable pattern
108123

109124
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
110125
--> $DIR/consts-opaque.rs:80:9
@@ -115,14 +130,20 @@ LL | BAZ => {}
115130
error: unreachable pattern
116131
--> $DIR/consts-opaque.rs:82:9
117132
|
133+
LL | BAZ => {}
134+
| --- matches any value
135+
LL |
118136
LL | Baz::Baz1 => {} // should not be emitting unreachable warning
119-
| ^^^^^^^^^
137+
| ^^^^^^^^^ unreachable pattern
120138

121139
error: unreachable pattern
122140
--> $DIR/consts-opaque.rs:84:9
123141
|
142+
LL | BAZ => {}
143+
| --- matches any value
144+
...
124145
LL | _ => {}
125-
| ^
146+
| ^ unreachable pattern
126147

127148
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
128149
--> $DIR/consts-opaque.rs:90:9
@@ -133,8 +154,11 @@ LL | BAZ => {}
133154
error: unreachable pattern
134155
--> $DIR/consts-opaque.rs:92:9
135156
|
157+
LL | BAZ => {}
158+
| --- matches any value
159+
LL |
136160
LL | _ => {}
137-
| ^
161+
| ^ unreachable pattern
138162

139163
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
140164
--> $DIR/consts-opaque.rs:97:9
@@ -145,20 +169,28 @@ LL | BAZ => {}
145169
error: unreachable pattern
146170
--> $DIR/consts-opaque.rs:99:9
147171
|
172+
LL | BAZ => {}
173+
| --- matches any value
174+
LL |
148175
LL | Baz::Baz2 => {} // should not be emitting unreachable warning
149-
| ^^^^^^^^^
176+
| ^^^^^^^^^ unreachable pattern
150177

151178
error: unreachable pattern
152179
--> $DIR/consts-opaque.rs:101:9
153180
|
181+
LL | BAZ => {}
182+
| --- matches any value
183+
...
154184
LL | _ => {} // should not be emitting unreachable warning
155-
| ^
185+
| ^ unreachable pattern
156186

157187
error: unreachable pattern
158188
--> $DIR/consts-opaque.rs:127:9
159189
|
190+
LL | Wrap(_) => {}
191+
| ------- matches any value
160192
LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
161-
| ^^^^^^^^
193+
| ^^^^^^^^ unreachable pattern
162194

163195
error: unreachable pattern
164196
--> $DIR/consts-opaque.rs:141:9

src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,10 @@ LL | 5..15 => {},
133133
error: unreachable pattern
134134
--> $DIR/reachability.rs:83:9
135135
|
136+
LL | _ => {},
137+
| - matches any value
136138
LL | '\u{D7FF}'..='\u{E000}' => {},
137-
| ^^^^^^^^^^^^^^^^^^^^^^^
139+
| ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
138140

139141
error: unreachable pattern
140142
--> $DIR/reachability.rs:104:9

src/test/ui/pattern/usefulness/issue-3601.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0004]: non-exhaustive patterns: `Box(_, _)` not covered
1+
error[E0004]: non-exhaustive patterns: `box _` not covered
22
--> $DIR/issue-3601.rs:30:44
33
|
44
LL | box NodeKind::Element(ed) => match ed.kind {
5-
| ^^^^^^^ pattern `Box(_, _)` not covered
5+
| ^^^^^^^ pattern `box _` not covered
66
|
77
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
88
= note: the matched value is of type `Box<ElementKind>`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// This used to ICE in exhaustiveness checking. Explanation here:
2+
// https://github.com/rust-lang/rust/issues/82772#issuecomment-905946768
3+
fn main() {
4+
let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of
5+
let Box { .. }: Box<()>;
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0451]: field `1` of struct `Box` is private
2+
--> $DIR/issue-82772-match-box-as-struct.rs:4:15
3+
|
4+
LL | let Box { 1: _, .. }: Box<()>;
5+
| ^^^^ private field
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0451`.

0 commit comments

Comments
 (0)