diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-12-16 20:00:26 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-16 20:00:26 +0100 |
| commit | 7c301ecdf5e806b7aa3c44e4a185049fabbc4381 (patch) | |
| tree | 6d6c2ff00fee0ca77041191129d0f875a7d61c86 | |
| parent | dffaad83327454430129802f240121f8c7866208 (diff) | |
| parent | 43a79a0f4bf842c5e6a4ada2e6280fc9535c18ee (diff) | |
| download | rust-7c301ecdf5e806b7aa3c44e4a185049fabbc4381.tar.gz rust-7c301ecdf5e806b7aa3c44e4a185049fabbc4381.zip | |
Rollup merge of #134371 - scottmcm:fix-134352, r=oli-obk
Check for array lengths that aren't actually `usize` I wish typeck wouldn't give us `ty::Array`s that have this problem in the first place, but we can check for it. Fixes #134352 cc ``@matthiaskrgr``
3 files changed, 48 insertions, 7 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 70a74910a68..89a1f06d3d1 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -647,13 +647,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match place_ty.kind() { ty::Array(_elem_ty, len_const) => { - // We know how long an array is, so just use that as a constant - // directly -- no locals needed. We do need one statement so - // that borrow- and initialization-checking consider it used, - // though. FIXME: Do we really *need* to count this as a use? - // Could partial array tracking work off something else instead? - self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place); - let const_ = Const::from_ty_const(*len_const, usize_ty, self.tcx); + let ty_const = if let Some((_, len_ty)) = len_const.try_to_valtree() + && len_ty != self.tcx.types.usize + { + // Bad const generics can give us a constant from the type that's + // not actually a `usize`, so in that case give an error instead. + // FIXME: It'd be nice if the type checker made sure this wasn't + // possible, instead. + let err = self.tcx.dcx().span_delayed_bug( + span, + format!( + "Array length should have already been a type error, as it's {len_ty:?}" + ), + ); + ty::Const::new_error(self.tcx, err) + } else { + // We know how long an array is, so just use that as a constant + // directly -- no locals needed. We do need one statement so + // that borrow- and initialization-checking consider it used, + // though. FIXME: Do we really *need* to count this as a use? + // Could partial array tracking work off something else instead? + self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place); + *len_const + }; + + let const_ = Const::from_ty_const(ty_const, usize_ty, self.tcx); Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ })) } ty::Slice(_elem_ty) => { diff --git a/tests/ui/const-generics/issues/index_array_bad_type.rs b/tests/ui/const-generics/issues/index_array_bad_type.rs new file mode 100644 index 00000000000..41e4dba026c --- /dev/null +++ b/tests/ui/const-generics/issues/index_array_bad_type.rs @@ -0,0 +1,15 @@ +//@ check-fail +//@ compile-flags: -C opt-level=0 + +#![crate_type = "lib"] + +// This used to fail in the known-panics lint, as the MIR was ill-typed due to +// the length constant not actually having type usize. +// https://github.com/rust-lang/rust/issues/134352 + +pub struct BadStruct<const N: i64>(pub [u8; N]); +//~^ ERROR: the constant `N` is not of type `usize` + +pub fn bad_array_length_type(value: BadStruct<3>) -> u8 { + value.0[0] +} diff --git a/tests/ui/const-generics/issues/index_array_bad_type.stderr b/tests/ui/const-generics/issues/index_array_bad_type.stderr new file mode 100644 index 00000000000..e4417192150 --- /dev/null +++ b/tests/ui/const-generics/issues/index_array_bad_type.stderr @@ -0,0 +1,8 @@ +error: the constant `N` is not of type `usize` + --> $DIR/index_array_bad_type.rs:10:40 + | +LL | pub struct BadStruct<const N: i64>(pub [u8; N]); + | ^^^^^^^ expected `usize`, found `i64` + +error: aborting due to 1 previous error + |
