Skip to content

Commit

Permalink
Prevent spurious unreachable pattern lints
Browse files Browse the repository at this point in the history
Means you'll get more `non-exhaustive` patterns
  • Loading branch information
oli-obk committed Sep 22, 2023
1 parent 8759de0 commit b3c4f19
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 180 deletions.
43 changes: 28 additions & 15 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,15 @@ impl<'tcx> ConstToPat<'tcx> {
}
} else {
let err = InvalidPattern { span: self.span, non_sm_ty };
self.tcx().sess.emit_err(err);
return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild });
let e = self.tcx().sess.emit_err(err);
let kind = PatKind::Constant {
value: mir::ConstantKind::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 {
Expand Down Expand Up @@ -327,15 +334,15 @@ impl<'tcx> ConstToPat<'tcx> {
}
ty::FnDef(..) => {
self.saw_const_match_error.set(true);
tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
PatKind::Wild
let e = tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
PatKind::Constant { value: mir::ConstantKind::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);
PatKind::Wild
let e = tcx.sess.emit_err(err);
PatKind::Constant { value: mir::ConstantKind::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();
Expand Down Expand Up @@ -406,12 +413,18 @@ impl<'tcx> ConstToPat<'tcx> {
}
return Err(FallbackToConstRef);
} else {
if !self.saw_const_match_error.get() {
if self.saw_const_match_error.get() {
PatKind::Constant {
value: mir::ConstantKind::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);
PatKind::Constant {
value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)),
}
}
PatKind::Wild
}
}
// All other references are converted into deref patterns and then recursively
Expand All @@ -420,10 +433,10 @@ 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.
PatKind::Wild
let e = tcx.sess.emit_err(err);
PatKind::Constant {
value: mir::ConstantKind::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
Expand Down Expand Up @@ -452,8 +465,8 @@ impl<'tcx> ConstToPat<'tcx> {
_ => {
self.saw_const_match_error.set(true);
let err = InvalidPattern { span, non_sm_ty: ty };
tcx.sess.emit_err(err);
PatKind::Wild
let e = tcx.sess.emit_err(err);
PatKind::Constant { value: mir::ConstantKind::Ty(ty::Const::new_error(tcx, e, ty)) }
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
1 change: 0 additions & 1 deletion tests/ui/consts/const_in_pattern/issue-78057.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ fn main() {
FOO => {},
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
_ => {}
//~^ ERROR unreachable pattern
}
}
17 changes: 1 addition & 16 deletions tests/ui/consts/const_in_pattern/issue-78057.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

2 changes: 1 addition & 1 deletion tests/ui/consts/match_ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]`
}
Expand Down
21 changes: 20 additions & 1 deletion tests/ui/consts/match_ice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
2 changes: 1 addition & 1 deletion tests/ui/pattern/issue-72565.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
15 changes: 14 additions & 1 deletion tests/ui/pattern/issue-72565.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
4 changes: 2 additions & 2 deletions tests/ui/pattern/non-structural-match-types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
27 changes: 26 additions & 1 deletion tests/ui/pattern/non-structural-match-types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
29 changes: 9 additions & 20 deletions tests/ui/pattern/usefulness/consts-opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -51,56 +49,47 @@ 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
}

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
}

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 {
Baz::Baz1 => {}
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;
Expand Down
Loading

0 comments on commit b3c4f19

Please sign in to comment.