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
|
@ -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")
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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:?}"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue