Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 14c4d2f

Browse files
committedNov 5, 2023
Auto merge of rust-lang#117611 - Nadrieril:linear-pass-take-4, r=<try>
Rewrite exhaustiveness in one pass This is at least my 4th attempt at this in as many years x) Previous attempts were all too complicated or too slow. But we're finally here! The previous version of the exhaustiveness algorithm computed reachability for each arm then exhaustiveness of the whole match. Since each of these steps does roughly the same things, this rewrites the algorithm to do them all in one go. I also think this makes things much simpler. I also rewrote the documentation of the algorithm in depth. Hopefully it's up-to-date and easier to follow now. Plz comment if anything's unclear. r? `@oli-obk` I think you're one of the rare other people to understand the exhaustiveness algorithm? cc `@varkor` I know you're not active anymore, but if you feel like having a look you might enjoy this :D
2 parents 04817ff + ab918af commit 14c4d2f

18 files changed

+1230
-1001
lines changed
 

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
279279
} else {
280280
// Check the pattern for some things unrelated to exhaustiveness.
281281
let refutable = if cx.refutable { Refutable } else { Irrefutable };
282-
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
283-
pat.walk_always(|pat| check_for_bindings_named_same_as_variants(self, pat, refutable));
282+
pat.walk_always(|pat| {
283+
check_borrow_conflicts_in_at_patterns(self, pat);
284+
check_for_bindings_named_same_as_variants(self, pat, refutable);
285+
});
284286
Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat)))
285287
}
286288
}
@@ -289,6 +291,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
289291
&self,
290292
refutability: RefutableFlag,
291293
match_span: Option<Span>,
294+
scrut_span: Span,
292295
) -> MatchCheckCtxt<'p, 'tcx> {
293296
let refutable = match refutability {
294297
Irrefutable => false,
@@ -299,7 +302,9 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
299302
param_env: self.param_env,
300303
module: self.tcx.parent_module(self.lint_level).to_def_id(),
301304
pattern_arena: &self.pattern_arena,
305+
match_lint_level: self.lint_level,
302306
match_span,
307+
scrut_span,
303308
refutable,
304309
}
305310
}
@@ -330,7 +335,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
330335
source: hir::MatchSource,
331336
expr_span: Span,
332337
) {
333-
let cx = self.new_cx(Refutable, Some(expr_span));
338+
let scrut = &self.thir[scrut];
339+
let cx = self.new_cx(Refutable, Some(expr_span), scrut.span);
334340

335341
let mut tarms = Vec::with_capacity(arms.len());
336342
for &arm in arms {
@@ -346,9 +352,8 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
346352
}
347353
}
348354

349-
let scrut = &self.thir[scrut];
350355
let scrut_ty = scrut.ty;
351-
let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span);
356+
let report = compute_match_usefulness(&cx, &tarms, scrut_ty);
352357

353358
match source {
354359
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
@@ -453,10 +458,10 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
453458
pat: &Pat<'tcx>,
454459
refutability: RefutableFlag,
455460
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
456-
let cx = self.new_cx(refutability, None);
461+
let cx = self.new_cx(refutability, None, pat.span);
457462
let pat = self.lower_pattern(&cx, pat)?;
458463
let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
459-
let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span());
464+
let report = compute_match_usefulness(&cx, &arms, pat.ty());
460465
Ok((cx, report))
461466
}
462467

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

Lines changed: 181 additions & 191 deletions
Large diffs are not rendered by default.

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

Lines changed: 756 additions & 565 deletions
Large diffs are not rendered by default.

‎tests/ui/or-patterns/exhaustiveness-pass.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ fn main() {
3535
((0, 0) | (1, 0),) => {}
3636
_ => {}
3737
}
38+
match ((0, 0),) {
39+
// Note how the second one would be redundant without the guard.
40+
((x, y) | (y, x),) if x == 0 => {}
41+
_ => {}
42+
}
43+
match 0 {
44+
// We don't warn the second one as redundant in general because of cases like the one above.
45+
// We could technically do it if there are no bindings.
46+
0 | 0 if 0 == 0 => {}
47+
_ => {}
48+
}
3849

3950
// This one caused ICE https://github.com/rust-lang/rust/issues/117378
4051
match (0u8, 0) {

‎tests/ui/or-patterns/exhaustiveness-unreachable-pattern.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![deny(unreachable_patterns)]
22

33
// We wrap patterns in a tuple because top-level or-patterns were special-cased.
4+
#[rustfmt::skip]
45
fn main() {
56
match (0u8,) {
67
(1 | 2,) => {}
@@ -73,6 +74,11 @@ fn main() {
7374
| 0] => {} //~ ERROR unreachable
7475
_ => {}
7576
}
77+
match (true, 0) {
78+
(true, 0 | 0) => {} //~ ERROR unreachable
79+
(_, 0 | 0) => {} //~ ERROR unreachable
80+
_ => {}
81+
}
7682
match &[][..] {
7783
[0] => {}
7884
[0, _] => {}
@@ -149,4 +155,8 @@ fn main() {
149155
| true, //~ ERROR unreachable
150156
false | true) => {}
151157
}
158+
match (true, true) {
159+
(x, y)
160+
| (y, x) => {} //~ ERROR unreachable
161+
}
152162
}
Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unreachable pattern
2-
--> $DIR/exhaustiveness-unreachable-pattern.rs:7:9
2+
--> $DIR/exhaustiveness-unreachable-pattern.rs:8:9
33
|
44
LL | (1,) => {}
55
| ^^^^
@@ -11,128 +11,140 @@ LL | #![deny(unreachable_patterns)]
1111
| ^^^^^^^^^^^^^^^^^^^^
1212

1313
error: unreachable pattern
14-
--> $DIR/exhaustiveness-unreachable-pattern.rs:12:9
14+
--> $DIR/exhaustiveness-unreachable-pattern.rs:13:9
1515
|
1616
LL | (2,) => {}
1717
| ^^^^
1818

1919
error: unreachable pattern
20-
--> $DIR/exhaustiveness-unreachable-pattern.rs:18:9
20+
--> $DIR/exhaustiveness-unreachable-pattern.rs:19:9
2121
|
2222
LL | (1 | 2,) => {}
2323
| ^^^^^^^^
2424

2525
error: unreachable pattern
26-
--> $DIR/exhaustiveness-unreachable-pattern.rs:23:9
26+
--> $DIR/exhaustiveness-unreachable-pattern.rs:24:9
2727
|
2828
LL | (1, 3) => {}
2929
| ^^^^^^
3030

3131
error: unreachable pattern
32-
--> $DIR/exhaustiveness-unreachable-pattern.rs:24:9
32+
--> $DIR/exhaustiveness-unreachable-pattern.rs:25:9
3333
|
3434
LL | (1, 4) => {}
3535
| ^^^^^^
3636

3737
error: unreachable pattern
38-
--> $DIR/exhaustiveness-unreachable-pattern.rs:25:9
38+
--> $DIR/exhaustiveness-unreachable-pattern.rs:26:9
3939
|
4040
LL | (2, 4) => {}
4141
| ^^^^^^
4242

4343
error: unreachable pattern
44-
--> $DIR/exhaustiveness-unreachable-pattern.rs:26:9
44+
--> $DIR/exhaustiveness-unreachable-pattern.rs:27:9
4545
|
4646
LL | (2 | 1, 4) => {}
4747
| ^^^^^^^^^^
4848

4949
error: unreachable pattern
50-
--> $DIR/exhaustiveness-unreachable-pattern.rs:28:9
50+
--> $DIR/exhaustiveness-unreachable-pattern.rs:29:9
5151
|
5252
LL | (1, 4 | 5) => {}
5353
| ^^^^^^^^^^
5454

5555
error: unreachable pattern
56-
--> $DIR/exhaustiveness-unreachable-pattern.rs:36:9
56+
--> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
5757
|
5858
LL | (Some(1),) => {}
5959
| ^^^^^^^^^^
6060

6161
error: unreachable pattern
62-
--> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
62+
--> $DIR/exhaustiveness-unreachable-pattern.rs:38:9
6363
|
6464
LL | (None,) => {}
6565
| ^^^^^^^
6666

6767
error: unreachable pattern
68-
--> $DIR/exhaustiveness-unreachable-pattern.rs:42:9
68+
--> $DIR/exhaustiveness-unreachable-pattern.rs:43:9
6969
|
7070
LL | ((1..=4,),) => {}
7171
| ^^^^^^^^^^^
7272

7373
error: unreachable pattern
74-
--> $DIR/exhaustiveness-unreachable-pattern.rs:47:14
74+
--> $DIR/exhaustiveness-unreachable-pattern.rs:48:14
7575
|
7676
LL | (1 | 1,) => {}
7777
| ^
7878

7979
error: unreachable pattern
80-
--> $DIR/exhaustiveness-unreachable-pattern.rs:51:19
80+
--> $DIR/exhaustiveness-unreachable-pattern.rs:52:19
8181
|
8282
LL | (0 | 1) | 1 => {}
8383
| ^
8484

8585
error: unreachable pattern
86-
--> $DIR/exhaustiveness-unreachable-pattern.rs:57:14
86+
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:14
8787
|
8888
LL | 0 | (0 | 0) => {}
8989
| ^
9090

9191
error: unreachable pattern
92-
--> $DIR/exhaustiveness-unreachable-pattern.rs:57:18
92+
--> $DIR/exhaustiveness-unreachable-pattern.rs:58:18
9393
|
9494
LL | 0 | (0 | 0) => {}
9595
| ^
9696

9797
error: unreachable pattern
98-
--> $DIR/exhaustiveness-unreachable-pattern.rs:65:13
98+
--> $DIR/exhaustiveness-unreachable-pattern.rs:66:13
9999
|
100100
LL | / Some(
101101
LL | | 0 | 0) => {}
102102
| |______________________^
103103

104104
error: unreachable pattern
105-
--> $DIR/exhaustiveness-unreachable-pattern.rs:71:15
105+
--> $DIR/exhaustiveness-unreachable-pattern.rs:72:15
106106
|
107107
LL | | 0
108108
| ^
109109

110110
error: unreachable pattern
111-
--> $DIR/exhaustiveness-unreachable-pattern.rs:73:15
111+
--> $DIR/exhaustiveness-unreachable-pattern.rs:74:15
112112
|
113113
LL | | 0] => {}
114114
| ^
115115

116116
error: unreachable pattern
117-
--> $DIR/exhaustiveness-unreachable-pattern.rs:81:10
117+
--> $DIR/exhaustiveness-unreachable-pattern.rs:78:20
118+
|
119+
LL | (true, 0 | 0) => {}
120+
| ^
121+
122+
error: unreachable pattern
123+
--> $DIR/exhaustiveness-unreachable-pattern.rs:79:17
124+
|
125+
LL | (_, 0 | 0) => {}
126+
| ^
127+
128+
error: unreachable pattern
129+
--> $DIR/exhaustiveness-unreachable-pattern.rs:87:10
118130
|
119131
LL | [1
120132
| ^
121133

122134
error: unreachable pattern
123-
--> $DIR/exhaustiveness-unreachable-pattern.rs:93:10
135+
--> $DIR/exhaustiveness-unreachable-pattern.rs:99:10
124136
|
125137
LL | [true
126138
| ^^^^
127139

128140
error: unreachable pattern
129-
--> $DIR/exhaustiveness-unreachable-pattern.rs:100:36
141+
--> $DIR/exhaustiveness-unreachable-pattern.rs:106:36
130142
|
131143
LL | (true | false, None | Some(true
132144
| ^^^^
133145

134146
error: unreachable pattern
135-
--> $DIR/exhaustiveness-unreachable-pattern.rs:105:14
147+
--> $DIR/exhaustiveness-unreachable-pattern.rs:111:14
136148
|
137149
LL | (true
138150
| ^^^^
@@ -143,28 +155,34 @@ LL | (true | false, None | Some(t_or_f!())) => {}
143155
= note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info)
144156

145157
error: unreachable pattern
146-
--> $DIR/exhaustiveness-unreachable-pattern.rs:116:14
158+
--> $DIR/exhaustiveness-unreachable-pattern.rs:122:14
147159
|
148160
LL | Some(0
149161
| ^
150162

151163
error: unreachable pattern
152-
--> $DIR/exhaustiveness-unreachable-pattern.rs:135:19
164+
--> $DIR/exhaustiveness-unreachable-pattern.rs:141:19
153165
|
154166
LL | | false) => {}
155167
| ^^^^^
156168

157169
error: unreachable pattern
158-
--> $DIR/exhaustiveness-unreachable-pattern.rs:143:15
170+
--> $DIR/exhaustiveness-unreachable-pattern.rs:149:15
159171
|
160172
LL | | true) => {}
161173
| ^^^^
162174

163175
error: unreachable pattern
164-
--> $DIR/exhaustiveness-unreachable-pattern.rs:149:15
176+
--> $DIR/exhaustiveness-unreachable-pattern.rs:155:15
165177
|
166178
LL | | true,
167179
| ^^^^
168180

169-
error: aborting due to 26 previous errors
181+
error: unreachable pattern
182+
--> $DIR/exhaustiveness-unreachable-pattern.rs:160:15
183+
|
184+
LL | | (y, x) => {}
185+
| ^^^^^^
186+
187+
error: aborting due to 29 previous errors
170188

‎tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
2-
--> $DIR/pointer-sized-int.rs:54:11
2+
--> $DIR/pointer-sized-int.rs:59:11
33
|
44
LL | match 7usize {}
55
| ^^^^^^

‎tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | match 0usize {
99
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
1010
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1111
|
12-
LL ~ 0 ..= usize::MAX => {},
12+
LL ~ 0..=usize::MAX => {},
1313
LL + usize::MAX.. => todo!()
1414
|
1515

@@ -24,12 +24,12 @@ LL | match 0isize {
2424
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
2525
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
2626
|
27-
LL ~ isize::MIN ..= isize::MAX => {},
27+
LL ~ isize::MIN..=isize::MAX => {},
2828
LL + ..isize::MIN | isize::MAX.. => todo!()
2929
|
3030

3131
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
32-
--> $DIR/pointer-sized-int.rs:25:8
32+
--> $DIR/pointer-sized-int.rs:24:8
3333
|
3434
LL | m!(0usize, 0..=usize::MAX);
3535
| ^^^^^^ pattern `usize::MAX..` not covered
@@ -43,7 +43,7 @@ LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() }
4343
| +++++++++++++++++++++++++
4444

4545
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
46-
--> $DIR/pointer-sized-int.rs:27:8
46+
--> $DIR/pointer-sized-int.rs:26:8
4747
|
4848
LL | m!(0usize, 0..5 | 5..=usize::MAX);
4949
| ^^^^^^ pattern `usize::MAX..` not covered
@@ -57,7 +57,7 @@ LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() }
5757
| +++++++++++++++++++++++++
5858

5959
error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
60-
--> $DIR/pointer-sized-int.rs:29:8
60+
--> $DIR/pointer-sized-int.rs:28:8
6161
|
6262
LL | m!(0usize, 0..usize::MAX | usize::MAX);
6363
| ^^^^^^ pattern `usize::MAX..` not covered
@@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, usize::MAX.. => todo!() }
7171
| +++++++++++++++++++++++++
7272

7373
error[E0004]: non-exhaustive patterns: `(usize::MAX.., _)` not covered
74-
--> $DIR/pointer-sized-int.rs:31:8
74+
--> $DIR/pointer-sized-int.rs:30:8
7575
|
7676
LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
7777
| ^^^^^^^^^^^^^^ pattern `(usize::MAX.., _)` not covered
@@ -85,7 +85,7 @@ LL | match $s { $($t)+ => {}, (usize::MAX.., _) => todo!() }
8585
| ++++++++++++++++++++++++++++++
8686

8787
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
88-
--> $DIR/pointer-sized-int.rs:36:8
88+
--> $DIR/pointer-sized-int.rs:39:8
8989
|
9090
LL | m!(0isize, isize::MIN..=isize::MAX);
9191
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -99,7 +99,7 @@ LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
9999
| ++++++++++++++++++++++++++++++++++++++++
100100

101101
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
102-
--> $DIR/pointer-sized-int.rs:38:8
102+
--> $DIR/pointer-sized-int.rs:41:8
103103
|
104104
LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX);
105105
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
@@ -113,9 +113,9 @@ LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
113113
| ++++++++++++++++++++++++++++++++++++++++
114114

115115
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
116-
--> $DIR/pointer-sized-int.rs:40:8
116+
--> $DIR/pointer-sized-int.rs:43:8
117117
|
118-
LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX);
118+
LL | m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX);
119119
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
120120
|
121121
= note: the matched value is of type `isize`
@@ -126,37 +126,36 @@ help: ensure that all possible cases are being handled by adding a match arm wit
126126
LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
127127
| ++++++++++++++++++++++++++++++++++++++++
128128

129-
error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
130-
--> $DIR/pointer-sized-int.rs:42:8
129+
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
130+
--> $DIR/pointer-sized-int.rs:45:8
131131
|
132-
LL | m!((0isize, true), (isize::MIN..5, true)
133-
| ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
132+
LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX);
133+
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
134134
|
135-
= note: the matched value is of type `(isize, bool)`
135+
= note: the matched value is of type `isize`
136136
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
137137
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
138138
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
139139
|
140-
LL | match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => todo!() }
141-
| ++++++++++++++++++++++++++++++++++++++++++++++++++
140+
LL | match $s { $($t)+ => {}, ..isize::MIN | isize::MAX.. => todo!() }
141+
| ++++++++++++++++++++++++++++++++++++++++
142142

143-
error[E0004]: non-exhaustive patterns: `..isize::MIN` and `isize::MAX..` not covered
144-
--> $DIR/pointer-sized-int.rs:47:11
143+
error[E0004]: non-exhaustive patterns: `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
144+
--> $DIR/pointer-sized-int.rs:48:9
145145
|
146-
LL | match 0isize {
147-
| ^^^^^^ patterns `..isize::MIN` and `isize::MAX..` not covered
146+
LL | (0isize, true),
147+
| ^^^^^^^^^^^^^^ patterns `(..isize::MIN, _)` and `(isize::MAX.., _)` not covered
148148
|
149-
= note: the matched value is of type `isize`
149+
= note: the matched value is of type `(isize, bool)`
150150
= note: `isize` does not have fixed minimum and maximum values, so half-open ranges are necessary to match exhaustively
151151
= help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
152152
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
153153
|
154-
LL ~ 1 ..= isize::MAX => {},
155-
LL + ..isize::MIN | isize::MAX.. => todo!()
156-
|
154+
LL | match $s { $($t)+ => {}, (..isize::MIN, _) | (isize::MAX.., _) => todo!() }
155+
| ++++++++++++++++++++++++++++++++++++++++++++++++++
157156

158157
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
159-
--> $DIR/pointer-sized-int.rs:54:11
158+
--> $DIR/pointer-sized-int.rs:59:11
160159
|
161160
LL | match 7usize {}
162161
| ^^^^^^

‎tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@ macro_rules! m {
1313
fn main() {
1414
match 0usize {
1515
//[deny]~^ ERROR non-exhaustive patterns
16-
0 ..= usize::MAX => {}
16+
0..=usize::MAX => {}
1717
}
1818

1919
match 0isize {
2020
//[deny]~^ ERROR non-exhaustive patterns
21-
isize::MIN ..= isize::MAX => {}
21+
isize::MIN..=isize::MAX => {}
2222
}
2323

24-
m!(0usize, 0..);
2524
m!(0usize, 0..=usize::MAX);
2625
//[deny]~^ ERROR non-exhaustive patterns
2726
m!(0usize, 0..5 | 5..=usize::MAX);
@@ -30,26 +29,32 @@ fn main() {
3029
//[deny]~^ ERROR non-exhaustive patterns
3130
m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
3231
//[deny]~^ ERROR non-exhaustive patterns
32+
33+
m!(0usize, 0..);
34+
m!(0usize, 0..5 | 5..);
35+
m!(0usize, ..5 | 5..);
36+
m!((0usize, true), (0..5, true) | (5.., true) | (0.., false));
3337
m!(0usize, 0..=usize::MAX | usize::MAX..);
3438

35-
m!(0isize, ..0 | 0..);
3639
m!(0isize, isize::MIN..=isize::MAX);
3740
//[deny]~^ ERROR non-exhaustive patterns
3841
m!(0isize, isize::MIN..5 | 5..=isize::MAX);
3942
//[deny]~^ ERROR non-exhaustive patterns
43+
m!(0isize, isize::MIN..=-1 | 0 | 1..=isize::MAX);
44+
//[deny]~^ ERROR non-exhaustive patterns
4045
m!(0isize, isize::MIN..isize::MAX | isize::MAX);
4146
//[deny]~^ ERROR non-exhaustive patterns
42-
m!((0isize, true), (isize::MIN..5, true)
43-
| (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
44-
//[deny]~^^ ERROR non-exhaustive patterns
45-
m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..);
47+
m!(
48+
(0isize, true),
49+
(isize::MIN..5, true) | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false)
50+
);
51+
//[deny]~^^^ ERROR non-exhaustive patterns
4652

47-
match 0isize {
48-
//[deny]~^ ERROR non-exhaustive patterns
49-
isize::MIN ..= -1 => {}
50-
0 => {}
51-
1 ..= isize::MAX => {}
52-
}
53+
m!(0isize, ..0 | 0..);
54+
m!(0isize, ..5 | 5..);
55+
m!((0isize, true), (..5, true)
56+
| (5.., true) | (..0 | 0.., false));
57+
m!(0isize, ..=isize::MIN | isize::MIN..=isize::MAX | isize::MAX..);
5358

5459
match 7usize {}
5560
//~^ ERROR non-exhaustive patterns

‎tests/ui/pattern/usefulness/integer-ranges/reachability.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ macro_rules! m {
99
$t2 => {}
1010
_ => {}
1111
}
12-
}
12+
};
1313
}
1414

15+
#[rustfmt::skip]
1516
fn main() {
1617
m!(0u8, 42, 41);
1718
m!(0u8, 42, 42); //~ ERROR unreachable pattern
@@ -85,7 +86,7 @@ fn main() {
8586
match 'a' {
8687
'\u{0}'..='\u{D7FF}' => {},
8788
'\u{E000}'..='\u{10_FFFF}' => {},
88-
'\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable
89+
'\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern
8990
}
9091

9192
match (0u8, true) {
Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unreachable pattern
2-
--> $DIR/reachability.rs:17:17
2+
--> $DIR/reachability.rs:18:17
33
|
44
LL | m!(0u8, 42, 42);
55
| ^^
@@ -11,144 +11,150 @@ LL | #![deny(unreachable_patterns)]
1111
| ^^^^^^^^^^^^^^^^^^^^
1212

1313
error: unreachable pattern
14-
--> $DIR/reachability.rs:21:22
14+
--> $DIR/reachability.rs:22:22
1515
|
1616
LL | m!(0u8, 20..=30, 20);
1717
| ^^
1818

1919
error: unreachable pattern
20-
--> $DIR/reachability.rs:22:22
20+
--> $DIR/reachability.rs:23:22
2121
|
2222
LL | m!(0u8, 20..=30, 21);
2323
| ^^
2424

2525
error: unreachable pattern
26-
--> $DIR/reachability.rs:23:22
26+
--> $DIR/reachability.rs:24:22
2727
|
2828
LL | m!(0u8, 20..=30, 25);
2929
| ^^
3030

3131
error: unreachable pattern
32-
--> $DIR/reachability.rs:24:22
32+
--> $DIR/reachability.rs:25:22
3333
|
3434
LL | m!(0u8, 20..=30, 29);
3535
| ^^
3636

3737
error: unreachable pattern
38-
--> $DIR/reachability.rs:25:22
38+
--> $DIR/reachability.rs:26:22
3939
|
4040
LL | m!(0u8, 20..=30, 30);
4141
| ^^
4242

4343
error: unreachable pattern
44-
--> $DIR/reachability.rs:28:21
44+
--> $DIR/reachability.rs:29:21
4545
|
4646
LL | m!(0u8, 20..30, 20);
4747
| ^^
4848

4949
error: unreachable pattern
50-
--> $DIR/reachability.rs:29:21
50+
--> $DIR/reachability.rs:30:21
5151
|
5252
LL | m!(0u8, 20..30, 21);
5353
| ^^
5454

5555
error: unreachable pattern
56-
--> $DIR/reachability.rs:30:21
56+
--> $DIR/reachability.rs:31:21
5757
|
5858
LL | m!(0u8, 20..30, 25);
5959
| ^^
6060

6161
error: unreachable pattern
62-
--> $DIR/reachability.rs:31:21
62+
--> $DIR/reachability.rs:32:21
6363
|
6464
LL | m!(0u8, 20..30, 29);
6565
| ^^
6666

6767
error: unreachable pattern
68-
--> $DIR/reachability.rs:35:22
68+
--> $DIR/reachability.rs:36:22
6969
|
7070
LL | m!(0u8, 20..=30, 20..=30);
7171
| ^^^^^^^
7272

7373
error: unreachable pattern
74-
--> $DIR/reachability.rs:36:22
74+
--> $DIR/reachability.rs:37:22
7575
|
7676
LL | m!(0u8, 20.. 30, 20.. 30);
7777
| ^^^^^^^
7878

7979
error: unreachable pattern
80-
--> $DIR/reachability.rs:37:22
80+
--> $DIR/reachability.rs:38:22
8181
|
8282
LL | m!(0u8, 20..=30, 20.. 30);
8383
| ^^^^^^^
8484

8585
error: unreachable pattern
86-
--> $DIR/reachability.rs:39:22
86+
--> $DIR/reachability.rs:40:22
8787
|
8888
LL | m!(0u8, 20..=30, 21..=30);
8989
| ^^^^^^^
9090

9191
error: unreachable pattern
92-
--> $DIR/reachability.rs:40:22
92+
--> $DIR/reachability.rs:41:22
9393
|
9494
LL | m!(0u8, 20..=30, 20..=29);
9595
| ^^^^^^^
9696

9797
error: unreachable pattern
98-
--> $DIR/reachability.rs:42:24
98+
--> $DIR/reachability.rs:43:24
9999
|
100100
LL | m!('a', 'A'..='z', 'a'..='z');
101101
| ^^^^^^^^^
102102

103103
error: unreachable pattern
104-
--> $DIR/reachability.rs:49:9
104+
--> $DIR/reachability.rs:50:9
105105
|
106106
LL | 5..=8 => {},
107107
| ^^^^^
108108

109109
error: unreachable pattern
110-
--> $DIR/reachability.rs:55:9
110+
--> $DIR/reachability.rs:56:9
111111
|
112112
LL | 5..15 => {},
113113
| ^^^^^
114114

115115
error: unreachable pattern
116-
--> $DIR/reachability.rs:62:9
116+
--> $DIR/reachability.rs:63:9
117117
|
118118
LL | 5..25 => {},
119119
| ^^^^^
120120

121121
error: unreachable pattern
122-
--> $DIR/reachability.rs:70:9
122+
--> $DIR/reachability.rs:71:9
123123
|
124124
LL | 5..25 => {},
125125
| ^^^^^
126126

127127
error: unreachable pattern
128-
--> $DIR/reachability.rs:76:9
128+
--> $DIR/reachability.rs:77:9
129129
|
130130
LL | 5..15 => {},
131131
| ^^^^^
132132

133133
error: unreachable pattern
134-
--> $DIR/reachability.rs:83:9
134+
--> $DIR/reachability.rs:84:9
135135
|
136136
LL | _ => {},
137137
| - matches any value
138138
LL | '\u{D7FF}'..='\u{E000}' => {},
139139
| ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
140140

141141
error: unreachable pattern
142-
--> $DIR/reachability.rs:104:9
142+
--> $DIR/reachability.rs:89:9
143+
|
144+
LL | '\u{D7FF}'..='\u{E000}' => {},
145+
| ^^^^^^^^^^^^^^^^^^^^^^^
146+
147+
error: unreachable pattern
148+
--> $DIR/reachability.rs:105:9
143149
|
144150
LL | &FOO => {}
145151
| ^^^^
146152

147153
error: unreachable pattern
148-
--> $DIR/reachability.rs:105:9
154+
--> $DIR/reachability.rs:106:9
149155
|
150156
LL | BAR => {}
151157
| ^^^
152158

153-
error: aborting due to 24 previous errors
159+
error: aborting due to 25 previous errors
154160

‎tests/ui/pattern/usefulness/issue-3601.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn main() {
3131
//~^ ERROR non-exhaustive patterns
3232
//~| NOTE the matched value is of type
3333
//~| NOTE match arms with guards don't count towards exhaustivity
34-
//~| NOTE pattern `box _` not covered
34+
//~| NOTE pattern `box ElementKind::HTMLImageElement(_)` not covered
3535
//~| NOTE `Box<ElementKind>` defined here
3636
box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
3737
},

‎tests/ui/pattern/usefulness/issue-3601.stderr

Lines changed: 3 additions & 3 deletions
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 ElementKind::HTMLImageElement(_)` 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 ElementKind::HTMLImageElement(_)` not covered
66
|
77
note: `Box<ElementKind>` defined here
88
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
@@ -11,7 +11,7 @@ note: `Box<ElementKind>` defined here
1111
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
1212
|
1313
LL ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => true,
14-
LL ~ box _ => todo!(),
14+
LL ~ box ElementKind::HTMLImageElement(_) => todo!(),
1515
|
1616

1717
error: aborting due to previous error

‎tests/ui/pattern/usefulness/match-non-exhaustive.stderr

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ help: ensure that all possible cases are being handled by adding a match arm wit
1010
LL | match 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() }
1111
| ++++++++++++++++++++++++++++++++++++++++++++++++
1212

13-
error[E0004]: non-exhaustive patterns: `_` not covered
13+
error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
1414
--> $DIR/match-non-exhaustive.rs:3:11
1515
|
1616
LL | match 0 { 0 if false => () }
17-
| ^ pattern `_` not covered
17+
| ^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
1818
|
1919
= note: the matched value is of type `i32`
2020
= note: match arms with guards don't count towards exhaustivity
21-
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
21+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
2222
|
23-
LL | match 0 { 0 if false => (), _ => todo!() }
24-
| ++++++++++++++
23+
LL | match 0 { 0 if false => (), i32::MIN..=-1_i32 | 1_i32..=i32::MAX => todo!() }
24+
| +++++++++++++++++++++++++++++++++++++++++++++++++
2525

2626
error: aborting due to 2 previous errors
2727

‎tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ fn main() {
4343
//~^ ERROR `&[_, ..]` not covered
4444
[] => {}
4545
}
46+
match s {
47+
//~^ ERROR `&[]` and `&[_, ..]` not covered
48+
[..] if false => {}
49+
}
4650
match s {
4751
//~^ ERROR `&[_, _, ..]` not covered
4852
[] => {}

‎tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,23 @@ LL ~ [] => {},
8989
LL + &[_, ..] => todo!()
9090
|
9191

92-
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
92+
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
9393
--> $DIR/slice-patterns-exhaustiveness.rs:46:11
9494
|
95+
LL | match s {
96+
| ^ patterns `&[]` and `&[_, ..]` not covered
97+
|
98+
= note: the matched value is of type `&[bool]`
99+
= note: match arms with guards don't count towards exhaustivity
100+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
101+
|
102+
LL ~ [..] if false => {},
103+
LL + &[] | &[_, ..] => todo!()
104+
|
105+
106+
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
107+
--> $DIR/slice-patterns-exhaustiveness.rs:50:11
108+
|
95109
LL | match s {
96110
| ^ pattern `&[_, _, ..]` not covered
97111
|
@@ -103,7 +117,7 @@ LL + &[_, _, ..] => todo!()
103117
|
104118

105119
error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
106-
--> $DIR/slice-patterns-exhaustiveness.rs:51:11
120+
--> $DIR/slice-patterns-exhaustiveness.rs:55:11
107121
|
108122
LL | match s {
109123
| ^ pattern `&[false, ..]` not covered
@@ -116,7 +130,7 @@ LL + &[false, ..] => todo!()
116130
|
117131

118132
error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
119-
--> $DIR/slice-patterns-exhaustiveness.rs:56:11
133+
--> $DIR/slice-patterns-exhaustiveness.rs:60:11
120134
|
121135
LL | match s {
122136
| ^ pattern `&[false, _, ..]` not covered
@@ -129,7 +143,7 @@ LL + &[false, _, ..] => todo!()
129143
|
130144

131145
error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
132-
--> $DIR/slice-patterns-exhaustiveness.rs:62:11
146+
--> $DIR/slice-patterns-exhaustiveness.rs:66:11
133147
|
134148
LL | match s {
135149
| ^ pattern `&[_, .., false]` not covered
@@ -142,7 +156,7 @@ LL + &[_, .., false] => todo!()
142156
|
143157

144158
error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
145-
--> $DIR/slice-patterns-exhaustiveness.rs:69:11
159+
--> $DIR/slice-patterns-exhaustiveness.rs:73:11
146160
|
147161
LL | match s {
148162
| ^ pattern `&[_, _, .., true]` not covered
@@ -155,7 +169,7 @@ LL + &[_, _, .., true] => todo!()
155169
|
156170

157171
error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
158-
--> $DIR/slice-patterns-exhaustiveness.rs:76:11
172+
--> $DIR/slice-patterns-exhaustiveness.rs:80:11
159173
|
160174
LL | match s {
161175
| ^ pattern `&[true, _, .., _]` not covered
@@ -168,7 +182,7 @@ LL + &[true, _, .., _] => todo!()
168182
|
169183

170184
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
171-
--> $DIR/slice-patterns-exhaustiveness.rs:85:11
185+
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
172186
|
173187
LL | match s {
174188
| ^ patterns `&[]` and `&[_, _, ..]` not covered
@@ -181,7 +195,7 @@ LL + &[] | &[_, _, ..] => todo!()
181195
|
182196

183197
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
184-
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
198+
--> $DIR/slice-patterns-exhaustiveness.rs:93:11
185199
|
186200
LL | match s {
187201
| ^ patterns `&[]` and `&[_, _, ..]` not covered
@@ -194,7 +208,7 @@ LL + &[] | &[_, _, ..] => todo!()
194208
|
195209

196210
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
197-
--> $DIR/slice-patterns-exhaustiveness.rs:93:11
211+
--> $DIR/slice-patterns-exhaustiveness.rs:97:11
198212
|
199213
LL | match s {
200214
| ^ patterns `&[]` and `&[_, _, ..]` not covered
@@ -207,7 +221,7 @@ LL + &[] | &[_, _, ..] => todo!()
207221
|
208222

209223
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
210-
--> $DIR/slice-patterns-exhaustiveness.rs:98:11
224+
--> $DIR/slice-patterns-exhaustiveness.rs:102:11
211225
|
212226
LL | match s {
213227
| ^ patterns `&[]` and `&[_, _, ..]` not covered
@@ -220,7 +234,7 @@ LL + &[] | &[_, _, ..] => todo!()
220234
|
221235

222236
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
223-
--> $DIR/slice-patterns-exhaustiveness.rs:103:11
237+
--> $DIR/slice-patterns-exhaustiveness.rs:107:11
224238
|
225239
LL | match s {
226240
| ^ pattern `&[_, _, ..]` not covered
@@ -233,7 +247,7 @@ LL + &[_, _, ..] => todo!()
233247
|
234248

235249
error[E0004]: non-exhaustive patterns: `&[false]` not covered
236-
--> $DIR/slice-patterns-exhaustiveness.rs:108:11
250+
--> $DIR/slice-patterns-exhaustiveness.rs:112:11
237251
|
238252
LL | match s {
239253
| ^ pattern `&[false]` not covered
@@ -246,7 +260,7 @@ LL + &[false] => todo!()
246260
|
247261

248262
error[E0004]: non-exhaustive patterns: `&[false]` not covered
249-
--> $DIR/slice-patterns-exhaustiveness.rs:121:11
263+
--> $DIR/slice-patterns-exhaustiveness.rs:125:11
250264
|
251265
LL | match s1 {
252266
| ^^ pattern `&[false]` not covered
@@ -258,6 +272,6 @@ LL ~ CONST1 => {},
258272
LL + &[false] => todo!()
259273
|
260274

261-
error: aborting due to 20 previous errors
275+
error: aborting due to 21 previous errors
262276

263277
For more information about this error, try `rustc --explain E0004`.

‎tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
22

33
#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)]
4+
#![deny(unreachable_patterns)]
45

56
// aux-build:enums.rs
67
extern crate enums;
@@ -31,11 +32,21 @@ pub enum Bar {
3132
C,
3233
}
3334

35+
fn no_lint() {
36+
let non_enum = NonExhaustiveEnum::Unit;
37+
// Ok: without the attribute
38+
match non_enum {
39+
NonExhaustiveEnum::Unit => {}
40+
NonExhaustiveEnum::Tuple(_) => {}
41+
_ => {}
42+
}
43+
}
44+
45+
#[deny(non_exhaustive_omitted_patterns)]
3446
fn main() {
3547
let enumeration = Bar::A;
3648

3749
// Ok: this is a crate local non_exhaustive enum
38-
#[deny(non_exhaustive_omitted_patterns)]
3950
match enumeration {
4051
Bar::A => {}
4152
Bar::B => {}
@@ -44,22 +55,20 @@ fn main() {
4455

4556
let non_enum = NonExhaustiveEnum::Unit;
4657

47-
// Ok: without the attribute
58+
#[allow(non_exhaustive_omitted_patterns)]
4859
match non_enum {
4960
NonExhaustiveEnum::Unit => {}
5061
NonExhaustiveEnum::Tuple(_) => {}
5162
_ => {}
5263
}
5364

54-
#[deny(non_exhaustive_omitted_patterns)]
5565
match non_enum {
5666
//~^ some variants are not matched explicitly
5767
NonExhaustiveEnum::Unit => {}
5868
NonExhaustiveEnum::Tuple(_) => {}
5969
_ => {}
6070
}
6171

62-
#[deny(non_exhaustive_omitted_patterns)]
6372
match non_enum {
6473
//~^ some variants are not matched explicitly
6574
NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
@@ -68,45 +77,39 @@ fn main() {
6877

6978
let x = 5;
7079
// We ignore the guard.
71-
#[deny(non_exhaustive_omitted_patterns)]
7280
match non_enum {
7381
NonExhaustiveEnum::Unit if x > 10 => {}
7482
NonExhaustiveEnum::Tuple(_) => {}
7583
NonExhaustiveEnum::Struct { .. } => {}
7684
_ => {}
7785
}
7886

79-
#[deny(non_exhaustive_omitted_patterns)]
8087
match (non_enum, true) {
8188
(NonExhaustiveEnum::Unit, true) => {}
8289
(NonExhaustiveEnum::Tuple(_), false) => {}
8390
(NonExhaustiveEnum::Struct { .. }, false) => {}
8491
_ => {}
8592
}
86-
#[deny(non_exhaustive_omitted_patterns)]
8793
match (non_enum, true) {
8894
//~^ some variants are not matched explicitly
8995
(NonExhaustiveEnum::Unit, true) => {}
9096
(NonExhaustiveEnum::Tuple(_), false) => {}
9197
_ => {}
9298
}
9399

94-
#[deny(non_exhaustive_omitted_patterns)]
95100
match (true, non_enum) {
96101
(true, NonExhaustiveEnum::Unit) => {}
97102
(false, NonExhaustiveEnum::Tuple(_)) => {}
98103
(false, NonExhaustiveEnum::Struct { .. }) => {}
99104
_ => {}
100105
}
101-
#[deny(non_exhaustive_omitted_patterns)]
102106
match (true, non_enum) {
103107
//~^ some variants are not matched explicitly
104108
(true, NonExhaustiveEnum::Unit) => {}
105109
(false, NonExhaustiveEnum::Tuple(_)) => {}
106110
_ => {}
107111
}
108112

109-
#[deny(non_exhaustive_omitted_patterns)]
110113
match Some(non_enum) {
111114
//~^ some variants are not matched explicitly
112115
Some(NonExhaustiveEnum::Unit) => {}
@@ -116,15 +119,13 @@ fn main() {
116119

117120
// Ok: all covered and not `unreachable-patterns`
118121
#[deny(unreachable_patterns)]
119-
#[deny(non_exhaustive_omitted_patterns)]
120122
match non_enum {
121123
NonExhaustiveEnum::Unit => {}
122124
NonExhaustiveEnum::Tuple(_) => {}
123125
NonExhaustiveEnum::Struct { .. } => {}
124126
_ => {}
125127
}
126128

127-
#[deny(non_exhaustive_omitted_patterns)]
128129
match NestedNonExhaustive::B {
129130
//~^ some variants are not matched explicitly
130131
NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
@@ -133,54 +134,53 @@ fn main() {
133134
_ => {}
134135
}
135136

136-
#[warn(non_exhaustive_omitted_patterns)]
137137
match VariantNonExhaustive::Baz(1, 2) {
138138
VariantNonExhaustive::Baz(_, _) => {}
139139
VariantNonExhaustive::Bar { x, .. } => {}
140140
}
141141
//~^^ some fields are not explicitly listed
142142

143-
#[warn(non_exhaustive_omitted_patterns)]
144143
let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
145144
//~^ some fields are not explicitly listed
146145

147146
// Ok: this is local
148-
#[warn(non_exhaustive_omitted_patterns)]
149147
let Foo { a, b, .. } = Foo::default();
150148

151-
#[warn(non_exhaustive_omitted_patterns)]
152149
let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
153150
//~^ some fields are not explicitly listed
154151
//~^^ some fields are not explicitly listed
155152

156153
// Ok: this tests https://github.com/rust-lang/rust/issues/89382
157-
#[warn(non_exhaustive_omitted_patterns)]
158154
let MixedVisFields { a, b, .. } = MixedVisFields::default();
159155

160156
// Ok: this only has 1 variant
161-
#[deny(non_exhaustive_omitted_patterns)]
162157
match NonExhaustiveSingleVariant::A(true) {
163158
NonExhaustiveSingleVariant::A(true) => {}
164159
_ => {}
165160
}
166161

167162
// We can't catch the case below, so for consistency we don't catch this one either.
168-
#[deny(non_exhaustive_omitted_patterns)]
169163
match NonExhaustiveSingleVariant::A(true) {
170164
_ => {}
171165
}
172166
// We can't catch this case, because this would require digging fully through all the values of
173167
// any type we encounter. We need to be able to only consider present constructors.
174-
#[deny(non_exhaustive_omitted_patterns)]
175168
match &NonExhaustiveSingleVariant::A(true) {
176169
_ => {}
177170
}
178171

172+
match Some(NonExhaustiveSingleVariant::A(true)) {
173+
Some(_) => {}
174+
None => {}
175+
}
176+
match Some(&NonExhaustiveSingleVariant::A(true)) {
177+
Some(_) => {}
178+
None => {}
179+
}
180+
179181
// Ok: we don't lint on `if let` expressions
180-
#[deny(non_exhaustive_omitted_patterns)]
181182
if let NonExhaustiveEnum::Tuple(_) = non_enum {}
182183

183-
#[deny(non_exhaustive_omitted_patterns)]
184184
match UnstableEnum::Stable {
185185
//~^ some variants are not matched explicitly
186186
UnstableEnum::Stable => {}
@@ -189,7 +189,6 @@ fn main() {
189189
}
190190

191191
// Ok: the feature is on and all variants are matched
192-
#[deny(non_exhaustive_omitted_patterns)]
193192
match UnstableEnum::Stable {
194193
UnstableEnum::Stable => {}
195194
UnstableEnum::Stable2 => {}
@@ -198,52 +197,66 @@ fn main() {
198197
}
199198

200199
// Ok: the feature is on and both variants are matched
201-
#[deny(non_exhaustive_omitted_patterns)]
202200
match OnlyUnstableEnum::Unstable {
203201
OnlyUnstableEnum::Unstable => {}
204202
OnlyUnstableEnum::Unstable2 => {}
205203
_ => {}
206204
}
207205

208-
#[deny(non_exhaustive_omitted_patterns)]
209206
match OnlyUnstableEnum::Unstable {
210207
//~^ some variants are not matched explicitly
211208
OnlyUnstableEnum::Unstable => {}
212209
_ => {}
213210
}
214211

215-
#[warn(non_exhaustive_omitted_patterns)]
216212
let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
217213
//~^ some fields are not explicitly listed
218214

219215
// OK: both unstable fields are matched with feature on
220-
#[warn(non_exhaustive_omitted_patterns)]
221216
let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
222217

223-
#[warn(non_exhaustive_omitted_patterns)]
224218
let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
225219
//~^ some fields are not explicitly listed
226220

227221
// OK: both unstable and stable fields are matched with feature on
228-
#[warn(non_exhaustive_omitted_patterns)]
229222
let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
230223

231224
// Ok: local bindings are allowed
232-
#[deny(non_exhaustive_omitted_patterns)]
233225
let local = NonExhaustiveEnum::Unit;
234226

235227
// Ok: missing patterns will be blocked by the pattern being refutable
236-
#[deny(non_exhaustive_omitted_patterns)]
237228
let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
238229
//~^ refutable pattern in local binding
239230

240-
#[deny(non_exhaustive_omitted_patterns)]
231+
// Check that matching on a reference results in a correct diagnostic
241232
match &non_enum {
242233
//~^ some variants are not matched explicitly
234+
//~| pattern `&NonExhaustiveEnum::Struct { .. }` not covered
243235
NonExhaustiveEnum::Unit => {}
244236
NonExhaustiveEnum::Tuple(_) => {}
245237
_ => {}
246238
}
239+
240+
match (true, &non_enum) {
241+
//~^ some variants are not matched explicitly
242+
//~| patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered
243+
(true, NonExhaustiveEnum::Unit) => {}
244+
_ => {}
245+
}
246+
247+
match (&non_enum, true) {
248+
//~^ some variants are not matched explicitly
249+
//~| patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered
250+
(NonExhaustiveEnum::Unit, true) => {}
251+
_ => {}
252+
}
253+
254+
match Some(&non_enum) {
255+
//~^ some variants are not matched explicitly
256+
//~| pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered
257+
Some(NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_)) => {}
258+
_ => {}
259+
}
247260
}
248261

249262
#[deny(non_exhaustive_omitted_patterns)]
Lines changed: 50 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
warning: some fields are not explicitly listed
1+
error: some fields are not explicitly listed
22
--> $DIR/omitted-patterns.rs:139:9
33
|
44
LL | VariantNonExhaustive::Bar { x, .. } => {}
@@ -7,159 +7,109 @@ LL | VariantNonExhaustive::Bar { x, .. } => {}
77
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
88
= note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
99
note: the lint level is defined here
10-
--> $DIR/omitted-patterns.rs:136:12
10+
--> $DIR/omitted-patterns.rs:45:8
1111
|
12-
LL | #[warn(non_exhaustive_omitted_patterns)]
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
LL | #[deny(non_exhaustive_omitted_patterns)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

15-
warning: some fields are not explicitly listed
16-
--> $DIR/omitted-patterns.rs:144:9
15+
error: some fields are not explicitly listed
16+
--> $DIR/omitted-patterns.rs:143:9
1717
|
1818
LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
2020
|
2121
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
2222
= note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
23-
note: the lint level is defined here
24-
--> $DIR/omitted-patterns.rs:143:12
25-
|
26-
LL | #[warn(non_exhaustive_omitted_patterns)]
27-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2823

29-
warning: some fields are not explicitly listed
30-
--> $DIR/omitted-patterns.rs:152:29
24+
error: some fields are not explicitly listed
25+
--> $DIR/omitted-patterns.rs:149:29
3126
|
3227
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
3328
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
3429
|
3530
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
3631
= note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
37-
note: the lint level is defined here
38-
--> $DIR/omitted-patterns.rs:151:12
39-
|
40-
LL | #[warn(non_exhaustive_omitted_patterns)]
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4232

43-
warning: some fields are not explicitly listed
44-
--> $DIR/omitted-patterns.rs:152:9
33+
error: some fields are not explicitly listed
34+
--> $DIR/omitted-patterns.rs:149:9
4535
|
4636
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
4737
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
4838
|
4939
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
5040
= note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
5141

52-
warning: some fields are not explicitly listed
53-
--> $DIR/omitted-patterns.rs:216:9
42+
error: some fields are not explicitly listed
43+
--> $DIR/omitted-patterns.rs:212:9
5444
|
5545
LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
5646
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
5747
|
5848
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
5949
= note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
60-
note: the lint level is defined here
61-
--> $DIR/omitted-patterns.rs:215:12
62-
|
63-
LL | #[warn(non_exhaustive_omitted_patterns)]
64-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6550

66-
warning: some fields are not explicitly listed
67-
--> $DIR/omitted-patterns.rs:224:9
51+
error: some fields are not explicitly listed
52+
--> $DIR/omitted-patterns.rs:218:9
6853
|
6954
LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
7055
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
7156
|
7257
= help: ensure that all fields are mentioned explicitly by adding the suggested fields
7358
= note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
74-
note: the lint level is defined here
75-
--> $DIR/omitted-patterns.rs:223:12
76-
|
77-
LL | #[warn(non_exhaustive_omitted_patterns)]
78-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7959

8060
error: some variants are not matched explicitly
81-
--> $DIR/omitted-patterns.rs:55:11
61+
--> $DIR/omitted-patterns.rs:65:11
8262
|
8363
LL | match non_enum {
8464
| ^^^^^^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
8565
|
8666
= help: ensure that all variants are matched explicitly by adding the suggested match arms
8767
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
88-
note: the lint level is defined here
89-
--> $DIR/omitted-patterns.rs:54:12
90-
|
91-
LL | #[deny(non_exhaustive_omitted_patterns)]
92-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9368

9469
error: some variants are not matched explicitly
95-
--> $DIR/omitted-patterns.rs:63:11
70+
--> $DIR/omitted-patterns.rs:72:11
9671
|
9772
LL | match non_enum {
9873
| ^^^^^^^^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
9974
|
10075
= help: ensure that all variants are matched explicitly by adding the suggested match arms
10176
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
102-
note: the lint level is defined here
103-
--> $DIR/omitted-patterns.rs:62:12
104-
|
105-
LL | #[deny(non_exhaustive_omitted_patterns)]
106-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10777

10878
error: some variants are not matched explicitly
109-
--> $DIR/omitted-patterns.rs:87:11
79+
--> $DIR/omitted-patterns.rs:93:11
11080
|
11181
LL | match (non_enum, true) {
11282
| ^^^^^^^^^^^^^^^^ pattern `(NonExhaustiveEnum::Struct { .. }, _)` not covered
11383
|
11484
= help: ensure that all variants are matched explicitly by adding the suggested match arms
11585
= note: the matched value is of type `(NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
116-
note: the lint level is defined here
117-
--> $DIR/omitted-patterns.rs:86:12
118-
|
119-
LL | #[deny(non_exhaustive_omitted_patterns)]
120-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12186

12287
error: some variants are not matched explicitly
123-
--> $DIR/omitted-patterns.rs:102:11
88+
--> $DIR/omitted-patterns.rs:106:11
12489
|
12590
LL | match (true, non_enum) {
12691
| ^^^^^^^^^^^^^^^^ pattern `(_, NonExhaustiveEnum::Struct { .. })` not covered
12792
|
12893
= help: ensure that all variants are matched explicitly by adding the suggested match arms
12994
= note: the matched value is of type `(bool, NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
130-
note: the lint level is defined here
131-
--> $DIR/omitted-patterns.rs:101:12
132-
|
133-
LL | #[deny(non_exhaustive_omitted_patterns)]
134-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13595

13696
error: some variants are not matched explicitly
137-
--> $DIR/omitted-patterns.rs:110:11
97+
--> $DIR/omitted-patterns.rs:113:11
13898
|
13999
LL | match Some(non_enum) {
140100
| ^^^^^^^^^^^^^^ pattern `Some(NonExhaustiveEnum::Struct { .. })` not covered
141101
|
142102
= help: ensure that all variants are matched explicitly by adding the suggested match arms
143103
= note: the matched value is of type `Option<NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
144-
note: the lint level is defined here
145-
--> $DIR/omitted-patterns.rs:109:12
146-
|
147-
LL | #[deny(non_exhaustive_omitted_patterns)]
148-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
149104

150105
error: some variants are not matched explicitly
151-
--> $DIR/omitted-patterns.rs:128:11
106+
--> $DIR/omitted-patterns.rs:129:11
152107
|
153108
LL | match NestedNonExhaustive::B {
154109
| ^^^^^^^^^^^^^^^^^^^^^^ patterns `NestedNonExhaustive::C`, `NestedNonExhaustive::A(NonExhaustiveEnum::Tuple(_))` and `NestedNonExhaustive::A(NonExhaustiveEnum::Struct { .. })` not covered
155110
|
156111
= help: ensure that all variants are matched explicitly by adding the suggested match arms
157112
= note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
158-
note: the lint level is defined here
159-
--> $DIR/omitted-patterns.rs:127:12
160-
|
161-
LL | #[deny(non_exhaustive_omitted_patterns)]
162-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
163113

164114
error: some variants are not matched explicitly
165115
--> $DIR/omitted-patterns.rs:184:11
@@ -169,28 +119,18 @@ LL | match UnstableEnum::Stable {
169119
|
170120
= help: ensure that all variants are matched explicitly by adding the suggested match arms
171121
= note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
172-
note: the lint level is defined here
173-
--> $DIR/omitted-patterns.rs:183:12
174-
|
175-
LL | #[deny(non_exhaustive_omitted_patterns)]
176-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
177122

178123
error: some variants are not matched explicitly
179-
--> $DIR/omitted-patterns.rs:209:11
124+
--> $DIR/omitted-patterns.rs:206:11
180125
|
181126
LL | match OnlyUnstableEnum::Unstable {
182127
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `OnlyUnstableEnum::Unstable2` not covered
183128
|
184129
= help: ensure that all variants are matched explicitly by adding the suggested match arms
185130
= note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
186-
note: the lint level is defined here
187-
--> $DIR/omitted-patterns.rs:208:12
188-
|
189-
LL | #[deny(non_exhaustive_omitted_patterns)]
190-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
191131

192132
error[E0005]: refutable pattern in local binding
193-
--> $DIR/omitted-patterns.rs:237:9
133+
--> $DIR/omitted-patterns.rs:228:9
194134
|
195135
LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
196136
| ^^^^^^^^^^^^^^^ pattern `_` not covered
@@ -204,19 +144,41 @@ LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit
204144
| ++++++++++++++++
205145

206146
error: some variants are not matched explicitly
207-
--> $DIR/omitted-patterns.rs:241:11
147+
--> $DIR/omitted-patterns.rs:232:11
208148
|
209149
LL | match &non_enum {
210150
| ^^^^^^^^^ pattern `&NonExhaustiveEnum::Struct { .. }` not covered
211151
|
212152
= help: ensure that all variants are matched explicitly by adding the suggested match arms
213153
= note: the matched value is of type `&NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
214-
note: the lint level is defined here
215-
--> $DIR/omitted-patterns.rs:240:12
154+
155+
error: some variants are not matched explicitly
156+
--> $DIR/omitted-patterns.rs:240:11
157+
|
158+
LL | match (true, &non_enum) {
159+
| ^^^^^^^^^^^^^^^^^ patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered
216160
|
217-
LL | #[deny(non_exhaustive_omitted_patterns)]
218-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
161+
= help: ensure that all variants are matched explicitly by adding the suggested match arms
162+
= note: the matched value is of type `(bool, &NonExhaustiveEnum)` and the `non_exhaustive_omitted_patterns` attribute was found
163+
164+
error: some variants are not matched explicitly
165+
--> $DIR/omitted-patterns.rs:247:11
166+
|
167+
LL | match (&non_enum, true) {
168+
| ^^^^^^^^^^^^^^^^^ patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered
169+
|
170+
= help: ensure that all variants are matched explicitly by adding the suggested match arms
171+
= note: the matched value is of type `(&NonExhaustiveEnum, bool)` and the `non_exhaustive_omitted_patterns` attribute was found
172+
173+
error: some variants are not matched explicitly
174+
--> $DIR/omitted-patterns.rs:254:11
175+
|
176+
LL | match Some(&non_enum) {
177+
| ^^^^^^^^^^^^^^^ pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered
178+
|
179+
= help: ensure that all variants are matched explicitly by adding the suggested match arms
180+
= note: the matched value is of type `Option<&NonExhaustiveEnum>` and the `non_exhaustive_omitted_patterns` attribute was found
219181

220-
error: aborting due to 10 previous errors; 6 warnings emitted
182+
error: aborting due to 19 previous errors
221183

222184
For more information about this error, try `rustc --explain E0005`.

0 commit comments

Comments
 (0)
This repository has been archived.