Skip to content

Commit 85ff414

Browse files
committed
Prevent spurious unreachable pattern lints
Means you'll get more `non-exhaustive` patterns
1 parent de68911 commit 85ff414

File tree

14 files changed

+150
-180
lines changed

14 files changed

+150
-180
lines changed

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

+28-15
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,15 @@ impl<'tcx> ConstToPat<'tcx> {
191191
}
192192
} else {
193193
let err = InvalidPattern { span: self.span, non_sm_ty };
194-
self.tcx().sess.emit_err(err);
195-
return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild });
194+
let e = self.tcx().sess.emit_err(err);
195+
let kind = PatKind::Constant {
196+
value: mir::ConstantKind::Ty(ty::Const::new_error(
197+
self.tcx(),
198+
e,
199+
cv.ty(),
200+
)),
201+
};
202+
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
196203
}
197204
} else if !self.saw_const_match_lint.get() {
198205
if let Some(mir_structural_match_violation) = mir_structural_match_violation {
@@ -327,15 +334,15 @@ impl<'tcx> ConstToPat<'tcx> {
327334
}
328335
ty::FnDef(..) => {
329336
self.saw_const_match_error.set(true);
330-
tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
331-
PatKind::Wild
337+
let e = tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
338+
PatKind::Constant { value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)) }
332339
}
333340
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
334341
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
335342
self.saw_const_match_error.set(true);
336343
let err = TypeNotStructural { span, non_sm_ty: ty };
337-
tcx.sess.emit_err(err);
338-
PatKind::Wild
344+
let e = tcx.sess.emit_err(err);
345+
PatKind::Constant { value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)) }
339346
}
340347
ty::Adt(adt_def, args) if adt_def.is_enum() => {
341348
let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
@@ -406,12 +413,18 @@ impl<'tcx> ConstToPat<'tcx> {
406413
}
407414
return Err(FallbackToConstRef);
408415
} else {
409-
if !self.saw_const_match_error.get() {
416+
if self.saw_const_match_error.get() {
417+
PatKind::Constant {
418+
value: mir::ConstantKind::Ty(ty::Const::new_misc_error(tcx, ty)),
419+
}
420+
} else {
410421
self.saw_const_match_error.set(true);
411422
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
412-
tcx.sess.emit_err(err);
423+
let e = tcx.sess.emit_err(err);
424+
PatKind::Constant {
425+
value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)),
426+
}
413427
}
414-
PatKind::Wild
415428
}
416429
}
417430
// All other references are converted into deref patterns and then recursively
@@ -420,10 +433,10 @@ impl<'tcx> ConstToPat<'tcx> {
420433
_ => {
421434
if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() {
422435
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
423-
tcx.sess.emit_err(err);
424-
425-
// FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
426-
PatKind::Wild
436+
let e = tcx.sess.emit_err(err);
437+
PatKind::Constant {
438+
value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)),
439+
}
427440
} else {
428441
let old = self.behind_reference.replace(true);
429442
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
@@ -452,8 +465,8 @@ impl<'tcx> ConstToPat<'tcx> {
452465
_ => {
453466
self.saw_const_match_error.set(true);
454467
let err = InvalidPattern { span, non_sm_ty: ty };
455-
tcx.sess.emit_err(err);
456-
PatKind::Wild
468+
let e = tcx.sess.emit_err(err);
469+
PatKind::Constant { value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)) }
457470
}
458471
};
459472

tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,17 @@ LL | WHAT_A_TYPE => 0,
77
= note: the traits must be derived, manual `impl`s are not sufficient
88
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
99

10-
error: aborting due to previous error
10+
error[E0015]: cannot match on `TypeId` in constant functions
11+
--> $DIR/typeid-equality-by-subtyping.rs:18:9
12+
|
13+
LL | WHAT_A_TYPE => 0,
14+
| ^^^^^^^^^^^
15+
|
16+
= note: `TypeId` cannot be compared in compile-time, and therefore cannot be used in `match`es
17+
note: impl defined here, but it is not `const`
18+
--> $SRC_DIR/core/src/any.rs:LL:COL
19+
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
20+
21+
error: aborting due to 2 previous errors
1122

23+
For more information about this error, try `rustc --explain E0015`.

tests/ui/consts/const_in_pattern/issue-78057.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@ fn main() {
1212
FOO => {},
1313
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
1414
_ => {}
15-
//~^ ERROR unreachable pattern
1615
}
1716
}

tests/ui/consts/const_in_pattern/issue-78057.stderr

+1-16
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,5 @@ LL | FOO => {},
77
= note: the traits must be derived, manual `impl`s are not sufficient
88
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
99

10-
error: unreachable pattern
11-
--> $DIR/issue-78057.rs:14:9
12-
|
13-
LL | FOO => {},
14-
| --- matches any value
15-
LL |
16-
LL | _ => {}
17-
| ^ unreachable pattern
18-
|
19-
note: the lint level is defined here
20-
--> $DIR/issue-78057.rs:1:9
21-
|
22-
LL | #![deny(unreachable_patterns)]
23-
| ^^^^^^^^^^^^^^^^^^^^
24-
25-
error: aborting due to 2 previous errors
10+
error: aborting due to previous error
2611

tests/ui/consts/match_ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct T;
77

88
fn main() {
99
const C: &S = &S;
10-
match C {
10+
match C { //~ ERROR: non-exhaustive patterns: `&_` not covered
1111
C => {}
1212
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
1313
}

tests/ui/consts/match_ice.stderr

+20-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,24 @@ LL | C => {}
77
= note: the traits must be derived, manual `impl`s are not sufficient
88
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
99

10-
error: aborting due to previous error
10+
error[E0004]: non-exhaustive patterns: `&_` not covered
11+
--> $DIR/match_ice.rs:10:11
12+
|
13+
LL | match C {
14+
| ^ pattern `&_` not covered
15+
|
16+
note: `S` defined here
17+
--> $DIR/match_ice.rs:3:8
18+
|
19+
LL | struct S;
20+
| ^
21+
= note: the matched value is of type `&S`
22+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
23+
|
24+
LL ~ C => {},
25+
LL + &_ => todo!()
26+
|
27+
28+
error: aborting due to 2 previous errors
1129

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

tests/ui/pattern/issue-72565.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const F: &'static dyn PartialEq<u32> = &7u32;
22

33
fn main() {
44
let a: &dyn PartialEq<u32> = &7u32;
5-
match a {
5+
match a { //~ ERROR: non-exhaustive patterns: `&_` not covered
66
F => panic!(), //~ ERROR: `dyn PartialEq<u32>` cannot be used in patterns
77
}
88
}

tests/ui/pattern/issue-72565.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,18 @@ error: `dyn PartialEq<u32>` cannot be used in patterns
44
LL | F => panic!(),
55
| ^
66

7-
error: aborting due to previous error
7+
error[E0004]: non-exhaustive patterns: `&_` not covered
8+
--> $DIR/issue-72565.rs:5:11
9+
|
10+
LL | match a {
11+
| ^ pattern `&_` not covered
12+
|
13+
= note: the matched value is of type `&dyn PartialEq<u32>`
14+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
15+
|
16+
LL | F => panic!(), &_ => todo!(),
17+
| +++++++++++++++
18+
19+
error: aborting due to 2 previous errors
820

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

tests/ui/pattern/non-structural-match-types.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
#![feature(inline_const_pat)]
66

77
fn main() {
8-
match loop {} {
8+
match loop {} { //~ ERROR: non-exhaustive patterns: `_` not covered
99
const { || {} } => {}, //~ ERROR cannot be used in patterns
1010
}
11-
match loop {} {
11+
match loop {} { //~ ERROR: non-exhaustive patterns: `_` not covered
1212
const { async {} } => {}, //~ ERROR cannot be used in patterns
1313
}
1414
}

tests/ui/pattern/non-structural-match-types.stderr

+26-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,30 @@ error: `[async block@$DIR/non-structural-match-types.rs:12:17: 12:25]` cannot be
1010
LL | const { async {} } => {},
1111
| ^^^^^^^^^^^^^^^^^^
1212

13-
error: aborting due to 2 previous errors
13+
error[E0004]: non-exhaustive patterns: `_` not covered
14+
--> $DIR/non-structural-match-types.rs:8:11
15+
|
16+
LL | match loop {} {
17+
| ^^^^^^^ pattern `_` not covered
18+
|
19+
= note: the matched value is of type `[closure@$DIR/non-structural-match-types.rs:9:17: 9:19]`
20+
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+
|
22+
LL | const { || {} } => {}, _ => todo!(),
23+
| ++++++++++++++
24+
25+
error[E0004]: non-exhaustive patterns: `_` not covered
26+
--> $DIR/non-structural-match-types.rs:11:11
27+
|
28+
LL | match loop {} {
29+
| ^^^^^^^ pattern `_` not covered
30+
|
31+
= note: the matched value is of type `[async block@$DIR/non-structural-match-types.rs:12:17: 12:25]`
32+
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
33+
|
34+
LL | const { async {} } => {}, _ => todo!(),
35+
| ++++++++++++++
36+
37+
error: aborting due to 4 previous errors
1438

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

tests/ui/pattern/usefulness/consts-opaque.rs

+9-20
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,13 @@ fn main() {
3030
match FOO {
3131
FOO => {}
3232
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
33-
_ => {} // should not be emitting unreachable warning
34-
//~^ ERROR unreachable pattern
33+
_ => {}
3534
}
3635

3736
match FOO_REF {
3837
FOO_REF => {}
3938
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
40-
Foo(_) => {} // should not be emitting unreachable warning
41-
//~^ ERROR unreachable pattern
39+
Foo(_) => {}
4240
}
4341

4442
// This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071)
@@ -51,56 +49,47 @@ fn main() {
5149

5250
match BAR {
5351
Bar => {}
54-
BAR => {} // should not be emitting unreachable warning
52+
BAR => {}
5553
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
56-
//~| ERROR unreachable pattern
5754
_ => {}
5855
//~^ ERROR unreachable pattern
5956
}
6057

6158
match BAR {
6259
BAR => {}
6360
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
64-
Bar => {} // should not be emitting unreachable warning
65-
//~^ ERROR unreachable pattern
61+
Bar => {}
6662
_ => {}
6763
//~^ ERROR unreachable pattern
6864
}
6965

7066
match BAR {
7167
BAR => {}
7268
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
73-
BAR => {} // should not be emitting unreachable warning
69+
BAR => {}
7470
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
75-
//~| ERROR unreachable pattern
76-
_ => {} // should not be emitting unreachable warning
77-
//~^ ERROR unreachable pattern
71+
_ => {}
7872
}
7973

8074
match BAZ {
8175
BAZ => {}
8276
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
83-
Baz::Baz1 => {} // should not be emitting unreachable warning
84-
//~^ ERROR unreachable pattern
77+
Baz::Baz1 => {}
8578
_ => {}
86-
//~^ ERROR unreachable pattern
8779
}
8880

8981
match BAZ {
9082
Baz::Baz1 => {}
9183
BAZ => {}
9284
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
9385
_ => {}
94-
//~^ ERROR unreachable pattern
9586
}
9687

9788
match BAZ {
9889
BAZ => {}
9990
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
100-
Baz::Baz2 => {} // should not be emitting unreachable warning
101-
//~^ ERROR unreachable pattern
102-
_ => {} // should not be emitting unreachable warning
103-
//~^ ERROR unreachable pattern
91+
Baz::Baz2 => {}
92+
_ => {}
10493
}
10594

10695
type Quux = fn(usize, usize) -> usize;

0 commit comments

Comments
 (0)