mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-01 02:14:20 +00:00
Rollup merge of #133367 - compiler-errors:array-len-mismatch, r=BoxyUwU
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
This commit is contained in:
commit
cf09718876
@ -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)
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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) {
|
||||
@ -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
|
||||
}
|
||||
|
@ -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),
|
||||
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
//@ known-bug: rust-lang/rust#126359
|
||||
|
||||
struct OppOrder<const N: u8 = 3, T = u32> {
|
||||
arr: [T; N],
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = OppOrder::<3, u32> { arr: [0, 0, 0] };
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
//@ known-bug: #131101
|
||||
trait Foo<const N: u8> {
|
||||
fn do_x(&self) -> [u8; N];
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo<const 3> for Bar {
|
||||
fn do_x(&self) -> [u8; 3] {
|
||||
[0u8; 3]
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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`
|
||||
|
||||
|
10
tests/ui/consts/bad-array-size-in-type-err.rs
Normal file
10
tests/ui/consts/bad-array-size-in-type-err.rs
Normal file
@ -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
tests/ui/consts/bad-array-size-in-type-err.stderr
Normal file
21
tests/ui/consts/bad-array-size-in-type-err.stderr
Normal file
@ -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,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;
|
||||
|
@ -2,7 +2,7 @@ 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`
|
||||
|
||||
@ -10,7 +10,7 @@ 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`
|
||||
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user