Prevent spurious unreachable pattern lints

Means you'll get more `non-exhaustive` patterns
This commit is contained in:
Oli Scherer 2023-09-18 15:54:23 +00:00
parent 71704c4f84
commit d1fd11f3f9
14 changed files with 164 additions and 198 deletions

View File

@ -180,23 +180,26 @@ impl<'tcx> ConstToPat<'tcx> {
if let Some(non_sm_ty) = structural {
if !self.type_has_partial_eq_impl(cv.ty()) {
if let ty::Adt(def, ..) = non_sm_ty.kind() {
let e = if let ty::Adt(def, ..) = non_sm_ty.kind() {
if def.is_union() {
let err = UnionPattern { span: self.span };
self.tcx().sess.emit_err(err);
self.tcx().sess.emit_err(err)
} else {
// fatal avoids ICE from resolution of nonexistent method (rare case).
self.tcx()
.sess
.emit_fatal(TypeNotStructural { span: self.span, non_sm_ty });
.emit_fatal(TypeNotStructural { span: self.span, non_sm_ty })
}
} else {
let err = InvalidPattern { span: self.span, non_sm_ty };
self.tcx().sess.emit_err(err);
}
self.tcx().sess.emit_err(err)
};
// All branches above emitted an error. Don't print any more lints.
// The pattern we return is irrelevant since we errored.
return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild });
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
let kind = PatKind::Constant {
value: mir::Const::Ty(ty::Const::new_error(self.tcx(), e, cv.ty())),
};
return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
} else if !self.saw_const_match_lint.get() {
if let Some(mir_structural_match_violation) = mir_structural_match_violation {
match non_sm_ty.kind() {
@ -346,17 +349,17 @@ impl<'tcx> ConstToPat<'tcx> {
}
ty::FnDef(..) => {
self.saw_const_match_error.set(true);
tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
let e = tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) }
}
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty: ty };
tcx.sess.emit_err(err);
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
let e = tcx.sess.emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) }
}
ty::Adt(adt_def, args) if adt_def.is_enum() => {
let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
@ -427,14 +430,20 @@ impl<'tcx> ConstToPat<'tcx> {
}
return Err(FallbackToOpaqueConst);
} else {
if !self.saw_const_match_error.get() {
if self.saw_const_match_error.get() {
// We already errored. Signal that in the pattern, so that follow up errors can be silenced.
PatKind::Constant {
value: mir::Const::Ty(ty::Const::new_misc_error(tcx, ty)),
}
} else {
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
tcx.sess.emit_err(err);
let e = tcx.sess.emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
PatKind::Constant {
value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)),
}
}
tcx.sess.delay_span_bug(span, "`saw_const_match_error` set but no error?");
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
}
}
// All other references are converted into deref patterns and then recursively
@ -443,11 +452,11 @@ impl<'tcx> ConstToPat<'tcx> {
_ => {
if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() {
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
tcx.sess.emit_err(err);
// FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
let e = tcx.sess.emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
PatKind::Constant {
value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)),
}
} else {
let old = self.behind_reference.replace(true);
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
@ -476,9 +485,9 @@ impl<'tcx> ConstToPat<'tcx> {
_ => {
self.saw_const_match_error.set(true);
let err = InvalidPattern { span, non_sm_ty: ty };
tcx.sess.emit_err(err);
// We errored, so the pattern we generate is irrelevant.
PatKind::Wild
let e = tcx.sess.emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced.
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) }
}
};

View File

@ -7,5 +7,17 @@ LL | WHAT_A_TYPE => 0,
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: aborting due to previous error
error[E0015]: cannot match on `TypeId` in constant functions
--> $DIR/typeid-equality-by-subtyping.rs:18:9
|
LL | WHAT_A_TYPE => 0,
| ^^^^^^^^^^^
|
= note: `TypeId` cannot be compared in compile-time, and therefore cannot be used in `match`es
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -12,6 +12,5 @@ fn main() {
FOO => {},
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
_ => {}
//~^ ERROR unreachable pattern
}
}

View File

@ -7,20 +7,5 @@ LL | FOO => {},
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
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
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error

View File

@ -7,7 +7,7 @@ struct T;
fn main() {
const C: &S = &S;
match C {
match C { //~ ERROR: non-exhaustive patterns: `&_` not covered
C => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
}

View File

@ -7,5 +7,24 @@ LL | C => {}
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/match_ice.rs:10:11
|
LL | match C {
| ^ pattern `&_` not covered
|
note: `S` defined here
--> $DIR/match_ice.rs:3:8
|
LL | struct S;
| ^
= note: the matched value is of type `&S`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ C => {},
LL + &_ => todo!()
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0004`.

View File

@ -2,7 +2,7 @@ const F: &'static dyn PartialEq<u32> = &7u32;
fn main() {
let a: &dyn PartialEq<u32> = &7u32;
match a {
match a { //~ ERROR: non-exhaustive patterns: `&_` not covered
F => panic!(), //~ ERROR: `dyn PartialEq<u32>` cannot be used in patterns
}
}

View File

@ -4,5 +4,18 @@ error: `dyn PartialEq<u32>` cannot be used in patterns
LL | F => panic!(),
| ^
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/issue-72565.rs:5:11
|
LL | match a {
| ^ pattern `&_` not covered
|
= note: the matched value is of type `&dyn PartialEq<u32>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL | F => panic!(), &_ => todo!(),
| +++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0004`.

View File

@ -5,10 +5,10 @@
#![feature(inline_const_pat)]
fn main() {
match loop {} {
match loop {} { //~ ERROR: non-exhaustive patterns: `_` not covered
const { || {} } => {}, //~ ERROR cannot be used in patterns
}
match loop {} {
match loop {} { //~ ERROR: non-exhaustive patterns: `_` not covered
const { async {} } => {}, //~ ERROR cannot be used in patterns
}
}

View File

@ -10,5 +10,30 @@ error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be
LL | const { async {} } => {},
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/non-structural-match-types.rs:8:11
|
LL | match loop {} {
| ^^^^^^^ pattern `_` not covered
|
= note: the matched value is of type `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL | const { || {} } => {}, _ => todo!(),
| ++++++++++++++
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/non-structural-match-types.rs:11:11
|
LL | match loop {} {
| ^^^^^^^ pattern `_` not covered
|
= note: the matched value is of type `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL | const { async {} } => {}, _ => todo!(),
| ++++++++++++++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0004`.

View File

@ -30,15 +30,13 @@ fn main() {
match FOO {
FOO => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
_ => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
_ => {}
}
match FOO_REF {
FOO_REF => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
Foo(_) => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
Foo(_) => {}
}
// This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071)
@ -51,9 +49,8 @@ fn main() {
match BAR {
Bar => {}
BAR => {} // should not be emitting unreachable warning
BAR => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
//~| ERROR unreachable pattern
_ => {}
//~^ ERROR unreachable pattern
}
@ -61,8 +58,7 @@ fn main() {
match BAR {
BAR => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
Bar => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
Bar => {}
_ => {}
//~^ ERROR unreachable pattern
}
@ -70,20 +66,16 @@ fn main() {
match BAR {
BAR => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
BAR => {} // should not be emitting unreachable warning
BAR => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
//~| ERROR unreachable pattern
_ => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
_ => {}
}
match BAZ {
BAZ => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
Baz::Baz1 => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
Baz::Baz1 => {}
_ => {}
//~^ ERROR unreachable pattern
}
match BAZ {
@ -91,16 +83,13 @@ fn main() {
BAZ => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
_ => {}
//~^ ERROR unreachable pattern
}
match BAZ {
BAZ => {}
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
Baz::Baz2 => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
_ => {} // should not be emitting unreachable warning
//~^ ERROR unreachable pattern
Baz::Baz2 => {}
_ => {}
}
type Quux = fn(usize, usize) -> usize;

View File

@ -8,7 +8,7 @@ LL | FOO => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:38:9
--> $DIR/consts-opaque.rs:37:9
|
LL | FOO_REF => {}
| ^^^^^^^
@ -17,7 +17,7 @@ LL | FOO_REF => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:46:9
--> $DIR/consts-opaque.rs:44:9
|
LL | FOO_REF_REF => {}
| ^^^^^^^^^^^
@ -29,16 +29,7 @@ LL | FOO_REF_REF => {}
= note: `#[warn(indirect_structural_match)]` on by default
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:54:9
|
LL | BAR => {} // should not be emitting unreachable warning
| ^^^
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:62:9
--> $DIR/consts-opaque.rs:52:9
|
LL | BAR => {}
| ^^^
@ -47,7 +38,7 @@ LL | BAR => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:71:9
--> $DIR/consts-opaque.rs:59:9
|
LL | BAR => {}
| ^^^
@ -56,16 +47,25 @@ LL | BAR => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:73:9
--> $DIR/consts-opaque.rs:67:9
|
LL | BAR => {} // should not be emitting unreachable warning
LL | BAR => {}
| ^^^
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:69:9
|
LL | BAR => {}
| ^^^
|
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:81:9
--> $DIR/consts-opaque.rs:75:9
|
LL | BAZ => {}
| ^^^
@ -74,7 +74,7 @@ LL | BAZ => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:91:9
--> $DIR/consts-opaque.rs:83:9
|
LL | BAZ => {}
| ^^^
@ -83,7 +83,7 @@ LL | BAZ => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:98:9
--> $DIR/consts-opaque.rs:89:9
|
LL | BAZ => {}
| ^^^
@ -92,12 +92,12 @@ LL | BAZ => {}
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: unreachable pattern
--> $DIR/consts-opaque.rs:33:9
--> $DIR/consts-opaque.rs:54:9
|
LL | FOO => {}
LL | Bar => {}
| --- matches any value
LL |
LL | _ => {} // should not be emitting unreachable warning
...
LL | _ => {}
| ^ unreachable pattern
|
note: the lint level is defined here
@ -107,120 +107,21 @@ LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
--> $DIR/consts-opaque.rs:40:9
|
LL | FOO_REF => {}
| ------- matches any value
LL |
LL | Foo(_) => {} // should not be emitting unreachable warning
| ^^^^^^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:54:9
--> $DIR/consts-opaque.rs:62:9
|
LL | Bar => {}
| --- matches any value
LL | BAR => {} // should not be emitting unreachable warning
| ^^^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:57:9
|
LL | Bar => {}
| --- matches any value
...
LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:64:9
|
LL | BAR => {}
| --- matches any value
LL |
LL | Bar => {} // should not be emitting unreachable warning
| ^^^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:66:9
|
LL | BAR => {}
| --- matches any value
...
LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:73:9
|
LL | BAR => {}
| --- matches any value
LL |
LL | BAR => {} // should not be emitting unreachable warning
| ^^^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:76:9
|
LL | BAR => {}
| --- matches any value
...
LL | _ => {} // should not be emitting unreachable warning
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:83: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:85:9
|
LL | BAZ => {}
| --- matches any value
...
LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:93:9
|
LL | BAZ => {}
| --- matches any value
LL |
LL | _ => {}
| ^ unreachable pattern
error: unreachable pattern
--> $DIR/consts-opaque.rs:100: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:102:9
|
LL | BAZ => {}
| --- matches any value
...
LL | _ => {} // should not be emitting unreachable warning
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered
--> $DIR/consts-opaque.rs:135:11
--> $DIR/consts-opaque.rs:124:11
|
LL | match WRAPQUUX {
| ^^^^^^^^ pattern `Wrap(_)` not covered
|
note: `Wrap<fn(usize, usize) -> usize>` defined here
--> $DIR/consts-opaque.rs:117:12
--> $DIR/consts-opaque.rs:106:12
|
LL | struct Wrap<T>(T);
| ^^^^
@ -231,6 +132,6 @@ LL ~ WRAPQUUX => {},
LL + Wrap(_) => todo!()
|
error: aborting due to 23 previous errors; 1 warning emitted
error: aborting due to 12 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0004`.

View File

@ -12,7 +12,7 @@ struct B(i32);
fn main() {
const FOO: [B; 1] = [B(0)];
match [B(1)] {
match [B(1)] { //~ ERROR: non-exhaustive patterns: `[_]` not covered
FOO => { }
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
}

View File

@ -7,5 +7,19 @@ LL | FOO => { }
= note: the traits must be derived, manual `impl`s are not sufficient
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `[_]` not covered
--> $DIR/match-nonempty-array-forbidden-without-eq.rs:15:11
|
LL | match [B(1)] {
| ^^^^^^ pattern `[_]` not covered
|
= note: the matched value is of type `[B; 1]`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ FOO => { },
LL + [_] => todo!()
|
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0004`.