diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index b659dd896aba0..459fa290dd02b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2492,8 +2492,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Const<'tcx> { let tcx = self.tcx(); - let (elem_ty, len) = match ty.kind() { - ty::Array(elem_ty, len) => (elem_ty, len), + let elem_ty = match ty.kind() { + ty::Array(elem_ty, _) => elem_ty, ty::Error(e) => return Const::new_error(tcx, *e), _ => { let e = tcx @@ -2509,28 +2509,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|elem| self.lower_const_arg(elem, *elem_ty)) .collect::>(); - let len = tcx - .try_normalize_erasing_regions( - ty::TypingEnv::new(ty::ParamEnv::empty(), TypingMode::non_body_analysis()), - Unnormalized::new_wip(*len), - ) - .unwrap_or(*len); - if let Some(expected_len) = len.try_to_target_usize(tcx) - && expected_len != elems.len() as u64 - { - let e = tcx.dcx().span_err( - array_expr.span, - format!( - "expected array with {expected_len} elements, found {} elements", - array_expr.elems.len() - ), - ); - return Const::new_error(tcx, e); - } - + // The array len passed in the type might be an infer var, or a const param, or it could + // just be an incorrect constant. So, construct the resulting valtree's type based on the + // provided syntax rather than the expected type. The surrounding typeck will catch any + // mismatches. + let valtree_ty = Ty::new_array(tcx, *elem_ty, elems.len() as u64); let valtree = ty::ValTree::from_branches(tcx, elems); - - ty::Const::new_value(tcx, valtree, ty) + ty::Const::new_value(tcx, valtree, valtree_ty) } fn try_recover_misrepresented_function_call( diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs index 5656d55d9f9c6..f2c8a242dbcc0 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -28,13 +28,13 @@ fn baz::LEN]>() {} fn main() { foo::(); - //~^ ERROR: expected array with 2 elements, found 0 elements + //~^ ERROR: the constant `*b""` is not of type `[u8; 2]` foo::(); - //~^ ERROR: expected array with 2 elements, found 3 elements + //~^ ERROR: the constant `*b"\x00\x00\x00"` is not of type `[u8; 2]` bar::<{ [] }>(); - //~^ ERROR: expected array with 2 elements, found 0 elements + //~^ ERROR: the constant `*b""` is not of type `[u8; 2]` bar::<{ [1, 2, 3] }>(); - //~^ ERROR: expected array with 2 elements, found 3 elements + //~^ ERROR: the constant `*b"\x01\x02\x03"` is not of type `[u8; 2]` baz::<{ [42] }>(); - //~^ ERROR: expected array with 3 elements, found 1 elements + //~^ ERROR: the constant `*b"*"` is not of type `[u8; 3]` } diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr index e83b0e98dfe6c..82a9cfc86b5d7 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr @@ -1,32 +1,62 @@ -error: expected array with 2 elements, found 0 elements - --> $DIR/array-const-arg-len-mismatch.rs:30:20 +error: the constant `*b""` is not of type `[u8; 2]` + --> $DIR/array-const-arg-len-mismatch.rs:30:11 | LL | foo::(); - | ^^ + | ^^ expected `[u8; 2]`, found `[u8; 0]` + | +note: required by a const generic parameter in `foo` + --> $DIR/array-const-arg-len-mismatch.rs:11:42 + | +LL | fn foo() -> [T; N] { + | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` -error: expected array with 2 elements, found 3 elements - --> $DIR/array-const-arg-len-mismatch.rs:32:20 +error: the constant `*b"\x00\x00\x00"` is not of type `[u8; 2]` + --> $DIR/array-const-arg-len-mismatch.rs:32:11 | LL | foo::(); - | ^^^^^^^^^ + | ^^ expected `[u8; 2]`, found `[u8; 3]` + | +note: required by a const generic parameter in `foo` + --> $DIR/array-const-arg-len-mismatch.rs:11:42 + | +LL | fn foo() -> [T; N] { + | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` -error: expected array with 2 elements, found 0 elements +error: the constant `*b""` is not of type `[u8; 2]` --> $DIR/array-const-arg-len-mismatch.rs:34:13 | LL | bar::<{ [] }>(); - | ^^ + | ^^ expected `[u8; 2]`, found `[u8; 0]` + | +note: required by a const generic parameter in `bar` + --> $DIR/array-const-arg-len-mismatch.rs:15:8 + | +LL | fn bar() {} + | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` -error: expected array with 2 elements, found 3 elements +error: the constant `*b"\x01\x02\x03"` is not of type `[u8; 2]` --> $DIR/array-const-arg-len-mismatch.rs:36:13 | LL | bar::<{ [1, 2, 3] }>(); - | ^^^^^^^^^ + | ^^^^^^^^^ expected `[u8; 2]`, found `[u8; 3]` + | +note: required by a const generic parameter in `bar` + --> $DIR/array-const-arg-len-mismatch.rs:15:8 + | +LL | fn bar() {} + | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` -error: expected array with 3 elements, found 1 elements +error: the constant `*b"*"` is not of type `[u8; 3]` --> $DIR/array-const-arg-len-mismatch.rs:38:13 | LL | baz::<{ [42] }>(); - | ^^^^ + | ^^^^ expected `[u8; 3]`, found `[u8; 1]` + | +note: required by a const generic parameter in `baz` + --> $DIR/array-const-arg-len-mismatch.rs:27:8 + | +LL | fn baz::LEN]>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `baz` error: aborting due to 5 previous errors diff --git a/tests/crashes/160553.rs b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs similarity index 79% rename from tests/crashes/160553.rs rename to tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs index dc5628cf598fb..2c680a37ea1f9 100644 --- a/tests/crashes/160553.rs +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs @@ -1,5 +1,4 @@ -//@ known-bug: #160553 -//@ compile-flags: -Copt-level=0 +//! Regression test for #160553 (used to ICE) #![allow(incomplete_features)] #![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] #![feature(generic_const_parameter_types)] @@ -20,6 +19,7 @@ fn foo::LEN]>() -> [u8; ::LEN] fn bar() -> [u8; ::LEN] { foo::() + //~^ ERROR the constant `*b"\x01\x02\x03"` is not of type `[u8; ::LEN]` } fn main() { diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr new file mode 100644 index 0000000000000..c9ee69146f326 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr @@ -0,0 +1,14 @@ +error: the constant `*b"\x01\x02\x03"` is not of type `[u8; ::LEN]` + --> $DIR/generic_const_items-mismatched-array-len.rs:21:11 + | +LL | foo::() + | ^ expected `[u8; ::LEN]`, found `[u8; 3]` + | +note: required by a const generic parameter in `foo` + --> $DIR/generic_const_items-mismatched-array-len.rs:16:18 + | +LL | fn foo::LEN]>() -> [u8; ::LEN] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs new file mode 100644 index 0000000000000..5891e66aa77b0 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs @@ -0,0 +1,8 @@ +//@ check-pass + +#![feature(min_adt_const_params, min_generic_const_args, generic_const_parameter_types)] +fn foo() {} + +fn main() { + foo::<_, core::direct_const_arg!([0, 1, 2, 3])>(); +}