Skip to content

Commit f453d11

Browse files
committed
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.
2 parents 4752c05 + 3f91712 commit f453d11

8 files changed

+111
-43
lines changed

Diff for: src/librustc_mir/hair/pattern/_match.rs

+30-36
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
347347
) => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
348348

349349
(_, &PatKind::Binding { subpattern: Some(ref s), .. }) => s.fold_with(self),
350+
(_, &PatKind::AscribeUserType { subpattern: ref s, .. }) => s.fold_with(self),
350351
_ => pat.super_fold_with(self),
351352
}
352353
}
@@ -747,7 +748,7 @@ impl<'tcx> Constructor<'tcx> {
747748
.iter()
748749
.filter_map(|c: &Constructor<'_>| match c {
749750
Slice(slice) => Some(*slice),
750-
// FIXME(#65413): We ignore `ConstantValue`s here.
751+
// FIXME(oli-obk): implement `deref` for `ConstValue`
751752
ConstantValue(..) => None,
752753
_ => bug!("bad slice pattern constructor {:?}", c),
753754
})
@@ -1759,9 +1760,7 @@ fn pat_constructor<'tcx>(
17591760
pat: &Pat<'tcx>,
17601761
) -> Option<Constructor<'tcx>> {
17611762
match *pat.kind {
1762-
PatKind::AscribeUserType { ref subpattern, .. } => {
1763-
pat_constructor(tcx, param_env, subpattern)
1764-
}
1763+
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
17651764
PatKind::Binding { .. } | PatKind::Wild => None,
17661765
PatKind::Leaf { .. } | PatKind::Deref { .. } => Some(Single),
17671766
PatKind::Variant { adt_def, variant_index, .. } => {
@@ -1771,7 +1770,19 @@ fn pat_constructor<'tcx>(
17711770
if let Some(int_range) = IntRange::from_const(tcx, param_env, value, pat.span) {
17721771
Some(IntRange(int_range))
17731772
} else {
1774-
Some(ConstantValue(value))
1773+
match (value.val, &value.ty.kind) {
1774+
(_, ty::Array(_, n)) => {
1775+
let len = n.eval_usize(tcx, param_env);
1776+
Some(Slice(Slice { array_len: Some(len), kind: FixedLen(len) }))
1777+
}
1778+
(ty::ConstKind::Value(ConstValue::Slice { start, end, .. }), ty::Slice(_)) => {
1779+
let len = (end - start) as u64;
1780+
Some(Slice(Slice { array_len: None, kind: FixedLen(len) }))
1781+
}
1782+
// FIXME(oli-obk): implement `deref` for `ConstValue`
1783+
// (ty::ConstKind::Value(ConstValue::ByRef { .. }), ty::Slice(_)) => { ... }
1784+
_ => Some(ConstantValue(value)),
1785+
}
17751786
}
17761787
}
17771788
PatKind::Range(PatRange { lo, hi, end }) => {
@@ -2085,32 +2096,19 @@ fn split_grouped_constructors<'p, 'tcx>(
20852096
let mut max_suffix_len = self_suffix;
20862097
let mut max_fixed_len = 0;
20872098

2088-
for row in matrix.heads() {
2089-
match *row.kind {
2090-
PatKind::Constant { value } => {
2091-
// extract the length of an array/slice from a constant
2092-
match (value.val, &value.ty.kind) {
2093-
(_, ty::Array(_, n)) => {
2094-
max_fixed_len =
2095-
cmp::max(max_fixed_len, n.eval_usize(tcx, param_env))
2096-
}
2097-
(
2098-
ty::ConstKind::Value(ConstValue::Slice { start, end, .. }),
2099-
ty::Slice(_),
2100-
) => max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64),
2101-
_ => {}
2099+
let head_ctors =
2100+
matrix.heads().filter_map(|pat| pat_constructor(tcx, param_env, pat));
2101+
for ctor in head_ctors {
2102+
match ctor {
2103+
Slice(slice) => match slice.pattern_kind() {
2104+
FixedLen(len) => {
2105+
max_fixed_len = cmp::max(max_fixed_len, len);
21022106
}
2103-
}
2104-
PatKind::Slice { ref prefix, slice: None, ref suffix }
2105-
| PatKind::Array { ref prefix, slice: None, ref suffix } => {
2106-
let fixed_len = prefix.len() as u64 + suffix.len() as u64;
2107-
max_fixed_len = cmp::max(max_fixed_len, fixed_len);
2108-
}
2109-
PatKind::Slice { ref prefix, slice: Some(_), ref suffix }
2110-
| PatKind::Array { ref prefix, slice: Some(_), ref suffix } => {
2111-
max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
2112-
max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
2113-
}
2107+
VarLen(prefix, suffix) => {
2108+
max_prefix_len = cmp::max(max_prefix_len, prefix);
2109+
max_suffix_len = cmp::max(max_suffix_len, suffix);
2110+
}
2111+
},
21142112
_ => {}
21152113
}
21162114
}
@@ -2250,21 +2248,17 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
22502248
/// fields filled with wild patterns.
22512249
fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
22522250
cx: &mut MatchCheckCtxt<'a, 'tcx>,
2253-
mut pat: &'q Pat<'tcx>,
2251+
pat: &'q Pat<'tcx>,
22542252
constructor: &Constructor<'tcx>,
22552253
ctor_wild_subpatterns: &[&'p Pat<'tcx>],
22562254
) -> Option<PatStack<'p, 'tcx>> {
2257-
while let PatKind::AscribeUserType { ref subpattern, .. } = *pat.kind {
2258-
pat = subpattern;
2259-
}
2260-
22612255
if let NonExhaustive = constructor {
22622256
// Only a wildcard pattern can match the special extra constructor
22632257
return if pat.is_wildcard() { Some(PatStack::default()) } else { None };
22642258
}
22652259

22662260
let result = match *pat.kind {
2267-
PatKind::AscribeUserType { .. } => bug!(), // Handled above
2261+
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
22682262

22692263
PatKind::Binding { .. } | PatKind::Wild => {
22702264
Some(PatStack::from_slice(ctor_wild_subpatterns))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
#![feature(slice_patterns)]
3+
#![deny(unreachable_patterns)]
4+
5+
const C0: &'static [u8] = b"\x00";
6+
7+
fn main() {
8+
let x: &[u8] = &[0];
9+
match x {
10+
&[] => {}
11+
&[1..=255] => {}
12+
C0 => {}
13+
&[_, _, ..] => {}
14+
}
15+
}

Diff for: src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
error[E0004]: non-exhaustive patterns: `&[..]` not covered
1+
error[E0004]: non-exhaustive patterns: `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
22
--> $DIR/match-byte-array-patterns-2.rs:4:11
33
|
44
LL | match buf {
5-
| ^^^ pattern `&[..]` not covered
5+
| ^^^ patterns `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
66
|
77
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
88

9-
error[E0004]: non-exhaustive patterns: `&[..]` not covered
9+
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
1010
--> $DIR/match-byte-array-patterns-2.rs:10:11
1111
|
1212
LL | match buf {
13-
| ^^^ pattern `&[..]` not covered
13+
| ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
1414
|
1515
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1616

Diff for: src/test/ui/pattern/usefulness/slice-pattern-const.rs

+7
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ fn main() {
4444
b"" => (), //~ ERROR unreachable pattern
4545
_ => (), //~ ERROR unreachable pattern
4646
}
47+
48+
const CONST1: &[bool; 1] = &[true];
49+
match &[false] {
50+
CONST1 => {}
51+
[true] => {} //~ ERROR unreachable pattern
52+
[false] => {}
53+
}
4754
}

Diff for: src/test/ui/pattern/usefulness/slice-pattern-const.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,11 @@ error: unreachable pattern
5252
LL | _ => (),
5353
| ^
5454

55-
error: aborting due to 8 previous errors
55+
error: unreachable pattern
56+
--> $DIR/slice-pattern-const.rs:51:9
57+
|
58+
LL | [true] => {}
59+
| ^^^^^^
60+
61+
error: aborting due to 9 previous errors
5662

Diff for: src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs

+22
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,26 @@ fn main() {
8282
[_, _] => {}
8383
[false, .., false] => {}
8484
}
85+
86+
const CONST: &[bool] = &[true];
87+
match s {
88+
//~^ ERROR `&[..]` not covered
89+
CONST => {}
90+
}
91+
match s {
92+
//~^ ERROR `&[true]` not covered
93+
[] => {},
94+
[false] => {},
95+
CONST => {},
96+
[_, _, ..] => {}
97+
}
98+
const CONST1: &[bool; 1] = &[true];
99+
match s1 {
100+
//~^ ERROR `&[false]` not covered
101+
CONST1 => {}
102+
}
103+
match s1 {
104+
CONST1 => {}
105+
[false] => {}
106+
}
85107
}

Diff for: src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr

+25-1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,30 @@ LL | match s {
102102
|
103103
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
104104

105-
error: aborting due to 13 previous errors
105+
error[E0004]: non-exhaustive patterns: `&[..]` not covered
106+
--> $DIR/slice-patterns-exhaustiveness.rs:87:11
107+
|
108+
LL | match s {
109+
| ^ pattern `&[..]` not covered
110+
|
111+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
112+
113+
error[E0004]: non-exhaustive patterns: `&[true]` not covered
114+
--> $DIR/slice-patterns-exhaustiveness.rs:91:11
115+
|
116+
LL | match s {
117+
| ^ pattern `&[true]` not covered
118+
|
119+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
120+
121+
error[E0004]: non-exhaustive patterns: `&[false]` not covered
122+
--> $DIR/slice-patterns-exhaustiveness.rs:99:11
123+
|
124+
LL | match s1 {
125+
| ^^ pattern `&[false]` not covered
126+
|
127+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
128+
129+
error: aborting due to 16 previous errors
106130

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

Diff for: src/test/ui/pattern/usefulness/slice-patterns-reachability.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![deny(unreachable_patterns)]
33

44
fn main() {
5-
let s: &[bool] = &[true; 0];
5+
let s: &[bool] = &[];
66

77
match s {
88
[true, ..] => {}

0 commit comments

Comments
 (0)