Auto merge of #66603 - Nadrieril:fix-65413, r=varkor
Fix #65413 #65413 was due to an oversight in `pat_constructor` that didn't check if a particular const value was maybe a slice/array const.
This commit is contained in:
commit
f453d1127d
|
@ -347,6 +347,7 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
|
|||
) => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
|
||||
|
||||
(_, &PatKind::Binding { subpattern: Some(ref s), .. }) => s.fold_with(self),
|
||||
(_, &PatKind::AscribeUserType { subpattern: ref s, .. }) => s.fold_with(self),
|
||||
_ => pat.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
|
@ -747,7 +748,7 @@ impl<'tcx> Constructor<'tcx> {
|
|||
.iter()
|
||||
.filter_map(|c: &Constructor<'_>| match c {
|
||||
Slice(slice) => Some(*slice),
|
||||
// FIXME(#65413): We ignore `ConstantValue`s here.
|
||||
// FIXME(oli-obk): implement `deref` for `ConstValue`
|
||||
ConstantValue(..) => None,
|
||||
_ => bug!("bad slice pattern constructor {:?}", c),
|
||||
})
|
||||
|
@ -1759,9 +1760,7 @@ fn pat_constructor<'tcx>(
|
|||
pat: &Pat<'tcx>,
|
||||
) -> Option<Constructor<'tcx>> {
|
||||
match *pat.kind {
|
||||
PatKind::AscribeUserType { ref subpattern, .. } => {
|
||||
pat_constructor(tcx, param_env, subpattern)
|
||||
}
|
||||
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
|
||||
PatKind::Binding { .. } | PatKind::Wild => None,
|
||||
PatKind::Leaf { .. } | PatKind::Deref { .. } => Some(Single),
|
||||
PatKind::Variant { adt_def, variant_index, .. } => {
|
||||
|
@ -1771,7 +1770,19 @@ fn pat_constructor<'tcx>(
|
|||
if let Some(int_range) = IntRange::from_const(tcx, param_env, value, pat.span) {
|
||||
Some(IntRange(int_range))
|
||||
} else {
|
||||
Some(ConstantValue(value))
|
||||
match (value.val, &value.ty.kind) {
|
||||
(_, ty::Array(_, n)) => {
|
||||
let len = n.eval_usize(tcx, param_env);
|
||||
Some(Slice(Slice { array_len: Some(len), kind: FixedLen(len) }))
|
||||
}
|
||||
(ty::ConstKind::Value(ConstValue::Slice { start, end, .. }), ty::Slice(_)) => {
|
||||
let len = (end - start) as u64;
|
||||
Some(Slice(Slice { array_len: None, kind: FixedLen(len) }))
|
||||
}
|
||||
// FIXME(oli-obk): implement `deref` for `ConstValue`
|
||||
// (ty::ConstKind::Value(ConstValue::ByRef { .. }), ty::Slice(_)) => { ... }
|
||||
_ => Some(ConstantValue(value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
PatKind::Range(PatRange { lo, hi, end }) => {
|
||||
|
@ -2085,32 +2096,19 @@ fn split_grouped_constructors<'p, 'tcx>(
|
|||
let mut max_suffix_len = self_suffix;
|
||||
let mut max_fixed_len = 0;
|
||||
|
||||
for row in matrix.heads() {
|
||||
match *row.kind {
|
||||
PatKind::Constant { value } => {
|
||||
// extract the length of an array/slice from a constant
|
||||
match (value.val, &value.ty.kind) {
|
||||
(_, ty::Array(_, n)) => {
|
||||
max_fixed_len =
|
||||
cmp::max(max_fixed_len, n.eval_usize(tcx, param_env))
|
||||
}
|
||||
(
|
||||
ty::ConstKind::Value(ConstValue::Slice { start, end, .. }),
|
||||
ty::Slice(_),
|
||||
) => max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64),
|
||||
_ => {}
|
||||
let head_ctors =
|
||||
matrix.heads().filter_map(|pat| pat_constructor(tcx, param_env, pat));
|
||||
for ctor in head_ctors {
|
||||
match ctor {
|
||||
Slice(slice) => match slice.pattern_kind() {
|
||||
FixedLen(len) => {
|
||||
max_fixed_len = cmp::max(max_fixed_len, len);
|
||||
}
|
||||
}
|
||||
PatKind::Slice { ref prefix, slice: None, ref suffix }
|
||||
| PatKind::Array { ref prefix, slice: None, ref suffix } => {
|
||||
let fixed_len = prefix.len() as u64 + suffix.len() as u64;
|
||||
max_fixed_len = cmp::max(max_fixed_len, fixed_len);
|
||||
}
|
||||
PatKind::Slice { ref prefix, slice: Some(_), ref suffix }
|
||||
| PatKind::Array { ref prefix, slice: Some(_), ref suffix } => {
|
||||
max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
|
||||
max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
|
||||
}
|
||||
VarLen(prefix, suffix) => {
|
||||
max_prefix_len = cmp::max(max_prefix_len, prefix);
|
||||
max_suffix_len = cmp::max(max_suffix_len, suffix);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -2250,21 +2248,17 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
|
|||
/// fields filled with wild patterns.
|
||||
fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
|
||||
cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
mut pat: &'q Pat<'tcx>,
|
||||
pat: &'q Pat<'tcx>,
|
||||
constructor: &Constructor<'tcx>,
|
||||
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
|
||||
) -> Option<PatStack<'p, 'tcx>> {
|
||||
while let PatKind::AscribeUserType { ref subpattern, .. } = *pat.kind {
|
||||
pat = subpattern;
|
||||
}
|
||||
|
||||
if let NonExhaustive = constructor {
|
||||
// Only a wildcard pattern can match the special extra constructor
|
||||
return if pat.is_wildcard() { Some(PatStack::default()) } else { None };
|
||||
}
|
||||
|
||||
let result = match *pat.kind {
|
||||
PatKind::AscribeUserType { .. } => bug!(), // Handled above
|
||||
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
|
||||
|
||||
PatKind::Binding { .. } | PatKind::Wild => {
|
||||
Some(PatStack::from_slice(ctor_wild_subpatterns))
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// check-pass
|
||||
#![feature(slice_patterns)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
const C0: &'static [u8] = b"\x00";
|
||||
|
||||
fn main() {
|
||||
let x: &[u8] = &[0];
|
||||
match x {
|
||||
&[] => {}
|
||||
&[1..=255] => {}
|
||||
C0 => {}
|
||||
&[_, _, ..] => {}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
error[E0004]: non-exhaustive patterns: `&[..]` not covered
|
||||
error[E0004]: non-exhaustive patterns: `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
|
||||
--> $DIR/match-byte-array-patterns-2.rs:4:11
|
||||
|
|
||||
LL | match buf {
|
||||
| ^^^ pattern `&[..]` not covered
|
||||
| ^^^ patterns `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[..]` not covered
|
||||
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
|
||||
--> $DIR/match-byte-array-patterns-2.rs:10:11
|
||||
|
|
||||
LL | match buf {
|
||||
| ^^^ pattern `&[..]` not covered
|
||||
| ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
|
|
|
@ -44,4 +44,11 @@ fn main() {
|
|||
b"" => (), //~ ERROR unreachable pattern
|
||||
_ => (), //~ ERROR unreachable pattern
|
||||
}
|
||||
|
||||
const CONST1: &[bool; 1] = &[true];
|
||||
match &[false] {
|
||||
CONST1 => {}
|
||||
[true] => {} //~ ERROR unreachable pattern
|
||||
[false] => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,5 +52,11 @@ error: unreachable pattern
|
|||
LL | _ => (),
|
||||
| ^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const.rs:51:9
|
||||
|
|
||||
LL | [true] => {}
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
|
|
@ -82,4 +82,26 @@ fn main() {
|
|||
[_, _] => {}
|
||||
[false, .., false] => {}
|
||||
}
|
||||
|
||||
const CONST: &[bool] = &[true];
|
||||
match s {
|
||||
//~^ ERROR `&[..]` not covered
|
||||
CONST => {}
|
||||
}
|
||||
match s {
|
||||
//~^ ERROR `&[true]` not covered
|
||||
[] => {},
|
||||
[false] => {},
|
||||
CONST => {},
|
||||
[_, _, ..] => {}
|
||||
}
|
||||
const CONST1: &[bool; 1] = &[true];
|
||||
match s1 {
|
||||
//~^ ERROR `&[false]` not covered
|
||||
CONST1 => {}
|
||||
}
|
||||
match s1 {
|
||||
CONST1 => {}
|
||||
[false] => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,30 @@ LL | match s {
|
|||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
error[E0004]: non-exhaustive patterns: `&[..]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:87:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ pattern `&[..]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[true]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:91:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ pattern `&[true]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:99:11
|
||||
|
|
||||
LL | match s1 {
|
||||
| ^^ pattern `&[false]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
let s: &[bool] = &[true; 0];
|
||||
let s: &[bool] = &[];
|
||||
|
||||
match s {
|
||||
[true, ..] => {}
|
||||
|
|
Loading…
Reference in New Issue