Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 969b42d

Browse files
committedDec 22, 2020
Auto merge of #80242 - Nadrieril:explain-and-factor-splitting, r=varkor
Clarify constructor splitting in exhaustiveness checking I reworked the explanation of the algorithm completely to make it properly account for the various extensions we've added. This includes constructor splitting, which was previously not clearly included in the algorithm. This makes wildcards less magical; I added some detailed examples; and this distinguishes clearly between constructors that only make sense in patterns (like ranges) and those that make sense for values (like `Some`). This reformulation had been floating around in my mind for a while, and I'm quite happy with how it turned out. Let me know how you feel about it. I also factored out all three cases of splitting (wildcards, ranges and slices) into dedicated structs to encapsulate the complicated bits. I measured no perf impact but I don't trust my local measurements for refactors since #79284. r? `@varkor` `@rustbot` modify labels: +A-exhaustiveness-checking
2 parents bb1fbbf + be23694 commit 969b42d

File tree

4 files changed

+895
-787
lines changed

4 files changed

+895
-787
lines changed
 

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

Lines changed: 573 additions & 507 deletions
Large diffs are not rendered by default.

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

Lines changed: 251 additions & 252 deletions
Large diffs are not rendered by default.

‎src/test/ui/pattern/usefulness/consts-opaque.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ enum Baz {
2525
impl Eq for Baz {}
2626
const BAZ: Baz = Baz::Baz1;
2727

28-
type Quux = fn(usize, usize) -> usize;
29-
fn quux(a: usize, b: usize) -> usize { a + b }
30-
const QUUX: Quux = quux;
31-
3228
fn main() {
3329
match FOO {
3430
FOO => {}
@@ -106,9 +102,44 @@ fn main() {
106102
//~^ ERROR unreachable pattern
107103
}
108104

105+
type Quux = fn(usize, usize) -> usize;
106+
fn quux(a: usize, b: usize) -> usize { a + b }
107+
const QUUX: Quux = quux;
108+
109109
match QUUX {
110110
QUUX => {}
111111
QUUX => {}
112112
_ => {}
113113
}
114+
115+
#[derive(PartialEq, Eq)]
116+
struct Wrap<T>(T);
117+
const WRAPQUUX: Wrap<Quux> = Wrap(quux);
118+
119+
match WRAPQUUX {
120+
WRAPQUUX => {}
121+
WRAPQUUX => {}
122+
Wrap(_) => {}
123+
}
124+
125+
match WRAPQUUX {
126+
Wrap(_) => {}
127+
WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
128+
//~^ ERROR unreachable pattern
129+
}
130+
131+
#[derive(PartialEq, Eq)]
132+
enum WhoKnows<T> {
133+
Yay(T),
134+
Nope,
135+
};
136+
const WHOKNOWSQUUX: WhoKnows<Quux> = WhoKnows::Yay(quux);
137+
138+
match WHOKNOWSQUUX {
139+
WHOKNOWSQUUX => {}
140+
WhoKnows::Yay(_) => {}
141+
WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
142+
//~^ ERROR unreachable pattern
143+
WhoKnows::Nope => {}
144+
}
114145
}
Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
2-
--> $DIR/consts-opaque.rs:34:9
2+
--> $DIR/consts-opaque.rs:30:9
33
|
44
LL | FOO => {}
55
| ^^^
66

77
error: unreachable pattern
8-
--> $DIR/consts-opaque.rs:36:9
8+
--> $DIR/consts-opaque.rs:32:9
99
|
1010
LL | _ => {} // should not be emitting unreachable warning
1111
| ^
@@ -17,19 +17,19 @@ LL | #![deny(unreachable_patterns)]
1717
| ^^^^^^^^^^^^^^^^^^^^
1818

1919
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
20-
--> $DIR/consts-opaque.rs:41:9
20+
--> $DIR/consts-opaque.rs:37:9
2121
|
2222
LL | FOO_REF => {}
2323
| ^^^^^^^
2424

2525
error: unreachable pattern
26-
--> $DIR/consts-opaque.rs:43:9
26+
--> $DIR/consts-opaque.rs:39:9
2727
|
2828
LL | Foo(_) => {} // should not be emitting unreachable warning
2929
| ^^^^^^
3030

3131
warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
32-
--> $DIR/consts-opaque.rs:49:9
32+
--> $DIR/consts-opaque.rs:45:9
3333
|
3434
LL | FOO_REF_REF => {}
3535
| ^^^^^^^^^^^
@@ -39,21 +39,21 @@ LL | FOO_REF_REF => {}
3939
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
4040

4141
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
42-
--> $DIR/consts-opaque.rs:57:9
42+
--> $DIR/consts-opaque.rs:53:9
4343
|
4444
LL | BAR => {} // should not be emitting unreachable warning
4545
| ^^^
4646

4747
error: unreachable pattern
48-
--> $DIR/consts-opaque.rs:57:9
48+
--> $DIR/consts-opaque.rs:53:9
4949
|
5050
LL | Bar => {}
5151
| --- matches any value
5252
LL | BAR => {} // should not be emitting unreachable warning
5353
| ^^^ unreachable pattern
5454

5555
error: unreachable pattern
56-
--> $DIR/consts-opaque.rs:60:9
56+
--> $DIR/consts-opaque.rs:56:9
5757
|
5858
LL | Bar => {}
5959
| --- matches any value
@@ -62,19 +62,19 @@ LL | _ => {}
6262
| ^ unreachable pattern
6363

6464
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
65-
--> $DIR/consts-opaque.rs:65:9
65+
--> $DIR/consts-opaque.rs:61:9
6666
|
6767
LL | BAR => {}
6868
| ^^^
6969

7070
error: unreachable pattern
71-
--> $DIR/consts-opaque.rs:67:9
71+
--> $DIR/consts-opaque.rs:63:9
7272
|
7373
LL | Bar => {} // should not be emitting unreachable warning
7474
| ^^^
7575

7676
error: unreachable pattern
77-
--> $DIR/consts-opaque.rs:69:9
77+
--> $DIR/consts-opaque.rs:65:9
7878
|
7979
LL | Bar => {} // should not be emitting unreachable warning
8080
| --- matches any value
@@ -83,76 +83,88 @@ LL | _ => {}
8383
| ^ unreachable pattern
8484

8585
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
86-
--> $DIR/consts-opaque.rs:74:9
86+
--> $DIR/consts-opaque.rs:70:9
8787
|
8888
LL | BAR => {}
8989
| ^^^
9090

9191
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
92-
--> $DIR/consts-opaque.rs:76:9
92+
--> $DIR/consts-opaque.rs:72:9
9393
|
9494
LL | BAR => {} // should not be emitting unreachable warning
9595
| ^^^
9696

9797
error: unreachable pattern
98-
--> $DIR/consts-opaque.rs:76:9
98+
--> $DIR/consts-opaque.rs:72:9
9999
|
100100
LL | BAR => {} // should not be emitting unreachable warning
101101
| ^^^
102102

103103
error: unreachable pattern
104-
--> $DIR/consts-opaque.rs:79:9
104+
--> $DIR/consts-opaque.rs:75:9
105105
|
106106
LL | _ => {} // should not be emitting unreachable warning
107107
| ^
108108

109109
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
110-
--> $DIR/consts-opaque.rs:84:9
110+
--> $DIR/consts-opaque.rs:80:9
111111
|
112112
LL | BAZ => {}
113113
| ^^^
114114

115115
error: unreachable pattern
116-
--> $DIR/consts-opaque.rs:86:9
116+
--> $DIR/consts-opaque.rs:82:9
117117
|
118118
LL | Baz::Baz1 => {} // should not be emitting unreachable warning
119119
| ^^^^^^^^^
120120

121121
error: unreachable pattern
122-
--> $DIR/consts-opaque.rs:88:9
122+
--> $DIR/consts-opaque.rs:84:9
123123
|
124124
LL | _ => {}
125125
| ^
126126

127127
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
128-
--> $DIR/consts-opaque.rs:94:9
128+
--> $DIR/consts-opaque.rs:90:9
129129
|
130130
LL | BAZ => {}
131131
| ^^^
132132

133133
error: unreachable pattern
134-
--> $DIR/consts-opaque.rs:96:9
134+
--> $DIR/consts-opaque.rs:92:9
135135
|
136136
LL | _ => {}
137137
| ^
138138

139139
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
140-
--> $DIR/consts-opaque.rs:101:9
140+
--> $DIR/consts-opaque.rs:97:9
141141
|
142142
LL | BAZ => {}
143143
| ^^^
144144

145145
error: unreachable pattern
146-
--> $DIR/consts-opaque.rs:103:9
146+
--> $DIR/consts-opaque.rs:99:9
147147
|
148148
LL | Baz::Baz2 => {} // should not be emitting unreachable warning
149149
| ^^^^^^^^^
150150

151151
error: unreachable pattern
152-
--> $DIR/consts-opaque.rs:105:9
152+
--> $DIR/consts-opaque.rs:101:9
153153
|
154154
LL | _ => {} // should not be emitting unreachable warning
155155
| ^
156156

157-
error: aborting due to 22 previous errors; 1 warning emitted
157+
error: unreachable pattern
158+
--> $DIR/consts-opaque.rs:127:9
159+
|
160+
LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
161+
| ^^^^^^^^
162+
163+
error: unreachable pattern
164+
--> $DIR/consts-opaque.rs:141:9
165+
|
166+
LL | WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
167+
| ^^^^^^^^^^^^
168+
169+
error: aborting due to 24 previous errors; 1 warning emitted
158170

0 commit comments

Comments
 (0)
Please sign in to comment.