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
|
@ -95,10 +95,10 @@ fn const_to_valtree_inner<'tcx>(
|
|||
}
|
||||
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
|
||||
let val = ecx.read_immediate(place)?;
|
||||
let val = val.to_scalar();
|
||||
let val = val.to_scalar_int().unwrap();
|
||||
*num_nodes += 1;
|
||||
|
||||
Ok(ty::ValTree::Leaf(val.assert_int()))
|
||||
Ok(ty::ValTree::Leaf(val))
|
||||
}
|
||||
|
||||
ty::Pat(base, ..) => {
|
||||
|
@ -125,7 +125,7 @@ fn const_to_valtree_inner<'tcx>(
|
|||
let val = val.to_scalar();
|
||||
// We are in the CTFE machine, so ptr-to-int casts will fail.
|
||||
// This can only be `Ok` if `val` already is an integer.
|
||||
let Ok(val) = val.try_to_int() else {
|
||||
let Ok(val) = val.try_to_scalar_int() else {
|
||||
return Err(ValTreeCreationError::NonSupportedType);
|
||||
};
|
||||
// It's just a ScalarInt!
|
||||
|
@ -411,7 +411,7 @@ fn valtree_into_mplace<'tcx>(
|
|||
ty::Adt(def, _) if def.is_enum() => {
|
||||
// First element of valtree corresponds to variant
|
||||
let scalar_int = branches[0].unwrap_leaf();
|
||||
let variant_idx = VariantIdx::from_u32(scalar_int.try_to_u32().unwrap());
|
||||
let variant_idx = VariantIdx::from_u32(scalar_int.to_u32());
|
||||
let variant = def.variant(variant_idx);
|
||||
debug!(?variant);
|
||||
|
||||
|
|
|
@ -123,14 +123,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// (`tag_bits` itself is only used for error messages below.)
|
||||
let tag_bits = tag_val
|
||||
.to_scalar()
|
||||
.try_to_int()
|
||||
.try_to_scalar_int()
|
||||
.map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
|
||||
.assert_bits(tag_layout.size);
|
||||
.to_bits(tag_layout.size);
|
||||
// Cast bits from tag layout to discriminant layout.
|
||||
// After the checks we did above, this cannot fail, as
|
||||
// discriminants are int-like.
|
||||
let discr_val = self.int_to_int_or_float(&tag_val, discr_layout).unwrap();
|
||||
let discr_bits = discr_val.to_scalar().assert_bits(discr_layout.size);
|
||||
let discr_bits = discr_val.to_scalar().to_bits(discr_layout.size)?;
|
||||
// Convert discriminant to variant index, and catch invalid discriminants.
|
||||
let index = match *ty.kind() {
|
||||
ty::Adt(adt, _) => {
|
||||
|
@ -152,7 +152,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// discriminant (encoded in niche/tag) and variant index are the same.
|
||||
let variants_start = niche_variants.start().as_u32();
|
||||
let variants_end = niche_variants.end().as_u32();
|
||||
let variant = match tag_val.try_to_int() {
|
||||
let variant = match tag_val.try_to_scalar_int() {
|
||||
Err(dbg_val) => {
|
||||
// So this is a pointer then, and casting to an int failed.
|
||||
// Can only happen during CTFE.
|
||||
|
@ -167,7 +167,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
untagged_variant
|
||||
}
|
||||
Ok(tag_bits) => {
|
||||
let tag_bits = tag_bits.assert_bits(tag_layout.size);
|
||||
let tag_bits = tag_bits.to_bits(tag_layout.size);
|
||||
// We need to use machine arithmetic to get the relative variant idx:
|
||||
// variant_index_relative = tag_val - niche_start_val
|
||||
let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
|
||||
|
@ -175,7 +175,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let variant_index_relative_val =
|
||||
self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
|
||||
let variant_index_relative =
|
||||
variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
|
||||
variant_index_relative_val.to_scalar().to_bits(tag_val.layout.size)?;
|
||||
// Check if this is in the range that indicates an actual discriminant.
|
||||
if variant_index_relative <= u128::from(variants_end - variants_start) {
|
||||
let variant_index_relative = u32::try_from(variant_index_relative)
|
||||
|
@ -294,8 +294,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
ImmTy::from_uint(variant_index_relative, tag_layout);
|
||||
let tag = self
|
||||
.binary_op(mir::BinOp::Add, &variant_index_relative_val, &niche_start_val)?
|
||||
.to_scalar()
|
||||
.assert_int();
|
||||
.to_scalar_int()?;
|
||||
Ok(Some((tag, tag_field)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -519,7 +519,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
|
||||
// First, check x % y != 0 (or if that computation overflows).
|
||||
let rem = self.binary_op(BinOp::Rem, a, b)?;
|
||||
if rem.to_scalar().assert_bits(a.layout.size) != 0 {
|
||||
if rem.to_scalar().to_bits(a.layout.size)? != 0 {
|
||||
throw_ub_custom!(
|
||||
fluent::const_eval_exact_div_has_remainder,
|
||||
a = format!("{a}"),
|
||||
|
|
|
@ -1344,7 +1344,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
/// Test if this value might be null.
|
||||
/// If the machine does not support ptr-to-int casts, this is conservative.
|
||||
pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<'tcx, bool> {
|
||||
Ok(match scalar.try_to_int() {
|
||||
Ok(match scalar.try_to_scalar_int() {
|
||||
Ok(int) => int.is_null(),
|
||||
Err(_) => {
|
||||
// Can only happen during CTFE.
|
||||
|
|
|
@ -87,6 +87,12 @@ impl<Prov: Provenance> Immediate<Prov> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
|
||||
pub fn to_scalar_int(self) -> ScalarInt {
|
||||
self.to_scalar().try_to_scalar_int().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
|
||||
pub fn to_scalar_pair(self) -> (Scalar<Prov>, Scalar<Prov>) {
|
||||
|
@ -219,19 +225,11 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
|
|||
Self::from_scalar(Scalar::from(s), layout)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Option<Self> {
|
||||
Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout))
|
||||
}
|
||||
#[inline]
|
||||
pub fn from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Self {
|
||||
Self::from_scalar(Scalar::from_uint(i, layout.size), layout)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Option<Self> {
|
||||
Some(Self::from_scalar(Scalar::try_from_int(i, layout.size)?, layout))
|
||||
}
|
||||
#[inline]
|
||||
pub fn from_int(i: impl Into<i128>, layout: TyAndLayout<'tcx>) -> Self {
|
||||
Self::from_scalar(Scalar::from_int(i, layout.size), layout)
|
||||
|
@ -276,7 +274,8 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
|
|||
#[inline]
|
||||
pub fn to_const_int(self) -> ConstInt {
|
||||
assert!(self.layout.ty.is_integral());
|
||||
let int = self.to_scalar().assert_int();
|
||||
let int = self.imm.to_scalar_int();
|
||||
assert_eq!(int.size(), self.layout.size);
|
||||
ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral())
|
||||
}
|
||||
|
||||
|
|
|
@ -95,10 +95,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let l = left.to_scalar_int()?;
|
||||
let r = right.to_scalar_int()?;
|
||||
// Prepare to convert the values to signed or unsigned form.
|
||||
let l_signed = || l.assert_int(left.layout.size);
|
||||
let l_unsigned = || l.assert_uint(left.layout.size);
|
||||
let r_signed = || r.assert_int(right.layout.size);
|
||||
let r_unsigned = || r.assert_uint(right.layout.size);
|
||||
let l_signed = || l.to_int(left.layout.size);
|
||||
let l_unsigned = || l.to_uint(left.layout.size);
|
||||
let r_signed = || r.to_int(right.layout.size);
|
||||
let r_unsigned = || r.to_uint(right.layout.size);
|
||||
|
||||
let throw_ub_on_overflow = match bin_op {
|
||||
AddUnchecked => Some(sym::unchecked_add),
|
||||
|
|
|
@ -653,8 +653,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
let WrappingRange { start, end } = valid_range;
|
||||
let max_value = size.unsigned_int_max();
|
||||
assert!(end <= max_value);
|
||||
let bits = match scalar.try_to_int() {
|
||||
Ok(int) => int.assert_bits(size),
|
||||
let bits = match scalar.try_to_scalar_int() {
|
||||
Ok(int) => int.to_bits(size),
|
||||
Err(_) => {
|
||||
// So this is a pointer then, and casting to an int failed.
|
||||
// Can only happen during CTFE.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue