Skip to content

Commit e3d9984

Browse files
committed
Auto merge of #66129 - Nadrieril:refactor-slice-pat-usefulness, r=varkor
Refactor slice pattern usefulness checking As a follow up to #65874, this PR changes how variable-length slice patterns are handled in usefulness checking. The objectives are: cleaning up that code to make it easier to understand, and paving the way to handling fixed-length slices more cleverly too, for #53820. Before this, variable-length slice patterns were eagerly expanded into a union of fixed-length slices. Now they have their own special constructor, which allows expanding them a bit more lazily. As a nice side-effect, this improves diagnostics. This PR shows a slight performance improvement, mostly due to 149792b. This will probably have to be reverted in some way when we implement or-patterns.
2 parents e931f00 + fd9921b commit e3d9984

21 files changed

+627
-264
lines changed

src/librustc_mir/hair/pattern/_match.rs

+344-249
Large diffs are not rendered by default.

src/librustc_mir/hair/pattern/check_match.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc::hir::{self, Pat};
1818

1919
use std::slice;
2020

21-
use syntax_pos::{MultiSpan, Span, DUMMY_SP};
21+
use syntax_pos::{MultiSpan, Span};
2222

2323
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
2424
let body_id = match tcx.hir().as_local_hir_id(def_id) {
@@ -491,7 +491,7 @@ fn check_not_useful(
491491
matrix: &Matrix<'_, 'tcx>,
492492
hir_id: HirId,
493493
) -> Result<(), Vec<super::Pat<'tcx>>> {
494-
let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
494+
let wild_pattern = super::Pat::wildcard_from_ty(ty);
495495
match is_useful(cx, matrix, &PatStack::from_pattern(&wild_pattern), ConstructWitness, hir_id) {
496496
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
497497
UsefulWithWitness(pats) => Err(if pats.is_empty() {

src/librustc_mir/hair/pattern/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_index::vec::Idx;
2626
use std::cmp::Ordering;
2727
use std::fmt;
2828
use syntax::ast;
29-
use syntax_pos::Span;
29+
use syntax_pos::{Span, DUMMY_SP};
3030

3131
#[derive(Clone, Debug)]
3232
pub enum PatternError {
@@ -55,6 +55,11 @@ pub struct Pat<'tcx> {
5555
pub kind: Box<PatKind<'tcx>>,
5656
}
5757

58+
impl<'tcx> Pat<'tcx> {
59+
pub(crate) fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
60+
Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) }
61+
}
62+
}
5863

5964
#[derive(Copy, Clone, Debug, PartialEq)]
6065
pub struct PatTyProj<'tcx> {

src/test/ui/consts/const_let_refutable.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _]` not covered
1+
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
22
--> $DIR/const_let_refutable.rs:3:16
33
|
44
LL | const fn slice([a, b]: &[i32]) -> i32 {
5-
| ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _]` not covered
5+
| ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
66

77
error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
88
--> $DIR/const_let_refutable.rs:4:5

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

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

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

+1-1
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

+2-2
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/non-exhaustive-match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn main() {
4444
}
4545
let vec = vec![0.5f32];
4646
let vec: &[f32] = &vec;
47-
match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
47+
match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _, ..]` not covered
4848
[0.1, 0.2, 0.3] => (),
4949
[0.1, 0.2] => (),
5050
[0.1] => (),

src/test/ui/pattern/usefulness/non-exhaustive-match.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ LL | match *vec {
6666
|
6767
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
6868

69-
error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
69+
error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
7070
--> $DIR/non-exhaustive-match.rs:47:11
7171
|
7272
LL | match *vec {
73-
| ^^^^ pattern `[_, _, _, _]` not covered
73+
| ^^^^ pattern `[_, _, _, _, ..]` not covered
7474
|
7575
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
7676

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#![feature(slice_patterns)]
2+
3+
fn main() {
4+
let s: &[bool] = &[true; 0];
5+
let s1: &[bool; 1] = &[false; 1];
6+
let s2: &[bool; 2] = &[false; 2];
7+
let s3: &[bool; 3] = &[false; 3];
8+
9+
match s1 {
10+
[true, ..] => {}
11+
[.., false] => {}
12+
}
13+
match s2 {
14+
//~^ ERROR `&[false, true]` not covered
15+
[true, ..] => {}
16+
[.., false] => {}
17+
}
18+
match s3 {
19+
//~^ ERROR `&[false, _, true]` not covered
20+
[true, ..] => {}
21+
[.., false] => {}
22+
}
23+
match s {
24+
//~^ ERROR `&[false, .., true]` not covered
25+
[] => {}
26+
[true, ..] => {}
27+
[.., false] => {}
28+
}
29+
30+
match s3 {
31+
//~^ ERROR `&[false, _, _]` not covered
32+
[true, .., true] => {}
33+
}
34+
match s {
35+
//~^ ERROR `&[_, ..]` not covered
36+
[] => {}
37+
}
38+
match s {
39+
//~^ ERROR `&[_, _, ..]` not covered
40+
[] => {}
41+
[_] => {}
42+
}
43+
match s {
44+
//~^ ERROR `&[false, ..]` not covered
45+
[] => {}
46+
[true, ..] => {}
47+
}
48+
match s {
49+
//~^ ERROR `&[false, _, ..]` not covered
50+
[] => {}
51+
[_] => {}
52+
[true, ..] => {}
53+
}
54+
match s {
55+
//~^ ERROR `&[_, .., false]` not covered
56+
[] => {}
57+
[_] => {}
58+
[.., true] => {}
59+
}
60+
61+
match s {
62+
//~^ ERROR `&[_, _, .., true]` not covered
63+
[] => {}
64+
[_] => {}
65+
[_, _] => {}
66+
[.., false] => {}
67+
}
68+
match s {
69+
//~^ ERROR `&[true, _, .., _]` not covered
70+
[] => {}
71+
[_] => {}
72+
[_, _] => {}
73+
[false, .., false] => {}
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
2+
--> $DIR/slice-patterns-exhaustiveness.rs:13:11
3+
|
4+
LL | match s2 {
5+
| ^^ pattern `&[false, true]` not covered
6+
|
7+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
8+
9+
error[E0004]: non-exhaustive patterns: `&[false, _, true]` not covered
10+
--> $DIR/slice-patterns-exhaustiveness.rs:18:11
11+
|
12+
LL | match s3 {
13+
| ^^ pattern `&[false, _, true]` not covered
14+
|
15+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
16+
17+
error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
18+
--> $DIR/slice-patterns-exhaustiveness.rs:23:11
19+
|
20+
LL | match s {
21+
| ^ pattern `&[false, .., true]` not covered
22+
|
23+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
24+
25+
error[E0004]: non-exhaustive patterns: `&[false, _, _]` not covered
26+
--> $DIR/slice-patterns-exhaustiveness.rs:30:11
27+
|
28+
LL | match s3 {
29+
| ^^ pattern `&[false, _, _]` not covered
30+
|
31+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
32+
33+
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
34+
--> $DIR/slice-patterns-exhaustiveness.rs:34:11
35+
|
36+
LL | match s {
37+
| ^ pattern `&[_, ..]` not covered
38+
|
39+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
40+
41+
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
42+
--> $DIR/slice-patterns-exhaustiveness.rs:38:11
43+
|
44+
LL | match s {
45+
| ^ pattern `&[_, _, ..]` not covered
46+
|
47+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
48+
49+
error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
50+
--> $DIR/slice-patterns-exhaustiveness.rs:43:11
51+
|
52+
LL | match s {
53+
| ^ pattern `&[false, ..]` not covered
54+
|
55+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
56+
57+
error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
58+
--> $DIR/slice-patterns-exhaustiveness.rs:48:11
59+
|
60+
LL | match s {
61+
| ^ pattern `&[false, _, ..]` not covered
62+
|
63+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
64+
65+
error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
66+
--> $DIR/slice-patterns-exhaustiveness.rs:54:11
67+
|
68+
LL | match s {
69+
| ^ pattern `&[_, .., false]` not covered
70+
|
71+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
72+
73+
error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
74+
--> $DIR/slice-patterns-exhaustiveness.rs:61:11
75+
|
76+
LL | match s {
77+
| ^ pattern `&[_, _, .., true]` not covered
78+
|
79+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
80+
81+
error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
82+
--> $DIR/slice-patterns-exhaustiveness.rs:68:11
83+
|
84+
LL | match s {
85+
| ^ pattern `&[true, _, .., _]` not covered
86+
|
87+
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
88+
89+
error: aborting due to 11 previous errors
90+
91+
For more information about this error, try `rustc --explain E0004`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// check-pass
2+
#![feature(slice_patterns)]
3+
4+
fn main() {
5+
let s: &[bool] = &[true; 0];
6+
let s0: &[bool; 0] = &[];
7+
let s1: &[bool; 1] = &[false; 1];
8+
let s2: &[bool; 2] = &[false; 2];
9+
10+
let [] = s0;
11+
let [_] = s1;
12+
let [_, _] = s2;
13+
14+
let [..] = s;
15+
let [..] = s0;
16+
let [..] = s1;
17+
let [..] = s2;
18+
19+
let [_, ..] = s1;
20+
let [.., _] = s1;
21+
let [_, ..] = s2;
22+
let [.., _] = s2;
23+
24+
let [_, _, ..] = s2;
25+
let [_, .., _] = s2;
26+
let [.., _, _] = s2;
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#![feature(slice_patterns)]
2+
#![deny(unreachable_patterns)]
3+
4+
fn main() {
5+
let s: &[bool] = &[true; 0];
6+
7+
match s {
8+
[true, ..] => {}
9+
[true, ..] => {} //~ ERROR unreachable pattern
10+
[true] => {} //~ ERROR unreachable pattern
11+
[..] => {}
12+
}
13+
match s {
14+
[.., true] => {}
15+
[.., true] => {} //~ ERROR unreachable pattern
16+
[true] => {} //~ ERROR unreachable pattern
17+
[..] => {}
18+
}
19+
match s {
20+
[false, .., true] => {}
21+
[false, .., true] => {} //~ ERROR unreachable pattern
22+
[false, true] => {} //~ ERROR unreachable pattern
23+
[false] => {}
24+
[..] => {}
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error: unreachable pattern
2+
--> $DIR/slice-patterns-reachability.rs:9:9
3+
|
4+
LL | [true, ..] => {}
5+
| ^^^^^^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/slice-patterns-reachability.rs:2:9
9+
|
10+
LL | #![deny(unreachable_patterns)]
11+
| ^^^^^^^^^^^^^^^^^^^^
12+
13+
error: unreachable pattern
14+
--> $DIR/slice-patterns-reachability.rs:10:9
15+
|
16+
LL | [true] => {}
17+
| ^^^^^^
18+
19+
error: unreachable pattern
20+
--> $DIR/slice-patterns-reachability.rs:15:9
21+
|
22+
LL | [.., true] => {}
23+
| ^^^^^^^^^^
24+
25+
error: unreachable pattern
26+
--> $DIR/slice-patterns-reachability.rs:16:9
27+
|
28+
LL | [true] => {}
29+
| ^^^^^^
30+
31+
error: unreachable pattern
32+
--> $DIR/slice-patterns-reachability.rs:21:9
33+
|
34+
LL | [false, .., true] => {}
35+
| ^^^^^^^^^^^^^^^^^
36+
37+
error: unreachable pattern
38+
--> $DIR/slice-patterns-reachability.rs:22:9
39+
|
40+
LL | [false, true] => {}
41+
| ^^^^^^^^^^^^^
42+
43+
error: aborting due to 6 previous errors
44+

src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ LL | let _ = match x {};
3030
|
3131
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
3232

33-
error[E0004]: non-exhaustive patterns: `&[_]` not covered
33+
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
3434
--> $DIR/uninhabited-matches-feature-gated.rs:21:19
3535
|
3636
LL | let _ = match x {
37-
| ^ pattern `&[_]` not covered
37+
| ^ pattern `&[_, ..]` not covered
3838
|
3939
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
4040

0 commit comments

Comments
 (0)