ScalarInt: size mismatches are a bug, do not delay the panic
This commit is contained in:
parent
13423befc4
commit
3c57ea0df7
45 changed files with 247 additions and 313 deletions
|
@ -84,11 +84,11 @@ impl<'tcx> ConstValue<'tcx> {
|
|||
}
|
||||
|
||||
pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
|
||||
self.try_to_scalar()?.try_to_int().ok()
|
||||
self.try_to_scalar()?.try_to_scalar_int().ok()
|
||||
}
|
||||
|
||||
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
|
||||
self.try_to_scalar_int()?.try_to_bits(size).ok()
|
||||
Some(self.try_to_scalar_int()?.to_bits(size))
|
||||
}
|
||||
|
||||
pub fn try_to_bool(&self) -> Option<bool> {
|
||||
|
@ -96,7 +96,7 @@ impl<'tcx> ConstValue<'tcx> {
|
|||
}
|
||||
|
||||
pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||
self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
|
||||
Some(self.try_to_scalar_int()?.to_target_usize(tcx))
|
||||
}
|
||||
|
||||
pub fn try_to_bits_for_ty(
|
||||
|
@ -300,7 +300,7 @@ impl<'tcx> Const<'tcx> {
|
|||
|
||||
#[inline]
|
||||
pub fn try_to_bits(self, size: Size) -> Option<u128> {
|
||||
self.try_to_scalar_int()?.try_to_bits(size).ok()
|
||||
Some(self.try_to_scalar_int()?.to_bits(size))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -367,7 +367,7 @@ impl<'tcx> Const<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Option<ScalarInt> {
|
||||
self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
|
||||
self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -375,7 +375,7 @@ impl<'tcx> Const<'tcx> {
|
|||
let int = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
let size =
|
||||
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
|
||||
int.try_to_bits(size).ok()
|
||||
Some(int.to_bits(size))
|
||||
}
|
||||
|
||||
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
||||
|
@ -391,7 +391,7 @@ impl<'tcx> Const<'tcx> {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Option<u64> {
|
||||
self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
|
||||
Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -122,16 +122,12 @@ impl<Prov> Scalar<Prov> {
|
|||
Scalar::Int(c.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
|
||||
ScalarInt::try_from_uint(i, size).map(Scalar::Int)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
|
||||
let i = i.into();
|
||||
Self::try_from_uint(i, size)
|
||||
ScalarInt::try_from_uint(i, size)
|
||||
.unwrap_or_else(|| bug!("Unsigned value {:#x} does not fit in {} bits", i, size.bits()))
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -164,16 +160,12 @@ impl<Prov> Scalar<Prov> {
|
|||
Self::from_uint(i, cx.data_layout().pointer_size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
||||
ScalarInt::try_from_int(i, size).map(Scalar::Int)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
|
||||
let i = i.into();
|
||||
Self::try_from_int(i, size)
|
||||
ScalarInt::try_from_int(i, size)
|
||||
.unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()))
|
||||
.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -227,7 +219,7 @@ impl<Prov> Scalar<Prov> {
|
|||
}
|
||||
|
||||
/// This is almost certainly not the method you want! You should dispatch on the type
|
||||
/// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
|
||||
/// and use `to_{u8,u16,...}`/`to_pointer` to perform ptr-to-int / int-to-ptr casts as needed.
|
||||
///
|
||||
/// This method only exists for the benefit of low-level operations that truly need to treat the
|
||||
/// scalar in whatever form it is.
|
||||
|
@ -289,7 +281,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
|||
/// The error type is `AllocId`, not `CtfeProvenance`, since `AllocId` is the "minimal"
|
||||
/// component all provenance types must have.
|
||||
#[inline]
|
||||
pub fn try_to_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
|
||||
pub fn try_to_scalar_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
|
||||
match self {
|
||||
Scalar::Int(int) => Ok(int),
|
||||
Scalar::Ptr(ptr, sz) => {
|
||||
|
@ -307,13 +299,13 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
|||
|
||||
#[inline(always)]
|
||||
pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> {
|
||||
self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
|
||||
self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
|
||||
pub fn assert_int(self) -> ScalarInt {
|
||||
self.try_to_int().unwrap()
|
||||
pub fn assert_scalar_int(self) -> ScalarInt {
|
||||
self.try_to_scalar_int().expect("got a pointer where a ScalarInt was expected")
|
||||
}
|
||||
|
||||
/// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in
|
||||
|
@ -330,13 +322,6 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
|
|||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
|
||||
pub fn assert_bits(self, target_size: Size) -> u128 {
|
||||
self.to_bits(target_size)
|
||||
.unwrap_or_else(|_| panic!("assertion failed: {self:?} fits {target_size:?}"))
|
||||
}
|
||||
|
||||
pub fn to_bool(self) -> InterpResult<'tcx, bool> {
|
||||
let val = self.to_u8()?;
|
||||
match val {
|
||||
|
|
|
@ -1033,8 +1033,8 @@ impl<'tcx> PatRangeBoundary<'tcx> {
|
|||
if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
|
||||
let sz = ty.primitive_size(tcx);
|
||||
let cmp = match ty.kind() {
|
||||
ty::Uint(_) | ty::Char => a.assert_uint(sz).cmp(&b.assert_uint(sz)),
|
||||
ty::Int(_) => a.assert_int(sz).cmp(&b.assert_int(sz)),
|
||||
ty::Uint(_) | ty::Char => a.to_uint(sz).cmp(&b.to_uint(sz)),
|
||||
ty::Int(_) => a.to_int(sz).cmp(&b.to_int(sz)),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
return Some(cmp);
|
||||
|
|
|
@ -376,7 +376,7 @@ impl<'tcx> Const<'tcx> {
|
|||
param_env: ParamEnv<'tcx>,
|
||||
) -> Option<(Ty<'tcx>, ScalarInt)> {
|
||||
let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
|
||||
let val = scalar.try_to_int().ok()?;
|
||||
let val = scalar.try_to_scalar_int().ok()?;
|
||||
Some((ty, val))
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ impl<'tcx> Const<'tcx> {
|
|||
let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
||||
scalar.try_to_bits(size).ok()
|
||||
Some(scalar.to_bits(size))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -405,7 +405,7 @@ impl<'tcx> Const<'tcx> {
|
|||
param_env: ParamEnv<'tcx>,
|
||||
) -> Option<u64> {
|
||||
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
scalar.try_to_target_usize(tcx).ok()
|
||||
Some(scalar.to_target_usize(tcx))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -246,6 +246,10 @@ impl ScalarInt {
|
|||
Self::try_from_uint(i, tcx.data_layout.pointer_size)
|
||||
}
|
||||
|
||||
/// Try to convert this ScalarInt to the raw underlying bits.
|
||||
/// Fails if the size is wrong. Generally a wrong size should lead to a panic,
|
||||
/// but Miri sometimes wants to be resilient to size mismatches,
|
||||
/// so the interpreter will generally use this `try` method.
|
||||
#[inline]
|
||||
pub fn try_to_bits(self, target_size: Size) -> Result<u128, Size> {
|
||||
assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST");
|
||||
|
@ -258,165 +262,149 @@ impl ScalarInt {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_bits(self, target_size: Size) -> u128 {
|
||||
pub fn to_bits(self, target_size: Size) -> u128 {
|
||||
self.try_to_bits(target_size).unwrap_or_else(|size| {
|
||||
bug!("expected int of size {}, but got size {}", target_size.bytes(), size.bytes())
|
||||
})
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to an unsigned integer of the given size.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
|
||||
/// `ScalarInt`s size in that case.
|
||||
/// Extracts the bits from the scalar without checking the size.
|
||||
#[inline]
|
||||
pub fn try_to_uint(self, size: Size) -> Result<u128, Size> {
|
||||
self.try_to_bits(size)
|
||||
pub fn to_bits_unchecked(self) -> u128 {
|
||||
self.check_data();
|
||||
self.data
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to an unsigned integer of the given size.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to `size`.
|
||||
#[inline]
|
||||
pub fn to_uint(self, size: Size) -> u128 {
|
||||
self.to_bits(size)
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to `u8`.
|
||||
/// Panics if the `size` of the `ScalarInt`in not equal to 1 byte.
|
||||
#[inline]
|
||||
pub fn to_u8(self) -> u8 {
|
||||
self.to_uint(Size::from_bits(8)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to `u16`.
|
||||
/// Panics if the size of the `ScalarInt` in not equal to 2 bytes.
|
||||
#[inline]
|
||||
pub fn to_u16(self) -> u16 {
|
||||
self.to_uint(Size::from_bits(16)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to `u32`.
|
||||
/// Panics if the `size` of the `ScalarInt` in not equal to 4 bytes.
|
||||
#[inline]
|
||||
pub fn to_u32(self) -> u32 {
|
||||
self.to_uint(Size::from_bits(32)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to `u64`.
|
||||
/// Panics if the `size` of the `ScalarInt` in not equal to 8 bytes.
|
||||
#[inline]
|
||||
pub fn to_u64(self) -> u64 {
|
||||
self.to_uint(Size::from_bits(64)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Converts the `ScalarInt` to `u128`.
|
||||
/// Panics if the `size` of the `ScalarInt` in not equal to 16 bytes.
|
||||
#[inline]
|
||||
pub fn to_u128(self) -> u128 {
|
||||
self.to_uint(Size::from_bits(128))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_uint(self, size: Size) -> u128 {
|
||||
self.assert_bits(size)
|
||||
pub fn to_target_usize(&self, tcx: TyCtxt<'_>) -> u64 {
|
||||
self.to_uint(tcx.data_layout.pointer_size).try_into().unwrap()
|
||||
}
|
||||
|
||||
// Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt`
|
||||
// in not equal to 1 byte and returns the `size` value of the `ScalarInt` in
|
||||
// that case.
|
||||
/// Converts the `ScalarInt` to `bool`.
|
||||
/// Panics if the `size` of the `ScalarInt` is not equal to 1 byte.
|
||||
/// Errors if it is not a valid `bool`.
|
||||
#[inline]
|
||||
pub fn try_to_u8(self) -> Result<u8, Size> {
|
||||
self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt`
|
||||
/// in not equal to 2 bytes and returns the `size` value of the `ScalarInt` in
|
||||
/// that case.
|
||||
#[inline]
|
||||
pub fn try_to_u16(self) -> Result<u16, Size> {
|
||||
self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt`
|
||||
/// in not equal to 4 bytes and returns the `size` value of the `ScalarInt` in
|
||||
/// that case.
|
||||
#[inline]
|
||||
pub fn try_to_u32(self) -> Result<u32, Size> {
|
||||
self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt`
|
||||
/// in not equal to 8 bytes and returns the `size` value of the `ScalarInt` in
|
||||
/// that case.
|
||||
#[inline]
|
||||
pub fn try_to_u64(self) -> Result<u64, Size> {
|
||||
self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt`
|
||||
/// in not equal to 16 bytes and returns the `size` value of the `ScalarInt` in
|
||||
/// that case.
|
||||
#[inline]
|
||||
pub fn try_to_u128(self) -> Result<u128, Size> {
|
||||
self.try_to_uint(Size::from_bits(128))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
|
||||
self.try_to_uint(tcx.data_layout.pointer_size).map(|v| u64::try_from(v).unwrap())
|
||||
}
|
||||
|
||||
// Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
|
||||
// in not equal to 1 byte or if the value is not 0 or 1 and returns the `size`
|
||||
// value of the `ScalarInt` in that case.
|
||||
#[inline]
|
||||
pub fn try_to_bool(self) -> Result<bool, Size> {
|
||||
match self.try_to_u8()? {
|
||||
pub fn try_to_bool(self) -> Result<bool, ()> {
|
||||
match self.to_u8() {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
_ => Err(self.size()),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to a signed integer of the given size.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
|
||||
/// `ScalarInt`s size in that case.
|
||||
/// Converts the `ScalarInt` to a signed integer of the given size.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to `size`.
|
||||
#[inline]
|
||||
pub fn try_to_int(self, size: Size) -> Result<i128, Size> {
|
||||
let b = self.try_to_bits(size)?;
|
||||
Ok(size.sign_extend(b) as i128)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_int(self, size: Size) -> i128 {
|
||||
let b = self.assert_bits(size);
|
||||
pub fn to_int(self, size: Size) -> i128 {
|
||||
let b = self.to_bits(size);
|
||||
size.sign_extend(b) as i128
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to i8.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to 1 byte
|
||||
/// and returns the `ScalarInt`s size in that case.
|
||||
pub fn try_to_i8(self) -> Result<i8, Size> {
|
||||
self.try_to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap())
|
||||
/// Converts the `ScalarInt` to i8.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to 1 byte.
|
||||
pub fn to_i8(self) -> i8 {
|
||||
self.to_int(Size::from_bits(8)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to i16.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to 2 bytes
|
||||
/// and returns the `ScalarInt`s size in that case.
|
||||
pub fn try_to_i16(self) -> Result<i16, Size> {
|
||||
self.try_to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap())
|
||||
/// Converts the `ScalarInt` to i16.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to 2 bytes.
|
||||
pub fn to_i16(self) -> i16 {
|
||||
self.to_int(Size::from_bits(16)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to i32.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to 4 bytes
|
||||
/// and returns the `ScalarInt`s size in that case.
|
||||
pub fn try_to_i32(self) -> Result<i32, Size> {
|
||||
self.try_to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap())
|
||||
/// Converts the `ScalarInt` to i32.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to 4 bytes.
|
||||
pub fn to_i32(self) -> i32 {
|
||||
self.to_int(Size::from_bits(32)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to i64.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to 8 bytes
|
||||
/// and returns the `ScalarInt`s size in that case.
|
||||
pub fn try_to_i64(self) -> Result<i64, Size> {
|
||||
self.try_to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap())
|
||||
/// Converts the `ScalarInt` to i64.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to 8 bytes.
|
||||
pub fn to_i64(self) -> i64 {
|
||||
self.to_int(Size::from_bits(64)).try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Tries to convert the `ScalarInt` to i128.
|
||||
/// Fails if the size of the `ScalarInt` is not equal to 16 bytes
|
||||
/// and returns the `ScalarInt`s size in that case.
|
||||
pub fn try_to_i128(self) -> Result<i128, Size> {
|
||||
self.try_to_int(Size::from_bits(128))
|
||||
/// Converts the `ScalarInt` to i128.
|
||||
/// Panics if the size of the `ScalarInt` is not equal to 16 bytes.
|
||||
pub fn to_i128(self) -> i128 {
|
||||
self.to_int(Size::from_bits(128))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_target_isize(&self, tcx: TyCtxt<'_>) -> Result<i64, Size> {
|
||||
self.try_to_int(tcx.data_layout.pointer_size).map(|v| i64::try_from(v).unwrap())
|
||||
pub fn to_target_isize(&self, tcx: TyCtxt<'_>) -> i64 {
|
||||
self.to_int(tcx.data_layout.pointer_size).try_into().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_float<F: Float>(self) -> Result<F, Size> {
|
||||
pub fn to_float<F: Float>(self) -> F {
|
||||
// Going through `to_uint` to check size and truncation.
|
||||
Ok(F::from_bits(self.try_to_bits(Size::from_bits(F::BITS))?))
|
||||
F::from_bits(self.to_bits(Size::from_bits(F::BITS)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_f16(self) -> Result<Half, Size> {
|
||||
self.try_to_float()
|
||||
pub fn to_f16(self) -> Half {
|
||||
self.to_float()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_f32(self) -> Result<Single, Size> {
|
||||
self.try_to_float()
|
||||
pub fn to_f32(self) -> Single {
|
||||
self.to_float()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_f64(self) -> Result<Double, Size> {
|
||||
self.try_to_float()
|
||||
pub fn to_f64(self) -> Double {
|
||||
self.to_float()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_f128(self) -> Result<Quad, Size> {
|
||||
self.try_to_float()
|
||||
pub fn to_f128(self) -> Quad {
|
||||
self.to_float()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from {
|
||||
macro_rules! from_x_for_scalar_int {
|
||||
($($ty:ty),*) => {
|
||||
$(
|
||||
impl From<$ty> for ScalarInt {
|
||||
|
@ -432,30 +420,29 @@ macro_rules! from {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! try_from {
|
||||
macro_rules! from_scalar_int_for_x {
|
||||
($($ty:ty),*) => {
|
||||
$(
|
||||
impl TryFrom<ScalarInt> for $ty {
|
||||
type Error = Size;
|
||||
impl From<ScalarInt> for $ty {
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
fn from(int: ScalarInt) -> Self {
|
||||
// The `unwrap` cannot fail because to_bits (if it succeeds)
|
||||
// is guaranteed to return a value that fits into the size.
|
||||
int.try_to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
|
||||
.map(|u| u.try_into().unwrap())
|
||||
int.to_bits(Size::from_bytes(std::mem::size_of::<$ty>()))
|
||||
.try_into().unwrap()
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
from!(u8, u16, u32, u64, u128, bool);
|
||||
try_from!(u8, u16, u32, u64, u128);
|
||||
from_x_for_scalar_int!(u8, u16, u32, u64, u128, bool);
|
||||
from_scalar_int_for_x!(u8, u16, u32, u64, u128);
|
||||
|
||||
impl TryFrom<ScalarInt> for bool {
|
||||
type Error = Size;
|
||||
type Error = ();
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
fn try_from(int: ScalarInt) -> Result<Self, ()> {
|
||||
int.try_to_bool()
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +450,7 @@ impl TryFrom<ScalarInt> for bool {
|
|||
impl From<char> for ScalarInt {
|
||||
#[inline]
|
||||
fn from(c: char) -> Self {
|
||||
Self { data: c as u128, size: NonZero::new(std::mem::size_of::<char>() as u8).unwrap() }
|
||||
(c as u32).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,10 +463,7 @@ impl TryFrom<ScalarInt> for char {
|
|||
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Self::Error> {
|
||||
let Ok(bits) = int.try_to_bits(Size::from_bytes(std::mem::size_of::<char>())) else {
|
||||
return Err(CharTryFromScalarInt);
|
||||
};
|
||||
match char::from_u32(bits.try_into().unwrap()) {
|
||||
match char::from_u32(int.to_u32()) {
|
||||
Some(c) => Ok(c),
|
||||
None => Err(CharTryFromScalarInt),
|
||||
}
|
||||
|
@ -494,11 +478,10 @@ impl From<Half> for ScalarInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ScalarInt> for Half {
|
||||
type Error = Size;
|
||||
impl From<ScalarInt> for Half {
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
int.try_to_bits(Size::from_bytes(2)).map(Self::from_bits)
|
||||
fn from(int: ScalarInt) -> Self {
|
||||
Self::from_bits(int.to_bits(Size::from_bytes(2)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,11 +493,10 @@ impl From<Single> for ScalarInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ScalarInt> for Single {
|
||||
type Error = Size;
|
||||
impl From<ScalarInt> for Single {
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
int.try_to_bits(Size::from_bytes(4)).map(Self::from_bits)
|
||||
fn from(int: ScalarInt) -> Self {
|
||||
Self::from_bits(int.to_bits(Size::from_bytes(4)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,11 +508,10 @@ impl From<Double> for ScalarInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ScalarInt> for Double {
|
||||
type Error = Size;
|
||||
impl From<ScalarInt> for Double {
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
int.try_to_bits(Size::from_bytes(8)).map(Self::from_bits)
|
||||
fn from(int: ScalarInt) -> Self {
|
||||
Self::from_bits(int.to_bits(Size::from_bytes(8)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -542,11 +523,10 @@ impl From<Quad> for ScalarInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<ScalarInt> for Quad {
|
||||
type Error = Size;
|
||||
impl From<ScalarInt> for Quad {
|
||||
#[inline]
|
||||
fn try_from(int: ScalarInt) -> Result<Self, Size> {
|
||||
int.try_to_bits(Size::from_bytes(16)).map(Self::from_bits)
|
||||
fn from(int: ScalarInt) -> Self {
|
||||
Self::from_bits(int.to_bits(Size::from_bytes(16)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ impl<'tcx> ValTree<'tcx> {
|
|||
}
|
||||
|
||||
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||
self.try_to_scalar_int().and_then(|s| s.try_to_target_usize(tcx).ok())
|
||||
self.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
|
||||
}
|
||||
|
||||
/// Get the values inside the ValTree as a slice of bytes. This only works for
|
||||
|
@ -100,8 +100,9 @@ impl<'tcx> ValTree<'tcx> {
|
|||
_ => return None,
|
||||
}
|
||||
|
||||
Some(tcx.arena.alloc_from_iter(
|
||||
self.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().try_to_u8().unwrap()),
|
||||
))
|
||||
Some(
|
||||
tcx.arena
|
||||
.alloc_from_iter(self.unwrap_branch().into_iter().map(|v| v.unwrap_leaf().to_u8())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1652,7 +1652,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() {
|
||||
match self.tcx().try_get_global_alloc(prov.alloc_id()) {
|
||||
Some(GlobalAlloc::Memory(alloc)) => {
|
||||
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
|
||||
let len = int.to_bits(self.tcx().data_layout.pointer_size);
|
||||
let range =
|
||||
AllocRange { start: offset, size: Size::from_bytes(len) };
|
||||
if let Ok(byte_str) =
|
||||
|
@ -1730,7 +1730,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
}
|
||||
// Pointer types
|
||||
ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(_) => {
|
||||
let data = int.assert_bits(self.tcx().data_layout.pointer_size);
|
||||
let data = int.to_bits(self.tcx().data_layout.pointer_size);
|
||||
self.typed_value(
|
||||
|this| {
|
||||
write!(this, "0x{data:x}")?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue