Skip to content

Commit

Permalink
Unrolled build for rust-lang#136205
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#136205 - compiler-errors:len-3, r=BoxyUwU

Properly check that array length is valid type during built-in unsizing in index

This results in duplicated errors, but this class of errors is not new; in general, we aren't really equipped to detect cases where a WF error due to a field type would be shadowed by the parent struct of that field also not being WF.

This also adds a note for these types of mismatches to make it clear that this is due to an array type.

Fixes rust-lang#134352

r? boxyuwu
  • Loading branch information
rust-timer authored Jan 29, 2025
2 parents a1d7676 + 7e68422 commit e03ed4a
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 9 deletions.
11 changes: 9 additions & 2 deletions compiler/rustc_hir_typeck/src/place_op.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,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");
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 0 additions & 6 deletions tests/crashes/131103.rs

This file was deleted.

2 changes: 2 additions & 0 deletions tests/ui/const-generics/bad-subst-const-kind.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/const-generics/issues/index_array_bad_type.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions tests/ui/const-generics/issues/index_array_bad_type.stderr
Original file line number Diff line number Diff line change
@@ -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

4 changes: 4 additions & 0 deletions tests/ui/const-generics/transmute-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/const-generics/type_mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/consts/bad-array-size-in-type-err.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit e03ed4a

Please sign in to comment.