From d43f980bfc14522b4513807438ddacb30870ce20 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Mon, 29 Jun 2026 15:48:15 -0700 Subject: [PATCH] check if len of array const arg matches the expected len --- .../src/hir_ty_lowering/mod.rs | 25 ++++++++++-- tests/crashes/160553.rs | 26 +++++++++++++ .../mgca/array-const-arg-len-mismatch.rs | 39 +++++++++++++++++++ .../mgca/array-const-arg-len-mismatch.stderr | 32 +++++++++++++++ 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 tests/crashes/160553.rs create mode 100644 tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs create mode 100644 tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr 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 fa3dca042ba0c..c590540914496 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2478,13 +2478,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Const<'tcx> { let tcx = self.tcx(); - let elem_ty = match ty.kind() { - ty::Array(elem_ty, _) => elem_ty, + let (elem_ty, len) = match ty.kind() { + ty::Array(elem_ty, len) => (elem_ty, len), ty::Error(e) => return Const::new_error(tcx, *e), _ => { let e = tcx .dcx() - .span_err(array_expr.span, format!("expected `{}`, found const array", ty)); + .span_err(array_expr.span, format!("expected `{ty}`, found const array")); return Const::new_error(tcx, e); } }; @@ -2495,6 +2495,25 @@ 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); + } + let valtree = ty::ValTree::from_branches(tcx, elems); ty::Const::new_value(tcx, valtree, ty) diff --git a/tests/crashes/160553.rs b/tests/crashes/160553.rs new file mode 100644 index 0000000000000..faf993e102756 --- /dev/null +++ b/tests/crashes/160553.rs @@ -0,0 +1,26 @@ +//@ known-bug: #160553 +//@ compile-flags: -Copt-level=0 +#![allow(incomplete_features)] +#![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(generic_const_parameter_types)] + +trait Trait { + type const LEN: usize; +} + +struct S; +impl Trait for S { + type const LEN: usize = 2; +} + +fn foo::LEN]>() -> [u8; ::LEN] { + A +} + +fn bar() -> [u8; ::LEN] { + foo::() +} + +fn main() { + bar::(); +} 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 new file mode 100644 index 0000000000000..10b824fed4f36 --- /dev/null +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -0,0 +1,39 @@ +//! Regression test for #155168 +//! +//! Ensure that providing an array const arg with the wrong number of elements +//! doesn't ICE or silently cause UB. +#![expect(incomplete_features)] +#![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(unsized_const_params, generic_const_parameter_types)] + +use std::marker::ConstParamTy_; + +fn foo() -> [T; N] { + M +} + +fn bar() {} + +trait Trait { + type const LEN: usize; +} + +struct S; +impl Trait for S { + type const LEN: usize = 3; +} + +fn baz::LEN]>() {} + +fn main() { + foo::(); + //~^ ERROR: expected array with 2 elements, found 0 elements + foo::(); + //~^ ERROR: expected array with 2 elements, found 3 elements + bar::<{ [] }>(); + //~^ ERROR: expected array with 2 elements, found 0 elements + bar::<{ [1, 2, 3] }>(); + //~^ ERROR: expected array with 2 elements, found 3 elements + baz::<{ [42] }>(); + //~^ ERROR: expected array with 3 elements, found 1 elements +} 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 new file mode 100644 index 0000000000000..42eea34bf6bc7 --- /dev/null +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr @@ -0,0 +1,32 @@ +error: expected array with 2 elements, found 0 elements + --> $DIR/array-const-arg-len-mismatch.rs:29:20 + | +LL | foo::(); + | ^^ + +error: expected array with 2 elements, found 3 elements + --> $DIR/array-const-arg-len-mismatch.rs:31:20 + | +LL | foo::(); + | ^^^^^^^^^ + +error: expected array with 2 elements, found 0 elements + --> $DIR/array-const-arg-len-mismatch.rs:33:13 + | +LL | bar::<{ [] }>(); + | ^^ + +error: expected array with 2 elements, found 3 elements + --> $DIR/array-const-arg-len-mismatch.rs:35:13 + | +LL | bar::<{ [1, 2, 3] }>(); + | ^^^^^^^^^ + +error: expected array with 3 elements, found 1 elements + --> $DIR/array-const-arg-len-mismatch.rs:37:13 + | +LL | baz::<{ [42] }>(); + | ^^^^ + +error: aborting due to 5 previous errors +