diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a29b173880a08..95312d55b3be1 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -914,8 +914,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // already reported in the query - ConstEvalFailure(_) => { - self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error"); + ConstEvalFailure(err) => { + self.tcx.sess.delay_span_bug( + span, + &format!("constant in type had an ignored error: {:?}", err), + ); return; } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 6d7b0926c7ae2..6415122dd3905 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -549,8 +549,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } } + let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?; let element = self.layout_of(element)?; - let count = count.unwrap_usize(tcx); let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index b000628a3f706..42bd790ca2e9c 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -342,9 +342,7 @@ fn fixed_vec_metadata( let (size, align) = cx.size_and_align_of(array_or_slice_type); let upper_bound = match array_or_slice_type.sty { - ty::Array(_, len) => { - len.unwrap_usize(cx.tcx) as c_longlong - } + ty::Array(_, len) => len.unwrap_usize(cx.tcx) as c_longlong, _ => -1 }; diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 74da3f96653e4..8aa27eef72a5e 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -332,8 +332,8 @@ fn place_base_conflict<'a, 'gcx: 'tcx, 'tcx>( }, (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => { if promoted_1 == promoted_2 { - if let ty::Array(_, size) = s1.ty.sty { - if size.unwrap_usize(tcx) == 0 { + if let ty::Array(_, len) = s1.ty.sty { + if let Some(0) = len.assert_usize(tcx) { // Ignore conflicts with promoted [T; 0]. debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); return Overlap::Disjoint; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a416792101f73..fe94181047fcd 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -316,8 +316,9 @@ impl Qualif for HasMutInterior { } else if let ty::Array(_, len) = ty.sty { // FIXME(eddyb) the `cx.mode == Mode::Fn` condition // seems unnecessary, given that this is merely a ZST. - if !(len.unwrap_usize(cx.tcx) == 0 && cx.mode == Mode::Fn) { - return true; + match len.assert_usize(cx.tcx) { + Some(0) if cx.mode == Mode::Fn => {}, + _ => return true, } } else { return true; diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 5cd95a9d834c4..64e2eedd721ef 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -400,27 +400,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 6dd3c0113cdcd..b5a50f4387581 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/const-generics/issue-61422.rs b/src/test/ui/const-generics/issue-61422.rs new file mode 100644 index 0000000000000..3ccf38e561977 --- /dev/null +++ b/src/test/ui/const-generics/issue-61422.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +use std::mem; + +fn foo() { + let arr: [u8; SIZE] = unsafe { + let mut array: [u8; SIZE] = mem::uninitialized(); + array + }; +} + +fn main() {} diff --git a/src/test/ui/const-generics/issue-61422.stderr b/src/test/ui/const-generics/issue-61422.stderr new file mode 100644 index 0000000000000..4cb76ec4fe18c --- /dev/null +++ b/src/test/ui/const-generics/issue-61422.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61422.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.rs b/src/test/ui/const-generics/mut-ref-const-param-array.rs new file mode 100644 index 0000000000000..f930fb8796325 --- /dev/null +++ b/src/test/ui/const-generics/mut-ref-const-param-array.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +use std::ops::AddAssign; + +fn inc(v: &mut [T; N]) -> &mut [T; N] { + for x in v.iter_mut() { + *x += x.clone(); + } + v +} + +fn main() { + let mut v = [1, 2, 3]; + inc(&mut v); + assert_eq!(v, [2, 4, 6]); +} diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.stderr b/src/test/ui/const-generics/mut-ref-const-param-array.stderr new file mode 100644 index 0000000000000..261d3578a11ac --- /dev/null +++ b/src/test/ui/const-generics/mut-ref-const-param-array.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/mut-ref-const-param-array.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs new file mode 100644 index 0000000000000..794048174f903 --- /dev/null +++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -0,0 +1,11 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +use std::mem::MaybeUninit; + +#[repr(transparent)] +pub struct MaybeUninitWrapper(MaybeUninit<[u64; N]>); + +fn main() {} diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr new file mode 100644 index 0000000000000..661bbd113bc0d --- /dev/null +++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr @@ -0,0 +1,6 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs new file mode 100644 index 0000000000000..e5048d6e6e320 --- /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 0000000000000..f9281262bb71b --- /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`.