Check for array lengths that aren't actually usize
This commit is contained in:
parent
b57d93d8b9
commit
43a79a0f4b
3 changed files with 48 additions and 7 deletions
|
@ -647,13 +647,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
match place_ty.kind() {
|
match place_ty.kind() {
|
||||||
ty::Array(_elem_ty, len_const) => {
|
ty::Array(_elem_ty, len_const) => {
|
||||||
// We know how long an array is, so just use that as a constant
|
let ty_const = if let Some((_, len_ty)) = len_const.try_to_valtree()
|
||||||
// directly -- no locals needed. We do need one statement so
|
&& len_ty != self.tcx.types.usize
|
||||||
// that borrow- and initialization-checking consider it used,
|
{
|
||||||
// though. FIXME: Do we really *need* to count this as a use?
|
// Bad const generics can give us a constant from the type that's
|
||||||
// Could partial array tracking work off something else instead?
|
// not actually a `usize`, so in that case give an error instead.
|
||||||
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place);
|
// FIXME: It'd be nice if the type checker made sure this wasn't
|
||||||
let const_ = Const::from_ty_const(*len_const, usize_ty, self.tcx);
|
// 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_ }))
|
Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }))
|
||||||
}
|
}
|
||||||
ty::Slice(_elem_ty) => {
|
ty::Slice(_elem_ty) => {
|
||||||
|
|
15
tests/ui/const-generics/issues/index_array_bad_type.rs
Normal file
15
tests/ui/const-generics/issues/index_array_bad_type.rs
Normal file
|
@ -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]
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue