From 5a2410a07c8b151cd518792f41fce3341af004cf Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 31 May 2019 22:27:26 +0100 Subject: [PATCH] Add error for pattern-matching on arrays without a fixed size --- src/librustc_typeck/check/_match.rs | 45 +++++++++++++++++----------- src/librustc_typeck/error_codes.rs | 32 ++++++++++++++++++++ src/test/ui/error-codes/E0730.rs | 11 +++++++ src/test/ui/error-codes/E0730.stderr | 15 ++++++++++ 4 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/error-codes/E0730.rs create mode 100644 src/test/ui/error-codes/E0730.stderr diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 5cd95a9d834..64e2eedd721 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -400,27 +400,36 @@ pub fn check_pat_walk( let expected_ty = self.structurally_resolved_type(pat.span, expected); let (inner_ty, slice_ty) = match expected_ty.sty { ty::Array(inner_ty, size) => { - let size = size.unwrap_usize(tcx); - let min_len = before.len() as u64 + after.len() as u64; - if slice.is_none() { - if min_len != size { - struct_span_err!( - tcx.sess, pat.span, E0527, - "pattern requires {} elements but array has {}", - min_len, size) - .span_label(pat.span, format!("expected {} elements", size)) + if let Some(size) = size.assert_usize(tcx) { + let min_len = before.len() as u64 + after.len() as u64; + if slice.is_none() { + if min_len != size { + struct_span_err!( + tcx.sess, pat.span, E0527, + "pattern requires {} elements but array has {}", + min_len, size) + .span_label(pat.span, format!("expected {} elements", size)) + .emit(); + } + (inner_ty, tcx.types.err) + } else if let Some(rest) = size.checked_sub(min_len) { + (inner_ty, tcx.mk_array(inner_ty, rest)) + } else { + struct_span_err!(tcx.sess, pat.span, E0528, + "pattern requires at least {} elements but array has {}", + min_len, size) + .span_label(pat.span, + format!("pattern cannot match array of {} elements", size)) .emit(); + (inner_ty, tcx.types.err) } - (inner_ty, tcx.types.err) - } else if let Some(rest) = size.checked_sub(min_len) { - (inner_ty, tcx.mk_array(inner_ty, rest)) } else { - struct_span_err!(tcx.sess, pat.span, E0528, - "pattern requires at least {} elements but array has {}", - min_len, size) - .span_label(pat.span, - format!("pattern cannot match array of {} elements", size)) - .emit(); + struct_span_err!( + tcx.sess, + pat.span, + E0730, + "cannot pattern-match on an array without a fixed length", + ).emit(); (inner_ty, tcx.types.err) } } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 6dd3c0113cd..b5a50f43875 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4648,6 +4648,38 @@ fn make_recursive_type() -> impl Sized { ``` "##, +E0730: r##" +An array without a fixed length was pattern-matched. + +Example of erroneous code: + +```compile_fail,E0730 +#![feature(const_generics)] + +fn is_123(x: [u32; N]) -> bool { + match x { + [1, 2, 3] => true, // error: cannot pattern-match on an + // array without a fixed length + _ => false + } +} +``` + +Ensure that the pattern is consistent with the size of the matched +array. Additional elements can be matched with `..`: + +``` +#![feature(slice_patterns)] + +let r = &[1, 2, 3, 4]; +match r { + &[a, b, ..] => { // ok! + println!("a={}, b={}", a, b); + } +} +``` +"##, + } register_diagnostics! { diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs new file mode 100644 index 00000000000..e5048d6e6e3 --- /dev/null +++ b/src/test/ui/error-codes/E0730.rs @@ -0,0 +1,11 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn is_123(x: [u32; N]) -> bool { + match x { + [1, 2, 3] => true, //~ ERROR cannot pattern-match on an array without a fixed length + _ => false + } +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr new file mode 100644 index 00000000000..f9281262bb7 --- /dev/null +++ b/src/test/ui/error-codes/E0730.stderr @@ -0,0 +1,15 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/E0730.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + +error[E0730]: cannot pattern-match on an array without a fixed length + --> $DIR/E0730.rs:6:9 + | +LL | [1, 2, 3] => true, + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0730`.