Skip to content

Commit e8289d8

Browse files
authored
Rollup merge of #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 #134352 r? boxyuwu
2 parents 9365547 + 7e68422 commit e8289d8

File tree

13 files changed

+63
-9
lines changed

13 files changed

+63
-9
lines changed

Diff for: compiler/rustc_hir_typeck/src/place_op.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_errors::Applicability;
22
use rustc_hir_analysis::autoderef::Autoderef;
33
use rustc_infer::infer::InferOk;
4+
use rustc_infer::traits::{Obligation, ObligationCauseCode};
45
use rustc_middle::span_bug;
56
use rustc_middle::ty::adjustment::{
67
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref,
@@ -136,8 +137,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
136137
let mut self_ty = adjusted_ty;
137138
if unsize {
138139
// We only unsize arrays here.
139-
if let ty::Array(element_ty, _) = adjusted_ty.kind() {
140-
self_ty = Ty::new_slice(self.tcx, *element_ty);
140+
if let ty::Array(element_ty, ct) = *adjusted_ty.kind() {
141+
self.register_predicate(Obligation::new(
142+
self.tcx,
143+
self.cause(base_expr.span, ObligationCauseCode::ArrayLen(adjusted_ty)),
144+
self.param_env,
145+
ty::ClauseKind::ConstArgHasType(ct, self.tcx.types.usize),
146+
));
147+
self_ty = Ty::new_slice(self.tcx, element_ty);
141148
} else {
142149
continue;
143150
}

Diff for: compiler/rustc_middle/src/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ pub enum ObligationCauseCode<'tcx> {
194194
/// A slice or array is WF only if `T: Sized`.
195195
SliceOrArrayElem,
196196

197+
/// An array `[T; N]` can only be indexed (and is only well-formed if) `N` has type usize.
198+
ArrayLen(Ty<'tcx>),
199+
197200
/// A tuple is WF only if its middle elements are `Sized`.
198201
TupleElem,
199202

Diff for: compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
27692769
ObligationCauseCode::SliceOrArrayElem => {
27702770
err.note("slice and array elements must have `Sized` type");
27712771
}
2772+
ObligationCauseCode::ArrayLen(array_ty) => {
2773+
err.note(format!("the length of array `{array_ty}` must be type `usize`"));
2774+
}
27722775
ObligationCauseCode::TupleElem => {
27732776
err.note("only the last element of a tuple may have a dynamically sized type");
27742777
}

Diff for: compiler/rustc_trait_selection/src/traits/wf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
689689
self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
690690
// Note that the len being WF is implicitly checked while visiting.
691691
// Here we just check that it's of type usize.
692-
let cause = self.cause(ObligationCauseCode::Misc);
692+
let cause = self.cause(ObligationCauseCode::ArrayLen(t));
693693
self.out.push(traits::Obligation::with_depth(
694694
tcx,
695695
cause,

Diff for: tests/crashes/131103.rs

-6
This file was deleted.

Diff for: tests/ui/const-generics/bad-subst-const-kind.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
33
|
44
LL | impl<const N: u64> Q for [u8; N] {
55
| ^^^^^^^ expected `usize`, found `u64`
6+
|
7+
= note: the length of array `[u8; N]` must be type `usize`
68

79
error: the constant `13` is not of type `u64`
810
--> $DIR/bad-subst-const-kind.rs:13:24

Diff for: tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
33
|
44
LL | impl<const N: u64> Q for [u8; N] {}
55
| ^^^^^^^ expected `usize`, found `u64`
6+
|
7+
= note: the length of array `[u8; N]` must be type `usize`
68

79
error[E0046]: not all trait items implemented, missing: `ASSOC`
810
--> $DIR/type_mismatch.rs:8:1
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct Struct<const N: i128>(pub [u8; N]);
2+
//~^ ERROR the constant `N` is not of type `usize`
3+
4+
pub fn function(value: Struct<3>) -> u8 {
5+
value.0[0]
6+
//~^ ERROR the constant `3` is not of type `usize`
7+
8+
// FIXME(const_generics): Ideally we wouldn't report the above error
9+
// b/c `Struct<_>` is never well formed, but I'd rather report too many
10+
// errors rather than ICE the compiler.
11+
}
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: the constant `N` is not of type `usize`
2+
--> $DIR/index_array_bad_type.rs:1:34
3+
|
4+
LL | struct Struct<const N: i128>(pub [u8; N]);
5+
| ^^^^^^^ expected `usize`, found `i128`
6+
|
7+
= note: the length of array `[u8; N]` must be type `usize`
8+
9+
error: the constant `3` is not of type `usize`
10+
--> $DIR/index_array_bad_type.rs:5:5
11+
|
12+
LL | value.0[0]
13+
| ^^^^^^^ expected `usize`, found `i128`
14+
|
15+
= note: the length of array `[u8; 3]` must be type `usize`
16+
17+
error: aborting due to 2 previous errors
18+

Diff for: tests/ui/const-generics/transmute-fail.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: the constant `W` is not of type `usize`
33
|
44
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
55
| ^^^^^^^^^^^^^ expected `usize`, found `bool`
6+
|
7+
= note: the length of array `[[u32; H]; W]` must be type `usize`
68

79
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
810
--> $DIR/transmute-fail.rs:11:9
@@ -18,6 +20,8 @@ error: the constant `W` is not of type `usize`
1820
|
1921
LL | std::mem::transmute(v)
2022
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
23+
|
24+
= note: the length of array `[[u32; H]; W]` must be type `usize`
2125

2226
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
2327
--> $DIR/transmute-fail.rs:26:9

Diff for: tests/ui/const-generics/type_mismatch.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
33
|
44
LL | fn bar<const N: u8>() -> [u8; N] {}
55
| ^^^^^^^ expected `usize`, found `u8`
6+
|
7+
= note: the length of array `[u8; N]` must be type `usize`
68

79
error: the constant `N` is not of type `u8`
810
--> $DIR/type_mismatch.rs:2:11

Diff for: tests/ui/consts/bad-array-size-in-type-err.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: the constant `N` is not of type `usize`
33
|
44
LL | arr: [i32; N],
55
| ^^^^^^^^ expected `usize`, found `u8`
6+
|
7+
= note: the length of array `[i32; N]` must be type `usize`
68

79
error[E0308]: mismatched types
810
--> $DIR/bad-array-size-in-type-err.rs:7:38
@@ -15,6 +17,8 @@ error: the constant `2` is not of type `usize`
1517
|
1618
LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
1719
| ^^^^^^^^^ expected `usize`, found `u8`
20+
|
21+
= note: the length of array `[i32; 2]` must be type `usize`
1822

1923
error: aborting due to 3 previous errors
2024

Diff for: tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.current.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ error: the constant `N` is not of type `usize`
99
|
1010
LL | fn func<const N: u32>() -> [(); N];
1111
| ^^^^^^^ expected `usize`, found `u32`
12+
|
13+
= note: the length of array `[(); N]` must be type `usize`
1214

1315
error: aborting due to 2 previous errors
1416

0 commit comments

Comments
 (0)