Skip to content

Commit f774eb6

Browse files
committed
Use VarLenSlice consistently when splitting constructors
The previous behaviour ignored slice lengths above a certain length because it could not do otherwise. We now have VarLenSlice however, that can represent the ignored lengths to make the algorithm more consistent. This does not change the correctness of the algorithm, but makes it easier to reason about. As a nice side-effect, exhaustiveness errors have improved: they now capture all missing lengths instead of only the shortest.
1 parent d582ed5 commit f774eb6

File tree

5 files changed

+40
-25
lines changed

5 files changed

+40
-25
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,7 +2042,7 @@ fn split_grouped_constructors<'p, 'tcx>(
20422042
//
20432043
// Of course, if fixed-length patterns exist, we must be sure
20442044
// that our length is large enough to miss them all, so
2045-
// we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
2045+
// we can pick `L = max(max(FIXED_LEN)+1, max(PREFIX_LEN) + max(SUFFIX_LEN))`
20462046
//
20472047
// for example, with the above pair of patterns, all elements
20482048
// but the first and last can be added/removed, so any
@@ -2080,9 +2080,24 @@ fn split_grouped_constructors<'p, 'tcx>(
20802080
}
20812081
}
20822082

2083-
let max_slice_length = cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len);
2084-
split_ctors
2085-
.extend((self_prefix + self_suffix..=max_slice_length).map(FixedLenSlice))
2083+
// For diagnostics, we keep the prefix and suffix lengths separate, so in the case
2084+
// where `max_fixed_len+1` is the largest, we adapt `max_prefix_len` accordingly,
2085+
// so that `L = max_prefix_len + max_suffix_len`.
2086+
if max_fixed_len + 1 >= max_prefix_len + max_suffix_len {
2087+
// The subtraction can't overflow thanks to the above check.
2088+
// The new `max_prefix_len` is also guaranteed to be larger than its previous
2089+
// value.
2090+
max_prefix_len = max_fixed_len + 1 - max_suffix_len;
2091+
}
2092+
2093+
// `ctor` originally covered the range `(self_prefix + self_suffix..infinity)`. We
2094+
// now split it into two: lengths smaller than `max_prefix_len + max_suffix_len`
2095+
// are treated independently as fixed-lengths slices, and lengths above are
2096+
// captured by a final VarLenSlice constructor.
2097+
split_ctors.extend(
2098+
(self_prefix + self_suffix..max_prefix_len + max_suffix_len).map(FixedLenSlice),
2099+
);
2100+
split_ctors.push(VarLenSlice(max_prefix_len, max_suffix_len));
20862101
}
20872102
// Any other constructor can be used unchanged.
20882103
_ => split_ctors.push(ctor),

src/test/ui/pattern/usefulness/match-slice-patterns.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
fn check(list: &[Option<()>]) {
44
match list {
5-
//~^ ERROR `&[_, Some(_), None, _]` not covered
5+
//~^ ERROR `&[_, Some(_), .., None, _]` not covered
66
&[] => {},
77
&[_] => {},
88
&[_, _] => {},

src/test/ui/pattern/usefulness/match-slice-patterns.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0004]: non-exhaustive patterns: `&[_, Some(_), None, _]` not covered
1+
error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
22
--> $DIR/match-slice-patterns.rs:4:11
33
|
44
LL | match list {
5-
| ^^^^ pattern `&[_, Some(_), None, _]` not covered
5+
| ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
66
|
77
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
88

src/test/ui/pattern/usefulness/slice-patterns.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn main() {
3737
[.., false] => {}
3838
}
3939
match s {
40-
//~^ ERROR `&[false, true]` not covered
40+
//~^ ERROR `&[false, .., true]` not covered
4141
[] => {}
4242
[true, ..] => {}
4343
[.., false] => {}
@@ -57,18 +57,18 @@ fn main() {
5757
[_] => {}
5858
}
5959
match s {
60-
//~^ ERROR `&[false]` not covered
60+
//~^ ERROR `&[false, ..]` not covered
6161
[] => {}
6262
[true, ..] => {}
6363
}
6464
match s {
65-
//~^ ERROR `&[false, _]` not covered
65+
//~^ ERROR `&[false, _, ..]` not covered
6666
[] => {}
6767
[_] => {}
6868
[true, ..] => {}
6969
}
7070
match s {
71-
//~^ ERROR `&[_, false]` not covered
71+
//~^ ERROR `&[_, .., false]` not covered
7272
[] => {}
7373
[_] => {}
7474
[.., true] => {}
@@ -94,14 +94,14 @@ fn main() {
9494
[..] => {}
9595
}
9696
match s {
97-
//~^ ERROR `&[_, _, true]` not covered
97+
//~^ ERROR `&[_, _, .., true]` not covered
9898
[] => {}
9999
[_] => {}
100100
[_, _] => {}
101101
[.., false] => {}
102102
}
103103
match s {
104-
//~^ ERROR `&[true, _, _]` not covered
104+
//~^ ERROR `&[true, _, .., _]` not covered
105105
[] => {}
106106
[_] => {}
107107
[_, _] => {}

src/test/ui/pattern/usefulness/slice-patterns.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ LL | match s3 {
1414
|
1515
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1616

17-
error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
17+
error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
1818
--> $DIR/slice-patterns.rs:39:11
1919
|
2020
LL | match s {
21-
| ^ pattern `&[false, true]` not covered
21+
| ^ pattern `&[false, .., true]` not covered
2222
|
2323
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
2424

@@ -46,27 +46,27 @@ LL | match s {
4646
|
4747
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
4848

49-
error[E0004]: non-exhaustive patterns: `&[false]` not covered
49+
error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
5050
--> $DIR/slice-patterns.rs:59:11
5151
|
5252
LL | match s {
53-
| ^ pattern `&[false]` not covered
53+
| ^ pattern `&[false, ..]` not covered
5454
|
5555
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
5656

57-
error[E0004]: non-exhaustive patterns: `&[false, _]` not covered
57+
error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
5858
--> $DIR/slice-patterns.rs:64:11
5959
|
6060
LL | match s {
61-
| ^ pattern `&[false, _]` not covered
61+
| ^ pattern `&[false, _, ..]` not covered
6262
|
6363
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
6464

65-
error[E0004]: non-exhaustive patterns: `&[_, false]` not covered
65+
error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
6666
--> $DIR/slice-patterns.rs:70:11
6767
|
6868
LL | match s {
69-
| ^ pattern `&[_, false]` not covered
69+
| ^ pattern `&[_, .., false]` not covered
7070
|
7171
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
7272

@@ -112,19 +112,19 @@ error: unreachable pattern
112112
LL | [false, true] => {}
113113
| ^^^^^^^^^^^^^
114114

115-
error[E0004]: non-exhaustive patterns: `&[_, _, true]` not covered
115+
error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
116116
--> $DIR/slice-patterns.rs:96:11
117117
|
118118
LL | match s {
119-
| ^ pattern `&[_, _, true]` not covered
119+
| ^ pattern `&[_, _, .., true]` not covered
120120
|
121121
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
122122

123-
error[E0004]: non-exhaustive patterns: `&[true, _, _]` not covered
123+
error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
124124
--> $DIR/slice-patterns.rs:103:11
125125
|
126126
LL | match s {
127-
| ^ pattern `&[true, _, _]` not covered
127+
| ^ pattern `&[true, _, .., _]` not covered
128128
|
129129
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
130130

0 commit comments

Comments
 (0)