use std::fmt;
use rustc_macros::HashStable;
+use rustc_apfloat::{Float, ieee::{Double, Single}};
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
use crate::ty::PlaceholderConst;
use crate::hir::def_id::DefId;
-use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
+use super::{InterpResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
/// Represents the result of a raw const operation, pre-validation.
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash, HashStable)]
"Scalar value {:#x} exceeds size of {} bytes", data, size);
}
+ /// Tag this scalar with `new_tag` if it is a pointer, leave it unchanged otherwise.
+ ///
+ /// Used by `MemPlace::replace_tag`.
#[inline]
pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
- // Used by `MemPlace::replace_tag`
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)),
Scalar::Raw { data, size } => Scalar::Raw { data, size },
}
impl<'tcx, Tag> Scalar<Tag> {
+ /// Erase the tag from the scalar, if any.
+ ///
+ /// Used by error reporting code to avoid having the error type depend on `Tag`.
#[inline]
pub fn erase_tag(self) -> Scalar {
- // Used by error reporting code to avoid having the error type depend on `Tag`
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
Scalar::Raw { data, size } => Scalar::Raw { data, size },
}
#[inline]
- pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
+ pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
Scalar::Raw { data, size } => {
}
#[inline]
- pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
+ pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
let dl = cx.data_layout();
match self {
Scalar::Raw { data, size } => {
}
#[inline]
- pub fn from_f32(f: f32) -> Self {
+ pub fn from_f32(f: Single) -> Self {
Scalar::Raw { data: f.to_bits() as u128, size: 4 }
}
#[inline]
- pub fn from_f64(f: f64) -> Self {
+ pub fn from_f64(f: Double) -> Self {
Scalar::Raw { data: f.to_bits() as u128, size: 8 }
}
}
#[inline]
- pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
+ pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
match self {
Scalar::Raw { data, size } => {
assert_eq!(target_size.bytes(), size as u64);
}
#[inline]
- pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
+ pub fn to_ptr(self) -> InterpResult<'tcx, Pointer<Tag>> {
match self {
Scalar::Raw { data: 0, .. } => err!(InvalidNullPointerUsage),
Scalar::Raw { .. } => err!(ReadBytesAsPointer),
}
}
- pub fn to_bool(self) -> EvalResult<'tcx, bool> {
+ pub fn to_bool(self) -> InterpResult<'tcx, bool> {
match self {
Scalar::Raw { data: 0, size: 1 } => Ok(false),
Scalar::Raw { data: 1, size: 1 } => Ok(true),
}
}
- pub fn to_char(self) -> EvalResult<'tcx, char> {
+ pub fn to_char(self) -> InterpResult<'tcx, char> {
let val = self.to_u32()?;
match ::std::char::from_u32(val) {
Some(c) => Ok(c),
}
}
- pub fn to_u8(self) -> EvalResult<'static, u8> {
+ pub fn to_u8(self) -> InterpResult<'static, u8> {
let sz = Size::from_bits(8);
let b = self.to_bits(sz)?;
Ok(b as u8)
}
- pub fn to_u32(self) -> EvalResult<'static, u32> {
+ pub fn to_u32(self) -> InterpResult<'static, u32> {
let sz = Size::from_bits(32);
let b = self.to_bits(sz)?;
Ok(b as u32)
}
- pub fn to_u64(self) -> EvalResult<'static, u64> {
+ pub fn to_u64(self) -> InterpResult<'static, u64> {
let sz = Size::from_bits(64);
let b = self.to_bits(sz)?;
Ok(b as u64)
}
- pub fn to_usize(self, cx: &impl HasDataLayout) -> EvalResult<'static, u64> {
+ pub fn to_usize(self, cx: &impl HasDataLayout) -> InterpResult<'static, u64> {
let b = self.to_bits(cx.data_layout().pointer_size)?;
Ok(b as u64)
}
- pub fn to_i8(self) -> EvalResult<'static, i8> {
+ pub fn to_i8(self) -> InterpResult<'static, i8> {
let sz = Size::from_bits(8);
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
Ok(b as i8)
}
- pub fn to_i32(self) -> EvalResult<'static, i32> {
+ pub fn to_i32(self) -> InterpResult<'static, i32> {
let sz = Size::from_bits(32);
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
Ok(b as i32)
}
- pub fn to_i64(self) -> EvalResult<'static, i64> {
+ pub fn to_i64(self) -> InterpResult<'static, i64> {
let sz = Size::from_bits(64);
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
Ok(b as i64)
}
- pub fn to_isize(self, cx: &impl HasDataLayout) -> EvalResult<'static, i64> {
+ pub fn to_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> {
let sz = cx.data_layout().pointer_size;
let b = self.to_bits(sz)?;
let b = sign_extend(b, sz) as i128;
}
#[inline]
- pub fn to_f32(self) -> EvalResult<'static, f32> {
- Ok(f32::from_bits(self.to_u32()?))
+ pub fn to_f32(self) -> InterpResult<'static, Single> {
+ // Going through `u32` to check size and truncation.
+ Ok(Single::from_bits(self.to_u32()? as u128))
}
#[inline]
- pub fn to_f64(self) -> EvalResult<'static, f64> {
- Ok(f64::from_bits(self.to_u64()?))
+ pub fn to_f64(self) -> InterpResult<'static, Double> {
+ // Going through `u64` to check size and truncation.
+ Ok(Double::from_bits(self.to_u64()? as u128))
}
}
}
impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
+ /// Erase the tag from the scalar, if any.
+ ///
+ /// Used by error reporting code to avoid having the error type depend on `Tag`.
#[inline]
pub fn erase_tag(self) -> ScalarMaybeUndef
{
- // Used by error reporting code to avoid having the error type depend on `Tag`
match self {
ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
}
#[inline]
- pub fn not_undef(self) -> EvalResult<'static, Scalar<Tag>> {
+ pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
match self {
ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
}
#[inline(always)]
- pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
+ pub fn to_ptr(self) -> InterpResult<'tcx, Pointer<Tag>> {
self.not_undef()?.to_ptr()
}
#[inline(always)]
- pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
+ pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> {
self.not_undef()?.to_bits(target_size)
}
#[inline(always)]
- pub fn to_bool(self) -> EvalResult<'tcx, bool> {
+ pub fn to_bool(self) -> InterpResult<'tcx, bool> {
self.not_undef()?.to_bool()
}
#[inline(always)]
- pub fn to_char(self) -> EvalResult<'tcx, char> {
+ pub fn to_char(self) -> InterpResult<'tcx, char> {
self.not_undef()?.to_char()
}
#[inline(always)]
- pub fn to_f32(self) -> EvalResult<'tcx, f32> {
+ pub fn to_f32(self) -> InterpResult<'tcx, Single> {
self.not_undef()?.to_f32()
}
#[inline(always)]
- pub fn to_f64(self) -> EvalResult<'tcx, f64> {
+ pub fn to_f64(self) -> InterpResult<'tcx, Double> {
self.not_undef()?.to_f64()
}
#[inline(always)]
- pub fn to_u8(self) -> EvalResult<'tcx, u8> {
+ pub fn to_u8(self) -> InterpResult<'tcx, u8> {
self.not_undef()?.to_u8()
}
#[inline(always)]
- pub fn to_u32(self) -> EvalResult<'tcx, u32> {
+ pub fn to_u32(self) -> InterpResult<'tcx, u32> {
self.not_undef()?.to_u32()
}
#[inline(always)]
- pub fn to_u64(self) -> EvalResult<'tcx, u64> {
+ pub fn to_u64(self) -> InterpResult<'tcx, u64> {
self.not_undef()?.to_u64()
}
#[inline(always)]
- pub fn to_usize(self, cx: &impl HasDataLayout) -> EvalResult<'tcx, u64> {
+ pub fn to_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
self.not_undef()?.to_usize(cx)
}
#[inline(always)]
- pub fn to_i8(self) -> EvalResult<'tcx, i8> {
+ pub fn to_i8(self) -> InterpResult<'tcx, i8> {
self.not_undef()?.to_i8()
}
#[inline(always)]
- pub fn to_i32(self) -> EvalResult<'tcx, i32> {
+ pub fn to_i32(self) -> InterpResult<'tcx, i32> {
self.not_undef()?.to_i32()
}
#[inline(always)]
- pub fn to_i64(self) -> EvalResult<'tcx, i64> {
+ pub fn to_i64(self) -> InterpResult<'tcx, i64> {
self.not_undef()?.to_i64()
}
#[inline(always)]
- pub fn to_isize(self, cx: &impl HasDataLayout) -> EvalResult<'tcx, i64> {
+ pub fn to_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
self.not_undef()?.to_isize(cx)
}
}