1
Fork 0

ScalarInt: size mismatches are a bug, do not delay the panic

This commit is contained in:
Ralf Jung 2024-06-08 16:13:45 +02:00
parent 13423befc4
commit 3c57ea0df7
45 changed files with 247 additions and 313 deletions

View file

@ -326,7 +326,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
// This allows the set of visited edges to grow monotonically with the lattice.
FlatSet::Bottom => TerminatorEdges::None,
FlatSet::Elem(scalar) => {
let choice = scalar.assert_bits(scalar.size());
let choice = scalar.assert_scalar_int().to_bits_unchecked();
TerminatorEdges::Single(targets.target_for_value(choice))
}
FlatSet::Top => TerminatorEdges::SwitchInt { discr, targets },
@ -609,7 +609,7 @@ fn propagatable_scalar(
map: &Map,
) -> Option<Scalar> {
if let FlatSet::Elem(value) = state.get_idx(place, map)
&& value.try_to_int().is_ok()
&& value.try_to_scalar_int().is_ok()
{
// Do not attempt to propagate pointers, as we may fail to preserve their identity.
Some(value)
@ -670,7 +670,7 @@ fn try_write_constant<'tcx>(
let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else {
throw_machine_stop_str!("discriminant with provenance")
};
let discr_bits = discr.assert_bits(discr.size());
let discr_bits = discr.to_bits(discr.size());
let Some((variant, _)) = def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) else {
throw_machine_stop_str!("illegal discriminant for enum")
};

View file

@ -471,7 +471,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let slice = self.evaluated[slice].as_ref()?;
let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
let len = slice.len(&self.ecx).ok()?;
let imm = ImmTy::try_from_uint(len, usize_layout)?;
let imm = ImmTy::from_uint(len, usize_layout);
imm.into()
}
NullaryOp(null_op, ty) => {
@ -492,7 +492,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
NullOp::UbChecks => return None,
};
let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
let imm = ImmTy::try_from_uint(val, usize_layout)?;
let imm = ImmTy::from_uint(val, usize_layout);
imm.into()
}
UnaryOp(un_op, operand) => {
@ -1180,7 +1180,7 @@ fn op_to_prop_const<'tcx>(
// If this constant has scalar ABI, return it as a `ConstValue::Scalar`.
if let Abi::Scalar(abi::Scalar::Initialized { .. }) = op.layout.abi
&& let Ok(scalar) = ecx.read_scalar(op)
&& scalar.try_to_int().is_ok()
&& scalar.try_to_scalar_int().is_ok()
{
return Some(ConstValue::Scalar(scalar));
}

View file

@ -356,15 +356,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
debug!("check_binary_op: reporting assert for {:?}", location);
let panic = AssertKind::Overflow(
op,
match l {
Some(l) => l.to_const_int(),
// Invent a dummy value, the diagnostic ignores it anyway
None => ConstInt::new(
ScalarInt::try_from_uint(1_u8, left_size).unwrap(),
left_ty.is_signed(),
left_ty.is_ptr_sized_integral(),
),
},
// Invent a dummy value, the diagnostic ignores it anyway
ConstInt::new(
ScalarInt::try_from_uint(1_u8, left_size).unwrap(),
left_ty.is_signed(),
left_ty.is_ptr_sized_integral(),
),
r.to_const_int(),
);
self.report_assert_as_lint(location, AssertLintKind::ArithmeticOverflow, panic);
@ -787,8 +784,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
TerminatorKind::SwitchInt { ref discr, ref targets } => {
if let Some(ref value) = self.eval_operand(discr)
&& let Some(value_const) = self.use_ecx(|this| this.ecx.read_scalar(value))
&& let Ok(constant) = value_const.try_to_int()
&& let Ok(constant) = constant.try_to_bits(constant.size())
&& let Ok(constant) = value_const.to_bits(value_const.size())
{
// We managed to evaluate the discriminant, so we know we only need to visit
// one target.

View file

@ -372,7 +372,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
}
fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool {
l.assert_int(l.size()) == ScalarInt::try_from_uint(r, size).unwrap().assert_int(size)
l.to_bits_unchecked() == ScalarInt::try_from_uint(r, size).unwrap().to_bits_unchecked()
}
// We first compare the two branches, and then the other branches need to fulfill the same conditions.

View file

@ -500,14 +500,14 @@ impl<'tcx> Validator<'_, 'tcx> {
}
_ => None,
};
match rhs_val.map(|x| x.assert_uint(sz)) {
match rhs_val.map(|x| x.to_uint(sz)) {
// for the zero test, int vs uint does not matter
Some(x) if x != 0 => {} // okay
_ => return Err(Unpromotable), // value not known or 0 -- not okay
}
// Furthermore, for signed divison, we also have to exclude `int::MIN / -1`.
if lhs_ty.is_signed() {
match rhs_val.map(|x| x.assert_int(sz)) {
match rhs_val.map(|x| x.to_int(sz)) {
Some(-1) | None => {
// The RHS is -1 or unknown, so we have to be careful.
// But is the LHS int::MIN?
@ -518,7 +518,7 @@ impl<'tcx> Validator<'_, 'tcx> {
_ => None,
};
let lhs_min = sz.signed_int_min();
match lhs_val.map(|x| x.assert_int(sz)) {
match lhs_val.map(|x| x.to_int(sz)) {
Some(x) if x != lhs_min => {} // okay
_ => return Err(Unpromotable), // value not known or int::MIN -- not okay
}

View file

@ -49,7 +49,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
let layout = tcx
.layout_of(param_env.and(opt.branch_value_ty))
.expect("if we have an evaluated constant we must know the layout");
int.assert_bits(layout.size)
int.to_bits(layout.size)
}
Scalar::Ptr(..) => continue,
};

View file

@ -5,12 +5,12 @@ use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
use rustc_infer::traits::Reveal;
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{
self, CoroutineArgsExt, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance,
self, CoroutineArgsExt, InstanceDef, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
Variance,
};
use rustc_middle::{bug, span_bug};
use rustc_target::abi::{Size, FIRST_VARIANT};
@ -1478,7 +1478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
});
for (value, _) in targets.iter() {
if Scalar::<()>::try_from_uint(value, size).is_none() {
if ScalarInt::try_from_uint(value, size).is_none() {
self.fail(
location,
format!("the value {value:#x} is not a proper {switch_ty:?}"),