check the types in ty::Value
to value conversion
and remove `ty::Const::try_to_scalar` because it becomes redundant
This commit is contained in:
parent
10fc0b159e
commit
0055fb92db
7 changed files with 75 additions and 22 deletions
|
@ -5,7 +5,6 @@ use rustc_error_messages::MultiSpan;
|
|||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||
|
||||
use crate::mir::interpret::Scalar;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
|
||||
mod int;
|
||||
|
@ -230,12 +229,6 @@ impl<'tcx> Const<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> {
|
||||
let cv = self.try_to_value()?;
|
||||
Some((cv.valtree.try_to_scalar()?, cv.ty))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||
self.try_to_value()?.try_to_target_usize(tcx)
|
||||
|
|
|
@ -117,9 +117,13 @@ pub struct Value<'tcx> {
|
|||
impl<'tcx> Value<'tcx> {
|
||||
/// Attempts to extract the raw bits from the constant.
|
||||
///
|
||||
/// Fails if the value can't be represented as bits (e.g. because it is an aggregate).
|
||||
/// Fails if the value can't be represented as bits (e.g. because it is a reference
|
||||
/// or an aggregate).
|
||||
#[inline]
|
||||
pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
|
||||
let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else {
|
||||
return None;
|
||||
};
|
||||
let scalar = self.valtree.try_to_scalar_int()?;
|
||||
let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty);
|
||||
let size = tcx.layout_of(input).ok()?.size;
|
||||
|
@ -127,10 +131,16 @@ impl<'tcx> Value<'tcx> {
|
|||
}
|
||||
|
||||
pub fn try_to_bool(self) -> Option<bool> {
|
||||
if !self.ty.is_bool() {
|
||||
return None;
|
||||
}
|
||||
self.valtree.try_to_scalar_int()?.try_to_bool().ok()
|
||||
}
|
||||
|
||||
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||
if !self.ty.is_usize() {
|
||||
return None;
|
||||
}
|
||||
self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,8 +51,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
|
|||
// Transforms a ty:Ty for being encoded and used in the substitution dictionary.
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match t.kind() {
|
||||
ty::Array(..)
|
||||
| ty::Closure(..)
|
||||
ty::Closure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
|
@ -67,6 +66,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
|
|||
| ty::Tuple(..)
|
||||
| ty::UnsafeBinder(_) => t.super_fold_with(self),
|
||||
|
||||
// Don't transform the type of the array length and keep it as `usize`.
|
||||
// This is required for `try_to_target_usize` to work correctly.
|
||||
&ty::Array(inner, len) => {
|
||||
let inner = self.fold_ty(inner);
|
||||
Ty::new_array_with_const_len(self.tcx, inner, len)
|
||||
}
|
||||
|
||||
ty::Bool => {
|
||||
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
||||
// Note: on all platforms that Rust's currently supports, its size and alignment
|
||||
|
|
|
@ -2023,14 +2023,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
_ => None,
|
||||
};
|
||||
if let Some(tykind) = tykind
|
||||
&& let hir::TyKind::Array(_, length) = tykind
|
||||
&& let Some((scalar, ty)) = sz.found.try_to_scalar()
|
||||
&& ty == self.tcx.types.usize
|
||||
&& let hir::TyKind::Array(_, length_arg) = tykind
|
||||
&& let Some(length_val) = sz.found.try_to_target_usize(self.tcx)
|
||||
{
|
||||
let span = length.span();
|
||||
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength {
|
||||
span,
|
||||
length: scalar.to_target_usize(&self.tcx).unwrap(),
|
||||
span: length_arg.span(),
|
||||
length: length_val,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
//@ known-bug: #131102
|
||||
pub struct Blorb<const N: u16>([String; N]);
|
||||
pub struct Wrap(Blorb<0>);
|
||||
pub const fn i(_: Wrap) {}
|
|
@ -8,3 +8,14 @@ fn main() {
|
|||
//~^ ERROR mismatched types
|
||||
//~| ERROR the constant `2` is not of type `usize`
|
||||
}
|
||||
|
||||
fn iter(val: BadArraySize::<2>) {
|
||||
for _ in val.arr {}
|
||||
//~^ ERROR the constant `2` is not of type `usize`
|
||||
//~| ERROR `[i32; 2]` is not an iterator
|
||||
}
|
||||
|
||||
// issue #131102
|
||||
pub struct Blorb<const N: u16>([String; N]); //~ ERROR the constant `N` is not of type `usize`
|
||||
pub struct Wrap(Blorb<0>);
|
||||
pub const fn i(_: Wrap) {} //~ ERROR destructor of `Wrap` cannot be evaluated at compile-time
|
||||
|
|
|
@ -6,6 +6,14 @@ LL | arr: [i32; N],
|
|||
|
|
||||
= note: the length of array `[i32; N]` must be type `usize`
|
||||
|
||||
error: the constant `N` is not of type `usize`
|
||||
--> $DIR/bad-array-size-in-type-err.rs:19:32
|
||||
|
|
||||
LL | pub struct Blorb<const N: u16>([String; N]);
|
||||
| ^^^^^^^^^^^ expected `usize`, found `u16`
|
||||
|
|
||||
= note: the length of array `[String; N]` must be type `usize`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/bad-array-size-in-type-err.rs:7:38
|
||||
|
|
||||
|
@ -20,6 +28,37 @@ LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
|
|||
|
|
||||
= note: the length of array `[i32; 2]` must be type `usize`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: the constant `2` is not of type `usize`
|
||||
--> $DIR/bad-array-size-in-type-err.rs:13:14
|
||||
|
|
||||
LL | for _ in val.arr {}
|
||||
| ^^^^^^^ expected `usize`, found `u8`
|
||||
|
|
||||
= note: the length of array `[i32; 2]` must be type `usize`
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
error[E0277]: `[i32; 2]` is not an iterator
|
||||
--> $DIR/bad-array-size-in-type-err.rs:13:14
|
||||
|
|
||||
LL | for _ in val.arr {}
|
||||
| ^^^^^^^ `[i32; 2]` is not an iterator; try calling `.into_iter()` or `.iter()`
|
||||
|
|
||||
= help: the trait `IntoIterator` is not implemented for `[i32; 2]`
|
||||
= help: the following other types implement trait `IntoIterator`:
|
||||
&[T; N]
|
||||
&[T]
|
||||
&mut [T; N]
|
||||
&mut [T]
|
||||
[T; N]
|
||||
|
||||
error[E0493]: destructor of `Wrap` cannot be evaluated at compile-time
|
||||
--> $DIR/bad-array-size-in-type-err.rs:21:16
|
||||
|
|
||||
LL | pub const fn i(_: Wrap) {}
|
||||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308, E0493.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue