Implement destructuring for all aggregates and for references
This commit is contained in:
parent
34c62e0abc
commit
b2532a8730
|
@ -93,8 +93,7 @@ pub(crate) fn deref_const<'tcx>(
|
||||||
MemPlaceMeta::None => mplace.layout.ty,
|
MemPlaceMeta::None => mplace.layout.ty,
|
||||||
MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
|
MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
|
||||||
// In case of unsized types, figure out the real type behind.
|
// In case of unsized types, figure out the real type behind.
|
||||||
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind {
|
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
|
||||||
ty::Dynamic(..) => ecx.read_drop_type_from_vtable(scalar).unwrap().1,
|
|
||||||
ty::Str => bug!("there's no sized equivalent of a `str`"),
|
ty::Str => bug!("there's no sized equivalent of a `str`"),
|
||||||
ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
|
ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
|
||||||
_ => bug!(
|
_ => bug!(
|
||||||
|
|
|
@ -409,7 +409,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
let deref_ty = match *ty.kind() {
|
let deref_ty = match *ty.kind() {
|
||||||
ty::Ref(_, deref_ty, _) => deref_ty,
|
ty::Ref(_, deref_ty, _) => deref_ty,
|
||||||
_ => bug!("non_scalar_compare called on non-reference type: {}", ty),
|
_ => {
|
||||||
|
trace!("non_scalar_compare called on non-reference type: {}", ty);
|
||||||
|
// Backcompat hack: due to non-structural matches not being a hard error, we can
|
||||||
|
// reach this for types that have manual `Eq` or `PartialEq` impls.
|
||||||
|
assert!(!ty.is_structural_eq_shallow(self.hir.tcx()));
|
||||||
|
let ref_ty = self.hir.tcx().mk_imm_ref(self.hir.tcx().lifetimes.re_erased, ty);
|
||||||
|
// let y = &place;
|
||||||
|
let y = self.temp(ref_ty, source_info.span);
|
||||||
|
self.cfg.push_assign(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
y,
|
||||||
|
Rvalue::Ref(self.hir.tcx().lifetimes.re_erased, BorrowKind::Shared, place),
|
||||||
|
);
|
||||||
|
val = Operand::Move(y);
|
||||||
|
// let temp = expect;
|
||||||
|
let temp = self.temp(ty, source_info.span);
|
||||||
|
self.cfg.push_assign(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
temp,
|
||||||
|
Rvalue::Use(expect),
|
||||||
|
);
|
||||||
|
// reftemp = &temp;
|
||||||
|
let reftemp = self.temp(ref_ty, source_info.span);
|
||||||
|
self.cfg.push_assign(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
reftemp,
|
||||||
|
Rvalue::Ref(self.hir.tcx().lifetimes.re_erased, BorrowKind::Shared, temp),
|
||||||
|
);
|
||||||
|
expect = Operand::Move(reftemp);
|
||||||
|
ty
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let eq_def_id = self.hir.tcx().require_lang_item(LangItem::PartialEq, None);
|
let eq_def_id = self.hir.tcx().require_lang_item(LangItem::PartialEq, None);
|
||||||
|
|
|
@ -28,10 +28,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
|
debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
|
||||||
debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
|
debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
|
||||||
|
|
||||||
self.tcx.infer_ctxt().enter(|infcx| {
|
let pat = self.tcx.infer_ctxt().enter(|infcx| {
|
||||||
let mut convert = ConstToPat::new(self, id, span, infcx);
|
let mut convert = ConstToPat::new(self, id, span, infcx);
|
||||||
convert.to_pat(cv, mir_structural_match_violation)
|
convert.to_pat(cv, mir_structural_match_violation)
|
||||||
})
|
});
|
||||||
|
|
||||||
|
debug!("const_to_pat: pat={:?}", pat);
|
||||||
|
pat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +48,10 @@ struct ConstToPat<'a, 'tcx> {
|
||||||
// value.
|
// value.
|
||||||
saw_const_match_error: Cell<bool>,
|
saw_const_match_error: Cell<bool>,
|
||||||
|
|
||||||
|
// For backcompat we need to keep allowing non-structurally-eq types behind references.
|
||||||
|
// See also all the `cant-hide-behind` tests.
|
||||||
|
behind_reference: Cell<bool>,
|
||||||
|
|
||||||
// inference context used for checking `T: Structural` bounds.
|
// inference context used for checking `T: Structural` bounds.
|
||||||
infcx: InferCtxt<'a, 'tcx>,
|
infcx: InferCtxt<'a, 'tcx>,
|
||||||
|
|
||||||
|
@ -65,6 +72,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
param_env: pat_ctxt.param_env,
|
param_env: pat_ctxt.param_env,
|
||||||
include_lint_checks: pat_ctxt.include_lint_checks,
|
include_lint_checks: pat_ctxt.include_lint_checks,
|
||||||
saw_const_match_error: Cell::new(false),
|
saw_const_match_error: Cell::new(false),
|
||||||
|
behind_reference: Cell::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +241,18 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
tcx.sess.span_err(span, "cannot use unions in constant patterns");
|
tcx.sess.span_err(span, "cannot use unions in constant patterns");
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
// keep old code until future-compat upgraded to errors.
|
// If the type is not structurally comparable, just emit the constant directly,
|
||||||
|
// causing the pattern match code to treat it opaquely.
|
||||||
|
// FIXME: This code doesn't emit errors itself, the caller emits the errors.
|
||||||
|
// So instead of specific errors, you just get blanket errors about the whole
|
||||||
|
// const type. See
|
||||||
|
// https://github.com/rust-lang/rust/pull/70743#discussion_r404701963 for
|
||||||
|
// details.
|
||||||
|
// Backwards compatibility hack because we can't cause hard errors on these
|
||||||
|
// types, so we compare them via `PartialEq::eq` at runtime.
|
||||||
|
ty::Adt(..) if !self.type_marked_structural(cv.ty) && self.behind_reference.get() => {
|
||||||
|
PatKind::Constant { value: cv }
|
||||||
|
}
|
||||||
ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty) => {
|
ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty) => {
|
||||||
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, cv.ty);
|
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, cv.ty);
|
||||||
let path = tcx.def_path_str(adt_def.did);
|
let path = tcx.def_path_str(adt_def.did);
|
||||||
|
@ -246,28 +265,6 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
tcx.sess.span_err(span, &msg);
|
tcx.sess.span_err(span, &msg);
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
// keep old code until future-compat upgraded to errors.
|
|
||||||
ty::Ref(_, adt_ty, _) if adt_ty.is_adt() && !self.type_marked_structural(adt_ty) => {
|
|
||||||
let adt_def =
|
|
||||||
if let ty::Adt(adt_def, _) = adt_ty.kind() { adt_def } else { unreachable!() };
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"adt_def {:?} has !type_marked_structural for adt_ty: {:?}",
|
|
||||||
adt_def, adt_ty
|
|
||||||
);
|
|
||||||
|
|
||||||
// HACK(estebank): Side-step ICE #53708, but anything other than erroring here
|
|
||||||
// would be wrong. Returnging `PatKind::Wild` is not technically correct.
|
|
||||||
let path = tcx.def_path_str(adt_def.did);
|
|
||||||
let msg = format!(
|
|
||||||
"to use a constant of type `{}` in a pattern, \
|
|
||||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
|
||||||
path, path,
|
|
||||||
);
|
|
||||||
self.saw_const_match_error.set(true);
|
|
||||||
tcx.sess.span_err(span, &msg);
|
|
||||||
PatKind::Wild
|
|
||||||
}
|
|
||||||
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
||||||
let destructured = tcx.destructure_const(param_env.and(cv));
|
let destructured = tcx.destructure_const(param_env.and(cv));
|
||||||
PatKind::Variant {
|
PatKind::Variant {
|
||||||
|
@ -293,7 +290,68 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
slice: None,
|
slice: None,
|
||||||
suffix: Vec::new(),
|
suffix: Vec::new(),
|
||||||
},
|
},
|
||||||
_ => PatKind::Constant { value: cv },
|
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
|
||||||
|
// These are not allowed and will error elsewhere anyway.
|
||||||
|
ty::Dynamic(..) => PatKind::Constant { value: cv },
|
||||||
|
// `&str` and `&[u8]` are represented as `ConstValue::Slice`, let's keep using this
|
||||||
|
// optimization for now.
|
||||||
|
ty::Str => PatKind::Constant { value: cv },
|
||||||
|
ty::Slice(elem_ty) if elem_ty == tcx.types.u8 => PatKind::Constant { value: cv },
|
||||||
|
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
|
||||||
|
// matching against references, you can only use byte string literals.
|
||||||
|
// FIXME: clean this up, likely by permitting array patterns when matching on slices
|
||||||
|
ty::Array(elem_ty, _) if elem_ty == tcx.types.u8 => PatKind::Constant { value: cv },
|
||||||
|
// Cannot merge this with the catch all branch below, because the `const_deref`
|
||||||
|
// changes the type from slice to array, and slice patterns behave differently from
|
||||||
|
// array patterns.
|
||||||
|
ty::Slice(..) => {
|
||||||
|
let old = self.behind_reference.replace(true);
|
||||||
|
let array = tcx.deref_const(self.param_env.and(cv));
|
||||||
|
let val = PatKind::Deref {
|
||||||
|
subpattern: Pat {
|
||||||
|
kind: Box::new(PatKind::Slice {
|
||||||
|
prefix: tcx
|
||||||
|
.destructure_const(param_env.and(array))
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.map(|val| self.recur(val))
|
||||||
|
.collect(),
|
||||||
|
slice: None,
|
||||||
|
suffix: vec![],
|
||||||
|
}),
|
||||||
|
span,
|
||||||
|
ty: pointee_ty,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.behind_reference.set(old);
|
||||||
|
val
|
||||||
|
}
|
||||||
|
// Backwards compatibility hack. Don't take away the reference, since
|
||||||
|
// `PartialEq::eq` takes a reference, this makes the rest of the matching logic
|
||||||
|
// simpler.
|
||||||
|
ty::Adt(..) if !self.type_marked_structural(pointee_ty) => {
|
||||||
|
PatKind::Constant { value: cv }
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let old = self.behind_reference.replace(true);
|
||||||
|
let val = PatKind::Deref {
|
||||||
|
subpattern: self.recur(tcx.deref_const(self.param_env.and(cv))),
|
||||||
|
};
|
||||||
|
self.behind_reference.set(old);
|
||||||
|
val
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
|
||||||
|
PatKind::Constant { value: cv }
|
||||||
|
}
|
||||||
|
// FIXME: these can have very suprising behaviour where optimization levels or other
|
||||||
|
// compilation choices change the runtime behaviour of the match.
|
||||||
|
// See https://github.com/rust-lang/rust/issues/70861 for examples.
|
||||||
|
ty::FnPtr(..) | ty::RawPtr(..) => PatKind::Constant { value: cv },
|
||||||
|
_ => {
|
||||||
|
tcx.sess.delay_span_bug(span, &format!("cannot make a pattern out of {}", cv.ty));
|
||||||
|
PatKind::Wild
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Pat { span, ty: cv.ty, kind: Box::new(kind) }
|
Pat { span, ty: cv.ty, kind: Box::new(kind) }
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub struct OsString {
|
||||||
// `OsStr::from_inner` current implementation relies
|
// `OsStr::from_inner` current implementation relies
|
||||||
// on `OsStr` being layout-compatible with `Slice`.
|
// on `OsStr` being layout-compatible with `Slice`.
|
||||||
// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
|
// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
|
||||||
// Anyway, `OsStr` representation and layout are considered implementation detail, are
|
// Anyway, `OsStr` representation and layout are considered implementation details, are
|
||||||
// not documented and must not be relied upon.
|
// not documented and must not be relied upon.
|
||||||
pub struct OsStr {
|
pub struct OsStr {
|
||||||
inner: Slice,
|
inner: Slice,
|
||||||
|
|
|
@ -19,8 +19,6 @@ pub fn main() {
|
||||||
assert_eq!(y, 2);
|
assert_eq!(y, 2);
|
||||||
let z = match &() {
|
let z = match &() {
|
||||||
ZST => 9,
|
ZST => 9,
|
||||||
// FIXME: this should not be required
|
|
||||||
_ => 42,
|
|
||||||
};
|
};
|
||||||
assert_eq!(z, 9);
|
assert_eq!(z, 9);
|
||||||
let z = match b"" {
|
let z = match b"" {
|
||||||
|
|
|
@ -10,10 +10,9 @@ fn main() {
|
||||||
match C {
|
match C {
|
||||||
C => {}
|
C => {}
|
||||||
//~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
//~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
||||||
//~| ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
|
||||||
}
|
}
|
||||||
const K: &T = &T;
|
const K: &T = &T;
|
||||||
match K { //~ ERROR non-exhaustive patterns: `&T` not covered
|
match K {
|
||||||
K => {}
|
K => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,5 @@ error: to use a constant of type `S` in a pattern, `S` must be annotated with `#
|
||||||
LL | C => {}
|
LL | C => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&T` not covered
|
error: aborting due to previous error
|
||||||
--> $DIR/match_ice.rs:16:11
|
|
||||||
|
|
|
||||||
LL | struct T;
|
|
||||||
| --------- `T` defined here
|
|
||||||
...
|
|
||||||
LL | match K {
|
|
||||||
| ^ pattern `&T` not covered
|
|
||||||
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
|
||||||
= note: the matched value is of type `&T`
|
|
||||||
|
|
||||||
error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
--> $DIR/match_ice.rs:11:9
|
|
||||||
|
|
|
||||||
LL | C => {}
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0004`.
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match b"." as &[u8] {
|
||||||
|
b"." if true => {},
|
||||||
|
b"." => panic!(),
|
||||||
|
b".." => panic!(),
|
||||||
|
b"" => panic!(),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
match b"." as &[u8] {
|
||||||
|
b"." if false => panic!(),
|
||||||
|
b"." => {},
|
||||||
|
b".." => panic!(),
|
||||||
|
b"" => panic!(),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
match b".." as &[u8] {
|
||||||
|
b"." if true => panic!(), // the miscompile caused this arm to be reached
|
||||||
|
b"." => panic!(),
|
||||||
|
b".." => {},
|
||||||
|
b"" => panic!(),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
match b".." as &[u8] {
|
||||||
|
b"." if false => panic!(),
|
||||||
|
b"." => panic!(),
|
||||||
|
b".." => {},
|
||||||
|
b"" => panic!(),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
match b"" as &[u8] {
|
||||||
|
b"." if true => panic!(),
|
||||||
|
b"." => panic!(),
|
||||||
|
b".." => panic!(),
|
||||||
|
b"" => {},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
match b"" as &[u8] {
|
||||||
|
b"." if false => panic!(),
|
||||||
|
b"." => panic!(),
|
||||||
|
b".." => panic!(),
|
||||||
|
b"" => {},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,4 @@
|
||||||
// failure-status: 101
|
// check-pass
|
||||||
// rustc-env:RUST_BACKTRACE=0
|
|
||||||
// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
|
|
||||||
// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"
|
|
||||||
// normalize-stderr-test "/_match.rs:[0-9]+:[0-9]+" -> "/_match.rs:LL:CC"
|
|
||||||
|
|
||||||
// This is a repro test for an ICE in our pattern handling of constants.
|
|
||||||
|
|
||||||
const FOO: &&&u32 = &&&42;
|
const FOO: &&&u32 = &&&42;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', compiler/rustc_mir_build/src/thir/pattern/_match.rs:LL:CC
|
|
||||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
|
||||||
|
|
||||||
error: internal compiler error: unexpected panic
|
|
||||||
|
|
||||||
note: the compiler unexpectedly panicked. this is a bug.
|
|
||||||
|
|
||||||
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
|
|
||||||
|
|
||||||
note: rustc VERSION running on TARGET
|
|
||||||
|
|
||||||
note: compiler flags: FLAGS
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ fn main() {
|
||||||
match &0 {
|
match &0 {
|
||||||
&42 => {}
|
&42 => {}
|
||||||
&FOO => {} //~ ERROR unreachable pattern
|
&FOO => {} //~ ERROR unreachable pattern
|
||||||
BAR => {} // Not detected as unreachable because `try_eval_bits` fails on `BAR`.
|
BAR => {} //~ ERROR unreachable pattern
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,12 @@ error: unreachable pattern
|
||||||
LL | &FOO => {}
|
LL | &FOO => {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to 15 previous errors
|
error: unreachable pattern
|
||||||
|
--> $DIR/exhaustive_integer_patterns.rs:163:9
|
||||||
|
|
|
||||||
|
LL | BAR => {}
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 16 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0004`.
|
For more information about this error, try `rustc --explain E0004`.
|
||||||
|
|
|
@ -6,19 +6,19 @@ fn main() {
|
||||||
match s {
|
match s {
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
[4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
|
[4, 5, 6, 7] => (), //~ ERROR unreachable pattern
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
[4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
|
[4, 5, 6, 7] => (), //~ ERROR unreachable pattern
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
[4, 5, 6, 7] => (),
|
[4, 5, 6, 7] => (),
|
||||||
MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
|
MAGIC_TEST => (), //~ ERROR unreachable pattern
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
const FOO: [u32; 1] = [4];
|
const FOO: [u32; 1] = [4];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/slice-pattern-const-2.rs:28:9
|
--> $DIR/slice-pattern-const-2.rs:9:9
|
||||||
|
|
|
|
||||||
LL | FOO => (),
|
LL | [4, 5, 6, 7] => (),
|
||||||
| ^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/slice-pattern-const-2.rs:1:9
|
--> $DIR/slice-pattern-const-2.rs:1:9
|
||||||
|
@ -10,5 +10,23 @@ note: the lint level is defined here
|
||||||
LL | #![deny(unreachable_patterns)]
|
LL | #![deny(unreachable_patterns)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: unreachable pattern
|
||||||
|
--> $DIR/slice-pattern-const-2.rs:15:9
|
||||||
|
|
|
||||||
|
LL | [4, 5, 6, 7] => (),
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/slice-pattern-const-2.rs:21:9
|
||||||
|
|
|
||||||
|
LL | MAGIC_TEST => (),
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/slice-pattern-const-2.rs:28:9
|
||||||
|
|
|
||||||
|
LL | FOO => (),
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -6,19 +6,19 @@ fn main() {
|
||||||
match s {
|
match s {
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||||
["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
|
["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
|
["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||||
["4", "5", "6", "7"] => (),
|
["4", "5", "6", "7"] => (),
|
||||||
MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
|
MAGIC_TEST => (), //~ ERROR unreachable pattern
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
const FOO: [&str; 1] = ["boo"];
|
const FOO: [&str; 1] = ["boo"];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: unreachable pattern
|
error: unreachable pattern
|
||||||
--> $DIR/slice-pattern-const-3.rs:28:9
|
--> $DIR/slice-pattern-const-3.rs:9:9
|
||||||
|
|
|
|
||||||
LL | FOO => (),
|
LL | ["4", "5", "6", "7"] => (),
|
||||||
| ^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/slice-pattern-const-3.rs:1:9
|
--> $DIR/slice-pattern-const-3.rs:1:9
|
||||||
|
@ -10,5 +10,23 @@ note: the lint level is defined here
|
||||||
LL | #![deny(unreachable_patterns)]
|
LL | #![deny(unreachable_patterns)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: unreachable pattern
|
||||||
|
--> $DIR/slice-pattern-const-3.rs:15:9
|
||||||
|
|
|
||||||
|
LL | ["4", "5", "6", "7"] => (),
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/slice-pattern-const-3.rs:21:9
|
||||||
|
|
|
||||||
|
LL | MAGIC_TEST => (),
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unreachable pattern
|
||||||
|
--> $DIR/slice-pattern-const-3.rs:28:9
|
||||||
|
|
|
||||||
|
LL | FOO => (),
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,15 @@ fn main() {
|
||||||
let s10: &[bool; 10] = &[false; 10];
|
let s10: &[bool; 10] = &[false; 10];
|
||||||
|
|
||||||
match s2 {
|
match s2 {
|
||||||
//~^ ERROR `&[false, _]` not covered
|
//~^ ERROR `&[false, _]` not covered
|
||||||
[true, .., true] => {}
|
[true, .., true] => {}
|
||||||
}
|
}
|
||||||
match s3 {
|
match s3 {
|
||||||
//~^ ERROR `&[false, ..]` not covered
|
//~^ ERROR `&[false, ..]` not covered
|
||||||
[true, .., true] => {}
|
[true, .., true] => {}
|
||||||
}
|
}
|
||||||
match s10 {
|
match s10 {
|
||||||
//~^ ERROR `&[false, ..]` not covered
|
//~^ ERROR `&[false, ..]` not covered
|
||||||
[true, .., true] => {}
|
[true, .., true] => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,58 +23,58 @@ fn main() {
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s2 {
|
match s2 {
|
||||||
//~^ ERROR `&[false, true]` not covered
|
//~^ ERROR `&[false, true]` not covered
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s3 {
|
match s3 {
|
||||||
//~^ ERROR `&[false, .., true]` not covered
|
//~^ ERROR `&[false, .., true]` not covered
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[false, .., true]` not covered
|
//~^ ERROR `&[false, .., true]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, ..]` not covered
|
//~^ ERROR `&[_, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, _, ..]` not covered
|
//~^ ERROR `&[_, _, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[false, ..]` not covered
|
//~^ ERROR `&[false, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[false, _, ..]` not covered
|
//~^ ERROR `&[false, _, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, .., false]` not covered
|
//~^ ERROR `&[_, .., false]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[.., true] => {}
|
[.., true] => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, _, .., true]` not covered
|
//~^ ERROR `&[_, _, .., true]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[_, _] => {}
|
[_, _] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[true, _, .., _]` not covered
|
//~^ ERROR `&[true, _, .., _]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[_, _] => {}
|
[_, _] => {}
|
||||||
|
@ -83,19 +83,43 @@ fn main() {
|
||||||
|
|
||||||
const CONST: &[bool] = &[true];
|
const CONST: &[bool] = &[true];
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[..]` not covered
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
|
&[true] => {}
|
||||||
|
}
|
||||||
|
match s {
|
||||||
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
CONST => {}
|
CONST => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[true]` not covered
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
[] => {},
|
CONST => {}
|
||||||
[false] => {},
|
&[false] => {}
|
||||||
CONST => {},
|
}
|
||||||
|
match s {
|
||||||
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
|
&[false] => {}
|
||||||
|
CONST => {}
|
||||||
|
}
|
||||||
|
match s {
|
||||||
|
//~^ ERROR `&[_, _, ..]` not covered
|
||||||
|
&[] => {}
|
||||||
|
CONST => {}
|
||||||
|
}
|
||||||
|
match s {
|
||||||
|
//~^ ERROR `&[false]` not covered
|
||||||
|
&[] => {}
|
||||||
|
CONST => {}
|
||||||
|
&[_, _, ..] => {}
|
||||||
|
}
|
||||||
|
match s {
|
||||||
|
[] => {}
|
||||||
|
[false] => {}
|
||||||
|
CONST => {}
|
||||||
[_, _, ..] => {}
|
[_, _, ..] => {}
|
||||||
}
|
}
|
||||||
const CONST1: &[bool; 1] = &[true];
|
const CONST1: &[bool; 1] = &[true];
|
||||||
match s1 {
|
match s1 {
|
||||||
//~^ ERROR `&[false]` not covered
|
//~^ ERROR `&[false]` not covered
|
||||||
CONST1 => {}
|
CONST1 => {}
|
||||||
}
|
}
|
||||||
match s1 {
|
match s1 {
|
||||||
|
|
|
@ -115,26 +115,62 @@ LL | match s {
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[..]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:85:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:85:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[..]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[true]` not covered
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
LL | match s {
|
||||||
| ^ pattern `&[true]` not covered
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:93:11
|
||||||
|
|
|
||||||
|
LL | match s {
|
||||||
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:98:11
|
||||||
|
|
|
||||||
|
LL | match s {
|
||||||
|
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:103:11
|
||||||
|
|
|
||||||
|
LL | match s {
|
||||||
|
| ^ pattern `&[_, _, ..]` not covered
|
||||||
|
|
|
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
= note: the matched value is of type `&[bool]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||||
--> $DIR/slice-patterns-exhaustiveness.rs:97:11
|
--> $DIR/slice-patterns-exhaustiveness.rs:108:11
|
||||||
|
|
|
||||||
|
LL | match s {
|
||||||
|
| ^ pattern `&[false]` not covered
|
||||||
|
|
|
||||||
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
|
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||||
|
--> $DIR/slice-patterns-exhaustiveness.rs:121:11
|
||||||
|
|
|
|
||||||
LL | match s1 {
|
LL | match s1 {
|
||||||
| ^^ pattern `&[false]` not covered
|
| ^^ pattern `&[false]` not covered
|
||||||
|
@ -142,6 +178,6 @@ LL | match s1 {
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||||
= note: the matched value is of type `&[bool; 1]`
|
= note: the matched value is of type `&[bool; 1]`
|
||||||
|
|
||||||
error: aborting due to 16 previous errors
|
error: aborting due to 20 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0004`.
|
For more information about this error, try `rustc --explain E0004`.
|
||||||
|
|
Loading…
Reference in New Issue