Skip to content

Commit

Permalink
Rollup merge of #133367 - compiler-errors:array-len-mismatch, r=BoxyUwU
Browse files Browse the repository at this point in the history
Simplify array length mismatch error reporting (to not try to turn consts into target usizes)

This changes `TypeError::FixedArrayLen` to use `ExpectedFound<ty::Const<'tcx>>` (instead of `ExpectedFound<u64>`), and renames it to `TypeError::ArrayLen`. This allows us to avoid a `try_to_target_usize` call in the type relation, which ICEs when we have a scalar of the wrong bit length (i.e. u8).

This also makes `structurally_relate_tys` to always use this type error kind any time we have a const mismatch resulting from relating the array-len part of `[T; N]`.

This has the effect of changing the error message we issue for array length mismatches involving non-valtree consts. I actually quite like the change, though, since before:

```
LL | fn test<const N: usize, const M: usize>() -> [u8; M] {
   |                                              ------- expected `[u8; M]` because of return type
LL |     [0; N]
   |     ^^^^^^ expected `M`, found `N`
   |
   = note: expected array `[u8; M]`
              found array `[u8; N]`
```

and after, which I think is far less verbose:

```
LL | fn test<const N: usize, const M: usize>() -> [u8; M] {
   |                                              ------- expected `[u8; M]` because of return type
LL |     [0; N]
   |     ^^^^^^ expected an array with a size of M, found one with a size of N
```

The only questions I have are:
1. Should we do something about backticks here? Right now we don't backtick either fully evaluated consts like `2`, or rigid consts like `Foo::BAR`.... but maybe we should? It seems kinda verbose to do for numbers -- maybe we could intercept those specifically.
2. I guess we may still run the risk of leaking unevaluated consts into error reporting like `2 + 1`...?

r? ``@BoxyUwU``

Fixes #126359
Fixes #131101
  • Loading branch information
compiler-errors authored Nov 26, 2024
2 parents 479de1f + 28970a2 commit cf09718
Show file tree
Hide file tree
Showing 18 changed files with 60 additions and 71 deletions.
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,6 @@ impl<'tcx> Const<'tcx> {
}

impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
fn try_to_target_usize(self, interner: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_target_usize(interner)
}

fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
Const::new_infer(tcx, infer)
}
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@ impl<'tcx> TypeError<'tcx> {
pluralize!(values.found)
)
.into(),
TypeError::FixedArraySize(values) => format!(
"expected an array with a fixed size of {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
TypeError::ArraySize(values) => format!(
"expected an array with a size of {}, found one with a size of {}",
values.expected, values.found,
)
.into(),
TypeError::ArgCount => "incorrect number of function parameters".into(),
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1792,12 +1792,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {

fn suggest_specify_actual_length(
&self,
terr: TypeError<'_>,
trace: &TypeTrace<'_>,
terr: TypeError<'tcx>,
trace: &TypeTrace<'tcx>,
span: Span,
) -> Option<TypeErrorAdditionalDiags> {
let hir = self.tcx.hir();
let TypeError::FixedArraySize(sz) = terr else {
let TypeError::ArraySize(sz) = terr else {
return None;
};
let tykind = match self.tcx.hir_node_by_def_id(trace.cause.body_id) {
Expand Down Expand Up @@ -1838,9 +1838,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let Some(tykind) = tykind
&& let hir::TyKind::Array(_, length) = tykind
&& let hir::ArrayLen::Body(ct) = length
&& let Some((scalar, ty)) = sz.found.try_to_scalar()
&& ty == self.tcx.types.usize
{
let span = ct.span();
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength {
span,
length: scalar.to_target_usize(&self.tcx).unwrap(),
})
} else {
None
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_type_ir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub enum TypeError<I: Interner> {
Mutability,
ArgumentMutability(usize),
TupleSize(ExpectedFound<usize>),
FixedArraySize(ExpectedFound<u64>),
ArraySize(ExpectedFound<I::Const>),
ArgCount,

RegionsDoesNotOutlive(I::Region, I::Region),
Expand Down Expand Up @@ -69,7 +69,7 @@ impl<I: Interner> TypeError<I> {
use self::TypeError::*;
match self {
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | PolarityMismatch(_) | Mismatch
| AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
| AbiMismatch(_) | ArraySize(_) | ArgumentSorts(..) | Sorts(_)
| VariadicMismatch(_) | TargetFeatureCast(_) => false,

Mutability
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_type_ir/src/inherent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,6 @@ pub trait Const<I: Interner<Const = Self>>:
+ Relate<I>
+ Flags
{
fn try_to_target_usize(self, interner: I) -> Option<u64>;

fn new_infer(interner: I, var: ty::InferConst) -> Self;

fn new_var(interner: I, var: ty::ConstVid) -> Self;
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_type_ir/src/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,19 +501,10 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
let t = relation.relate(a_t, b_t)?;
match relation.relate(sz_a, sz_b) {
Ok(sz) => Ok(Ty::new_array_with_const_len(cx, t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
let sz_a = sz_a.try_to_target_usize(cx);
let sz_b = sz_b.try_to_target_usize(cx);

match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => {
Err(TypeError::FixedArraySize(ExpectedFound::new(sz_a_val, sz_b_val)))
}
_ => Err(err),
}
Err(TypeError::ConstMismatch(_)) => {
Err(TypeError::ArraySize(ExpectedFound::new(sz_a, sz_b)))
}
Err(e) => Err(e),
}
}

Expand Down
9 changes: 0 additions & 9 deletions tests/crashes/126359.rs

This file was deleted.

12 changes: 0 additions & 12 deletions tests/crashes/131101.rs

This file was deleted.

5 changes: 1 addition & 4 deletions tests/ui/array-slice-vec/match_arr_unknown_len.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ error[E0308]: mismatched types
--> $DIR/match_arr_unknown_len.rs:3:9
|
LL | [1, 2] => true,
| ^^^^^^ expected `2`, found `N`
|
= note: expected array `[u32; 2]`
found array `[u32; N]`
| ^^^^^^ expected an array with a size of 2, found one with a size of N

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/const-argument-cross-crate-mismatch.rs:6:67
|
LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
| ------------------------- ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
| ------------------------- ^^^^^^^^^^ expected an array with a size of 3, found one with a size of 2
| |
| arguments to this struct are incorrect
|
Expand All @@ -16,7 +16,7 @@ error[E0308]: mismatched types
--> $DIR/const-argument-cross-crate-mismatch.rs:8:65
|
LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
| ------------------------- ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
| ------------------------- ^^^^^^^^^^^^^^^ expected an array with a size of 2, found one with a size of 3
| |
| arguments to this struct are incorrect
|
Expand Down
5 changes: 1 addition & 4 deletions tests/ui/const-generics/generic-param-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ error[E0308]: mismatched types
LL | fn test<const N: usize, const M: usize>() -> [u8; M] {
| ------- expected `[u8; M]` because of return type
LL | [0; N]
| ^^^^^^ expected `M`, found `N`
|
= note: expected array `[u8; M]`
found array `[u8; N]`
| ^^^^^^ expected an array with a size of M, found one with a size of N

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ error[E0308]: mismatched types
--> $DIR/issue-62504.rs:18:21
|
LL | ArrayHolder([0; Self::SIZE])
| ----------- ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
| ----------- ^^^^^^^^^^^^^^^ expected an array with a size of X, found one with a size of Self::SIZE
| |
| arguments to this struct are incorrect
|
= note: expected array `[u32; X]`
found array `[u32; Self::SIZE]`
note: tuple struct defined here
--> $DIR/issue-62504.rs:14:8
|
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/consts/array-literal-len-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/array-literal-len-mismatch.rs:1:26
|
LL | const NUMBERS: [u8; 3] = [10, 20];
| - ^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
| - ^^^^^^^^ expected an array with a size of 3, found one with a size of 2
| |
| help: consider specifying the actual array length: `2`

Expand Down
10 changes: 10 additions & 0 deletions tests/ui/consts/bad-array-size-in-type-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
struct BadArraySize<const N: u8> {
arr: [i32; N],
//~^ ERROR the constant `N` is not of type `usize`
}

fn main() {
let _ = BadArraySize::<2> { arr: [0, 0, 0] };
//~^ ERROR mismatched types
//~| ERROR the constant `2` is not of type `usize`
}
21 changes: 21 additions & 0 deletions tests/ui/consts/bad-array-size-in-type-err.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error: the constant `N` is not of type `usize`
--> $DIR/bad-array-size-in-type-err.rs:2:10
|
LL | arr: [i32; N],
| ^^^^^^^^ expected `usize`, found `u8`

error[E0308]: mismatched types
--> $DIR/bad-array-size-in-type-err.rs:7:38
|
LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
| ^^^^^^^^^ expected an array with a size of 2, found one with a size of 3

error: the constant `2` is not of type `usize`
--> $DIR/bad-array-size-in-type-err.rs:7:38
|
LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
| ^^^^^^^^^ expected `usize`, found `u8`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
4 changes: 2 additions & 2 deletions tests/ui/consts/const-array-oob-arith.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ const VAL: i32 = ARR[IDX];
const BONG: [i32; (ARR[0] - 41) as usize] = [5];
const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
//~^ ERROR: mismatched types
//~| expected an array with a fixed size of 2 elements, found one with 1 element
//~| expected an array
const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
//~^ ERROR: mismatched types
//~| expected an array with a fixed size of 1 element, found one with 2 elements
//~| expected an array

fn main() {
let _ = VAL;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/const-array-oob-arith.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ error[E0308]: mismatched types
--> $DIR/const-array-oob-arith.rs:5:45
|
LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
| ---------------------- ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
| ---------------------- ^^^ expected an array with a size of 2, found one with a size of 1
| |
| help: consider specifying the actual array length: `1`

error[E0308]: mismatched types
--> $DIR/const-array-oob-arith.rs:8:44
|
LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
| ---------------------- ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
| ---------------------- ^^^^^^^ expected an array with a size of 1, found one with a size of 2
| |
| help: consider specifying the actual array length: `2`

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/inference/array-len-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/array-len-mismatch.rs:6:26
|
LL | let wrong: [u8; 3] = [10, 20];
| ------- ^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
| ------- ^^^^^^^^ expected an array with a size of 3, found one with a size of 2
| | |
| | help: consider specifying the actual array length: `2`
| expected due to this
Expand All @@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/array-len-mismatch.rs:9:26
|
LL | let wrong: [u8; 3] = returns_arr();
| ------- ^^^^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
| ------- ^^^^^^^^^^^^^ expected an array with a size of 3, found one with a size of 2
| | |
| | help: consider specifying the actual array length: `2`
| expected due to this
Expand Down

0 comments on commit cf09718

Please sign in to comment.