Properly check that array length is valid type during built-in unsizing in index
This commit is contained in:
parent
fdd1a3b026
commit
7e68422859
13 changed files with 63 additions and 9 deletions
|
@ -1,6 +1,7 @@
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir_analysis::autoderef::Autoderef;
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::traits::{Obligation, ObligationCauseCode};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref,
|
||||
|
@ -136,8 +137,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut self_ty = adjusted_ty;
|
||||
if unsize {
|
||||
// We only unsize arrays here.
|
||||
if let ty::Array(element_ty, _) = adjusted_ty.kind() {
|
||||
self_ty = Ty::new_slice(self.tcx, *element_ty);
|
||||
if let ty::Array(element_ty, ct) = *adjusted_ty.kind() {
|
||||
self.register_predicate(Obligation::new(
|
||||
self.tcx,
|
||||
self.cause(base_expr.span, ObligationCauseCode::ArrayLen(adjusted_ty)),
|
||||
self.param_env,
|
||||
ty::ClauseKind::ConstArgHasType(ct, self.tcx.types.usize),
|
||||
));
|
||||
self_ty = Ty::new_slice(self.tcx, element_ty);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -194,6 +194,9 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
/// A slice or array is WF only if `T: Sized`.
|
||||
SliceOrArrayElem,
|
||||
|
||||
/// An array `[T; N]` can only be indexed (and is only well-formed if) `N` has type usize.
|
||||
ArrayLen(Ty<'tcx>),
|
||||
|
||||
/// A tuple is WF only if its middle elements are `Sized`.
|
||||
TupleElem,
|
||||
|
||||
|
|
|
@ -2770,6 +2770,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
ObligationCauseCode::SliceOrArrayElem => {
|
||||
err.note("slice and array elements must have `Sized` type");
|
||||
}
|
||||
ObligationCauseCode::ArrayLen(array_ty) => {
|
||||
err.note(format!("the length of array `{array_ty}` must be type `usize`"));
|
||||
}
|
||||
ObligationCauseCode::TupleElem => {
|
||||
err.note("only the last element of a tuple may have a dynamically sized type");
|
||||
}
|
||||
|
|
|
@ -689,7 +689,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||
self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
|
||||
// Note that the len being WF is implicitly checked while visiting.
|
||||
// Here we just check that it's of type usize.
|
||||
let cause = self.cause(ObligationCauseCode::Misc);
|
||||
let cause = self.cause(ObligationCauseCode::ArrayLen(t));
|
||||
self.out.push(traits::Obligation::with_depth(
|
||||
tcx,
|
||||
cause,
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
//@ known-bug: #131103
|
||||
struct Struct<const N: i128>(pub [u8; N]);
|
||||
|
||||
pub fn function(value: Struct<3>) -> u8 {
|
||||
value.0[0]
|
||||
}
|
|
@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
|
|||
|
|
||||
LL | impl<const N: u64> Q for [u8; N] {
|
||||
| ^^^^^^^ expected `usize`, found `u64`
|
||||
|
|
||||
= note: the length of array `[u8; N]` must be type `usize`
|
||||
|
||||
error: the constant `13` is not of type `u64`
|
||||
--> $DIR/bad-subst-const-kind.rs:13:24
|
||||
|
|
|
@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
|
|||
|
|
||||
LL | impl<const N: u64> Q for [u8; N] {}
|
||||
| ^^^^^^^ expected `usize`, found `u64`
|
||||
|
|
||||
= note: the length of array `[u8; N]` must be type `usize`
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `ASSOC`
|
||||
--> $DIR/type_mismatch.rs:8:1
|
||||
|
|
13
tests/ui/const-generics/issues/index_array_bad_type.rs
Normal file
13
tests/ui/const-generics/issues/index_array_bad_type.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
struct Struct<const N: i128>(pub [u8; N]);
|
||||
//~^ ERROR the constant `N` is not of type `usize`
|
||||
|
||||
pub fn function(value: Struct<3>) -> u8 {
|
||||
value.0[0]
|
||||
//~^ ERROR the constant `3` is not of type `usize`
|
||||
|
||||
// FIXME(const_generics): Ideally we wouldn't report the above error
|
||||
// b/c `Struct<_>` is never well formed, but I'd rather report too many
|
||||
// errors rather than ICE the compiler.
|
||||
}
|
||||
|
||||
fn main() {}
|
18
tests/ui/const-generics/issues/index_array_bad_type.stderr
Normal file
18
tests/ui/const-generics/issues/index_array_bad_type.stderr
Normal file
|
@ -0,0 +1,18 @@
|
|||
error: the constant `N` is not of type `usize`
|
||||
--> $DIR/index_array_bad_type.rs:1:34
|
||||
|
|
||||
LL | struct Struct<const N: i128>(pub [u8; N]);
|
||||
| ^^^^^^^ expected `usize`, found `i128`
|
||||
|
|
||||
= note: the length of array `[u8; N]` must be type `usize`
|
||||
|
||||
error: the constant `3` is not of type `usize`
|
||||
--> $DIR/index_array_bad_type.rs:5:5
|
||||
|
|
||||
LL | value.0[0]
|
||||
| ^^^^^^^ expected `usize`, found `i128`
|
||||
|
|
||||
= note: the length of array `[u8; 3]` must be type `usize`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -3,6 +3,8 @@ error: the constant `W` is not of type `usize`
|
|||
|
|
||||
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
| ^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
|
||||
= note: the length of array `[[u32; H]; W]` must be type `usize`
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:11:9
|
||||
|
@ -18,6 +20,8 @@ error: the constant `W` is not of type `usize`
|
|||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||
|
|
||||
= note: the length of array `[[u32; H]; W]` must be type `usize`
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:26:9
|
||||
|
|
|
@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
|
|||
|
|
||||
LL | fn bar<const N: u8>() -> [u8; N] {}
|
||||
| ^^^^^^^ expected `usize`, found `u8`
|
||||
|
|
||||
= note: the length of array `[u8; N]` must be type `usize`
|
||||
|
||||
error: the constant `N` is not of type `u8`
|
||||
--> $DIR/type_mismatch.rs:2:11
|
||||
|
|
|
@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
|
|||
|
|
||||
LL | arr: [i32; N],
|
||||
| ^^^^^^^^ expected `usize`, found `u8`
|
||||
|
|
||||
= note: the length of array `[i32; N]` must be type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-array-size-in-type-err.rs:7:38
|
||||
|
@ -15,6 +17,8 @@ error: the constant `2` is not of type `usize`
|
|||
|
|
||||
LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
|
||||
| ^^^^^^^^^ expected `usize`, found `u8`
|
||||
|
|
||||
= note: the length of array `[i32; 2]` must be type `usize`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ error: the constant `N` is not of type `usize`
|
|||
|
|
||||
LL | fn func<const N: u32>() -> [(); N];
|
||||
| ^^^^^^^ expected `usize`, found `u32`
|
||||
|
|
||||
= note: the length of array `[(); N]` must be type `usize`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue