Skip to content

Commit 5a2410a

Browse files
committed
Add error for pattern-matching on arrays without a fixed size
1 parent 2155135 commit 5a2410a

File tree

4 files changed

+85
-18
lines changed

4 files changed

+85
-18
lines changed

src/librustc_typeck/check/_match.rs

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -400,27 +400,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
400400
let expected_ty = self.structurally_resolved_type(pat.span, expected);
401401
let (inner_ty, slice_ty) = match expected_ty.sty {
402402
ty::Array(inner_ty, size) => {
403-
let size = size.unwrap_usize(tcx);
404-
let min_len = before.len() as u64 + after.len() as u64;
405-
if slice.is_none() {
406-
if min_len != size {
407-
struct_span_err!(
408-
tcx.sess, pat.span, E0527,
409-
"pattern requires {} elements but array has {}",
410-
min_len, size)
411-
.span_label(pat.span, format!("expected {} elements", size))
403+
if let Some(size) = size.assert_usize(tcx) {
404+
let min_len = before.len() as u64 + after.len() as u64;
405+
if slice.is_none() {
406+
if min_len != size {
407+
struct_span_err!(
408+
tcx.sess, pat.span, E0527,
409+
"pattern requires {} elements but array has {}",
410+
min_len, size)
411+
.span_label(pat.span, format!("expected {} elements", size))
412+
.emit();
413+
}
414+
(inner_ty, tcx.types.err)
415+
} else if let Some(rest) = size.checked_sub(min_len) {
416+
(inner_ty, tcx.mk_array(inner_ty, rest))
417+
} else {
418+
struct_span_err!(tcx.sess, pat.span, E0528,
419+
"pattern requires at least {} elements but array has {}",
420+
min_len, size)
421+
.span_label(pat.span,
422+
format!("pattern cannot match array of {} elements", size))
412423
.emit();
424+
(inner_ty, tcx.types.err)
413425
}
414-
(inner_ty, tcx.types.err)
415-
} else if let Some(rest) = size.checked_sub(min_len) {
416-
(inner_ty, tcx.mk_array(inner_ty, rest))
417426
} else {
418-
struct_span_err!(tcx.sess, pat.span, E0528,
419-
"pattern requires at least {} elements but array has {}",
420-
min_len, size)
421-
.span_label(pat.span,
422-
format!("pattern cannot match array of {} elements", size))
423-
.emit();
427+
struct_span_err!(
428+
tcx.sess,
429+
pat.span,
430+
E0730,
431+
"cannot pattern-match on an array without a fixed length",
432+
).emit();
424433
(inner_ty, tcx.types.err)
425434
}
426435
}

src/librustc_typeck/error_codes.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4648,6 +4648,38 @@ fn make_recursive_type() -> impl Sized {
46484648
```
46494649
"##,
46504650

4651+
E0730: r##"
4652+
An array without a fixed length was pattern-matched.
4653+
4654+
Example of erroneous code:
4655+
4656+
```compile_fail,E0730
4657+
#![feature(const_generics)]
4658+
4659+
fn is_123<const N: usize>(x: [u32; N]) -> bool {
4660+
match x {
4661+
[1, 2, 3] => true, // error: cannot pattern-match on an
4662+
// array without a fixed length
4663+
_ => false
4664+
}
4665+
}
4666+
```
4667+
4668+
Ensure that the pattern is consistent with the size of the matched
4669+
array. Additional elements can be matched with `..`:
4670+
4671+
```
4672+
#![feature(slice_patterns)]
4673+
4674+
let r = &[1, 2, 3, 4];
4675+
match r {
4676+
&[a, b, ..] => { // ok!
4677+
println!("a={}, b={}", a, b);
4678+
}
4679+
}
4680+
```
4681+
"##,
4682+
46514683
}
46524684

46534685
register_diagnostics! {

src/test/ui/error-codes/E0730.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
fn is_123<const N: usize>(x: [u32; N]) -> bool {
5+
match x {
6+
[1, 2, 3] => true, //~ ERROR cannot pattern-match on an array without a fixed length
7+
_ => false
8+
}
9+
}
10+
11+
fn main() {}

src/test/ui/error-codes/E0730.stderr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/E0730.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
7+
error[E0730]: cannot pattern-match on an array without a fixed length
8+
--> $DIR/E0730.rs:6:9
9+
|
10+
LL | [1, 2, 3] => true,
11+
| ^^^^^^^^^
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0730`.

0 commit comments

Comments
 (0)