Rollup merge of #125173 - scottmcm:never-checked, r=davidtwco

Remove `Rvalue::CheckedBinaryOp`

Zulip conversation: <https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/intrinsics.20vs.20binop.2Funop/near/438729996>
cc `@RalfJung`

While it's a draft,
r? ghost
This commit is contained in:
Matthias Krüger 2024-05-20 18:13:48 +02:00 committed by GitHub
commit 9987e900c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 212 additions and 215 deletions

View File

@ -1312,8 +1312,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
| Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) => {
self.consume_operand(location, (operand1, span), flow_state);
self.consume_operand(location, (operand2, span), flow_state);
}

View File

@ -302,8 +302,7 @@ impl<'cx, 'tcx> LoanInvalidationsGenerator<'cx, 'tcx> {
);
}
Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
| Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) => {
self.consume_operand(location, operand1);
self.consume_operand(location, operand2);
}

View File

@ -2417,8 +2417,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_operand(op, location);
}
Rvalue::BinaryOp(_, box (left, right))
| Rvalue::CheckedBinaryOp(_, box (left, right)) => {
Rvalue::BinaryOp(_, box (left, right)) => {
self.check_operand(left, location);
self.check_operand(right, location);
}
@ -2445,7 +2444,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..)
| Rvalue::CopyForDeref(..)
| Rvalue::UnaryOp(..)

View File

@ -609,14 +609,11 @@ fn codegen_stmt<'tcx>(
let lhs = codegen_operand(fx, &lhs_rhs.0);
let rhs = codegen_operand(fx, &lhs_rhs.1);
let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs);
lval.write_cvalue(fx, res);
}
Rvalue::CheckedBinaryOp(bin_op, ref lhs_rhs) => {
let lhs = codegen_operand(fx, &lhs_rhs.0);
let rhs = codegen_operand(fx, &lhs_rhs.1);
let res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
let res = if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs)
} else {
crate::num::codegen_binop(fx, bin_op, lhs, rhs)
};
lval.write_cvalue(fx, res);
}
Rvalue::UnaryOp(un_op, ref operand) => {

View File

@ -70,6 +70,7 @@ pub(crate) fn maybe_codegen<'tcx>(
}
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne | BinOp::Cmp => None,
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow => unreachable!(),
}
}
@ -132,6 +133,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
Some(out_place.to_cvalue(fx))
}
BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow => unreachable!(),
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
BinOp::Div | BinOp::Rem => unreachable!(),
BinOp::Cmp => unreachable!(),

View File

@ -179,6 +179,9 @@ pub(crate) fn codegen_int_binop<'tcx>(
}
}
BinOp::Offset => unreachable!("Offset is not an integer operation"),
BinOp::AddWithOverflow | BinOp::SubWithOverflow | BinOp::MulWithOverflow => {
unreachable!("Overflow binops handled by `codegen_checked_int_binop`")
}
// Compare binops handles by `codegen_binop`.
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::Cmp => {
unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty);

View File

@ -576,6 +576,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs))
if let Some(op) = op_with_overflow.overflowing_to_wrapping() =>
{
let lhs = self.codegen_operand(bx, lhs);
let rhs = self.codegen_operand(bx, rhs);
let result = self.codegen_scalar_checked_binop(
bx,
op,
lhs.immediate(),
rhs.immediate(),
lhs.layout.ty,
);
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
let operand_ty = Ty::new_tup(bx.tcx(), &[val_ty, bx.tcx().types.bool]);
OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) }
}
mir::Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
let lhs = self.codegen_operand(bx, lhs);
let rhs = self.codegen_operand(bx, rhs);
@ -604,20 +620,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
layout: bx.cx().layout_of(op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty)),
}
}
mir::Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
let lhs = self.codegen_operand(bx, lhs);
let rhs = self.codegen_operand(bx, rhs);
let result = self.codegen_scalar_checked_binop(
bx,
op,
lhs.immediate(),
rhs.immediate(),
lhs.layout.ty,
);
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
let operand_ty = Ty::new_tup(bx.tcx(), &[val_ty, bx.tcx().types.bool]);
OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) }
}
mir::Rvalue::UnaryOp(op, ref operand) => {
let operand = self.codegen_operand(bx, operand);
@ -928,6 +930,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.select(is_lt, bx.cx().const_i8(Ordering::Less as i8), ge)
}
}
mir::BinOp::AddWithOverflow
| mir::BinOp::SubWithOverflow
| mir::BinOp::MulWithOverflow => {
bug!("{op:?} needs to return a pair, so call codegen_scalar_checked_binop instead")
}
}
}
@ -1040,7 +1047,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::Cast(..) | // (*)
mir::Rvalue::ShallowInitBox(..) | // (*)
mir::Rvalue::BinaryOp(..) |
mir::Rvalue::CheckedBinaryOp(..) |
mir::Rvalue::UnaryOp(..) |
mir::Rvalue::Discriminant(..) |
mir::Rvalue::NullaryOp(..) |

View File

@ -167,15 +167,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
}
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
} else {
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
}
}
UnaryOp(un_op, ref operand) => {

View File

@ -580,7 +580,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
}
Rvalue::BinaryOp(op, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(op, box (lhs, rhs)) => {
Rvalue::BinaryOp(op, box (lhs, rhs)) => {
let lhs_ty = lhs.ty(self.body, self.tcx);
let rhs_ty = rhs.ty(self.body, self.tcx);

View File

@ -261,7 +261,7 @@ where
| Rvalue::Cast(_, operand, _)
| Rvalue::ShallowInitBox(operand, _) => in_operand::<Q, _>(cx, in_local, operand),
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
Rvalue::BinaryOp(_, box (lhs, rhs)) => {
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
}

View File

@ -200,7 +200,6 @@ where
| mir::Rvalue::Repeat(..)
| mir::Rvalue::Len(..)
| mir::Rvalue::BinaryOp(..)
| mir::Rvalue::CheckedBinaryOp(..)
| mir::Rvalue::NullaryOp(..)
| mir::Rvalue::UnaryOp(..)
| mir::Rvalue::Discriminant(..)

View File

@ -1037,8 +1037,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
)
}
}
AddUnchecked | SubUnchecked | MulUnchecked | Shl | ShlUnchecked | Shr
| ShrUnchecked => {
AddUnchecked | AddWithOverflow | SubUnchecked | SubWithOverflow
| MulUnchecked | MulWithOverflow | Shl | ShlUnchecked | Shr | ShrUnchecked => {
for x in [a, b] {
check_kinds!(
x,
@ -1067,31 +1067,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
}
Rvalue::CheckedBinaryOp(op, vals) => {
use BinOp::*;
let a = vals.0.ty(&self.body.local_decls, self.tcx);
let b = vals.1.ty(&self.body.local_decls, self.tcx);
match op {
Add | Sub | Mul => {
for x in [a, b] {
check_kinds!(
x,
"Cannot perform checked arithmetic on type {:?}",
ty::Uint(..) | ty::Int(..)
)
}
if a != b {
self.fail(
location,
format!(
"Cannot perform checked arithmetic on unequal types {a:?} and {b:?}"
),
);
}
}
_ => self.fail(location, format!("There is no checked version of {op:?}")),
}
}
Rvalue::UnaryOp(op, operand) => {
let a = operand.ty(&self.body.local_decls, self.tcx);
match op {

View File

@ -19,7 +19,9 @@ pub fn binop_left_homogeneous(op: mir::BinOp) -> bool {
match op {
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
| BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
Eq | Ne | Lt | Le | Gt | Ge | Cmp => false,
AddWithOverflow | SubWithOverflow | MulWithOverflow | Eq | Ne | Lt | Le | Gt | Ge | Cmp => {
false
}
}
}
@ -29,8 +31,9 @@ pub fn binop_left_homogeneous(op: mir::BinOp) -> bool {
pub fn binop_right_homogeneous(op: mir::BinOp) -> bool {
use rustc_middle::mir::BinOp::*;
match op {
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge | Cmp => true,
Add | AddUnchecked | AddWithOverflow | Sub | SubUnchecked | SubWithOverflow | Mul
| MulUnchecked | MulWithOverflow | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt
| Le | Gt | Ge | Cmp => true,
Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
}
}

View File

@ -971,9 +971,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
with_no_trimmed_paths!(write!(fmt, "{place:?} as {ty} ({kind:?})"))
}
BinaryOp(ref op, box (ref a, ref b)) => write!(fmt, "{op:?}({a:?}, {b:?})"),
CheckedBinaryOp(ref op, box (ref a, ref b)) => {
write!(fmt, "Checked{op:?}({a:?}, {b:?})")
}
UnaryOp(ref op, ref a) => write!(fmt, "{op:?}({a:?})"),
Discriminant(ref place) => write!(fmt, "discriminant({place:?})"),
NullaryOp(ref op, ref t) => {

View File

@ -438,7 +438,6 @@ impl<'tcx> Rvalue<'tcx> {
_,
)
| Rvalue::BinaryOp(_, _)
| Rvalue::CheckedBinaryOp(_, _)
| Rvalue::NullaryOp(_, _)
| Rvalue::UnaryOp(_, _)
| Rvalue::Discriminant(_)

View File

@ -1295,18 +1295,12 @@ pub enum Rvalue<'tcx> {
/// truncated as needed.
/// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching
/// types and return a value of that type.
/// * The `FooWithOverflow` are like the `Foo`, but returning `(T, bool)` instead of just `T`,
/// where the `bool` is true if the result is not equal to the infinite-precision result.
/// * The remaining operations accept signed integers, unsigned integers, or floats with
/// matching types and return a value of that type.
BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
///
/// For addition, subtraction, and multiplication on integers the error condition is set when
/// the infinite precision result would not be equal to the actual result.
///
/// Other combinations of types and operators are unsupported.
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
/// Computes a value as described by the operation.
NullaryOp(NullOp<'tcx>, Ty<'tcx>),
@ -1449,14 +1443,23 @@ pub enum BinOp {
Add,
/// Like `Add`, but with UB on overflow. (Integers only.)
AddUnchecked,
/// Like `Add`, but returns `(T, bool)` of both the wrapped result
/// and a bool indicating whether it overflowed.
AddWithOverflow,
/// The `-` operator (subtraction)
Sub,
/// Like `Sub`, but with UB on overflow. (Integers only.)
SubUnchecked,
/// Like `Sub`, but returns `(T, bool)` of both the wrapped result
/// and a bool indicating whether it overflowed.
SubWithOverflow,
/// The `*` operator (multiplication)
Mul,
/// Like `Mul`, but with UB on overflow. (Integers only.)
MulUnchecked,
/// Like `Mul`, but returns `(T, bool)` of both the wrapped result
/// and a bool indicating whether it overflowed.
MulWithOverflow,
/// The `/` operator (division)
///
/// For integer types, division by zero is UB, as is `MIN / -1` for signed.

View File

@ -179,12 +179,6 @@ impl<'tcx> Rvalue<'tcx> {
let rhs_ty = rhs.ty(local_decls, tcx);
op.ty(tcx, lhs_ty, rhs_ty)
}
Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
let lhs_ty = lhs.ty(local_decls, tcx);
let rhs_ty = rhs.ty(local_decls, tcx);
let ty = op.ty(tcx, lhs_ty, rhs_ty);
Ty::new_tup(tcx, &[ty, tcx.types.bool])
}
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
@ -263,6 +257,11 @@ impl<'tcx> BinOp {
assert_eq!(lhs_ty, rhs_ty);
lhs_ty
}
&BinOp::AddWithOverflow | &BinOp::SubWithOverflow | &BinOp::MulWithOverflow => {
// these should be integers of the same size.
assert_eq!(lhs_ty, rhs_ty);
Ty::new_tup(tcx, &[lhs_ty, tcx.types.bool])
}
&BinOp::Shl
| &BinOp::ShlUnchecked
| &BinOp::Shr
@ -315,6 +314,9 @@ impl BinOp {
BinOp::Le => hir::BinOpKind::Le,
BinOp::Ge => hir::BinOpKind::Ge,
BinOp::Cmp
| BinOp::AddWithOverflow
| BinOp::SubWithOverflow
| BinOp::MulWithOverflow
| BinOp::AddUnchecked
| BinOp::SubUnchecked
| BinOp::MulUnchecked
@ -325,4 +327,24 @@ impl BinOp {
}
}
}
/// If this is a `FooWithOverflow`, return `Some(Foo)`.
pub fn overflowing_to_wrapping(self) -> Option<BinOp> {
Some(match self {
BinOp::AddWithOverflow => BinOp::Add,
BinOp::SubWithOverflow => BinOp::Sub,
BinOp::MulWithOverflow => BinOp::Mul,
_ => return None,
})
}
/// If this is a `Foo`, return `Some(FooWithOverflow)`.
pub fn wrapping_to_overflowing(self) -> Option<BinOp> {
Some(match self {
BinOp::Add => BinOp::AddWithOverflow,
BinOp::Sub => BinOp::SubWithOverflow,
BinOp::Mul => BinOp::MulWithOverflow,
_ => return None,
})
}
}

View File

@ -696,8 +696,7 @@ macro_rules! make_mir_visitor {
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
Rvalue::BinaryOp(_bin_op, box(lhs, rhs))
| Rvalue::CheckedBinaryOp(_bin_op, box(lhs, rhs)) => {
Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => {
self.visit_operand(lhs, location);
self.visit_operand(rhs, location);
}

View File

@ -195,9 +195,15 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
},
@call(mir_checked, args) => {
parse_by_kind!(self, args[0], _, "binary op",
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
)),
ExprKind::Binary { op, lhs, rhs } => {
if let Some(op_with_overflow) = op.wrapping_to_overflowing() {
Ok(Rvalue::BinaryOp(
op_with_overflow, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
))
} else {
Err(self.expr_error(expr_id, "No WithOverflow form of this operator"))
}
},
)
},
@call(mir_offset, args) => {

View File

@ -568,11 +568,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let result_tup = Ty::new_tup(self.tcx, &[ty, bool_ty]);
let result_value = self.temp(result_tup, span);
let op_with_overflow = op.wrapping_to_overflowing().unwrap();
self.cfg.push_assign(
block,
source_info,
result_value,
Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))),
Rvalue::BinaryOp(op_with_overflow, Box::new((lhs.to_copy(), rhs.to_copy()))),
);
let val_fld = FieldIdx::ZERO;
let of_fld = FieldIdx::new(1);

View File

@ -109,7 +109,6 @@ where
| Rvalue::Repeat(..)
| Rvalue::Len(..)
| Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..)
| Rvalue::UnaryOp(..)
| Rvalue::Discriminant(..)

View File

@ -420,8 +420,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
| Rvalue::Cast(_, ref operand, _)
| Rvalue::ShallowInitBox(ref operand, _)
| Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
| Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
self.gather_operand(lhs);
self.gather_operand(rhs);
}

View File

@ -184,7 +184,6 @@ pub trait ValueAnalysis<'tcx> {
| Rvalue::Len(..)
| Rvalue::Cast(..)
| Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..)
| Rvalue::UnaryOp(..)
| Rvalue::Discriminant(..)

View File

@ -165,7 +165,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
}
}
}
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
Rvalue::BinaryOp(overflowing_op, box (left, right))
if let Some(op) = overflowing_op.overflowing_to_wrapping() =>
{
// Flood everything now, so we can use `insert_value_idx` directly later.
state.flood(target.as_ref(), self.map());
@ -175,7 +177,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
let overflow_target = self.map().apply(target, TrackElem::Field(1_u32.into()));
if value_target.is_some() || overflow_target.is_some() {
let (val, overflow) = self.binary_op(state, *op, left, right);
let (val, overflow) = self.binary_op(state, op, left, right);
if let Some(value_target) = value_target {
// We have flooded `target` earlier.

View File

@ -564,7 +564,7 @@ impl WriteInfo {
| Rvalue::ShallowInitBox(op, _) => {
self.add_operand(op);
}
Rvalue::BinaryOp(_, ops) | Rvalue::CheckedBinaryOp(_, ops) => {
Rvalue::BinaryOp(_, ops) => {
for op in [&ops.0, &ops.1] {
self.add_operand(op);
}

View File

@ -831,23 +831,18 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
// on both operands for side effect.
let lhs = lhs?;
let rhs = rhs?;
if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
return Some(value);
if let Some(op) = op.overflowing_to_wrapping() {
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
return Some(value);
}
Value::CheckedBinaryOp(op, lhs, rhs)
} else {
if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) {
return Some(value);
}
Value::BinaryOp(op, lhs, rhs)
}
Value::BinaryOp(op, lhs, rhs)
}
Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
let ty = lhs.ty(self.local_decls, self.tcx);
let lhs = self.simplify_operand(lhs, location);
let rhs = self.simplify_operand(rhs, location);
// Only short-circuit options after we called `simplify_operand`
// on both operands for side effect.
let lhs = lhs?;
let rhs = rhs?;
if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) {
return Some(value);
}
Value::CheckedBinaryOp(op, lhs, rhs)
}
Rvalue::UnaryOp(op, ref mut arg) => {
let arg = self.simplify_operand(arg, location)?;

View File

@ -399,16 +399,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
Rvalue::BinaryOp(op, box (left, right)) => {
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
self.check_binary_op(*op, left, right, location)?;
}
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
trace!(
"checking CheckedBinaryOp(op = {:?}, left = {:?}, right = {:?})",
op,
left,
right
);
self.check_binary_op(*op, left, right, location)?;
let op = op.overflowing_to_wrapping().unwrap_or(*op);
self.check_binary_op(op, left, right, location)?;
}
// Do not try creating references (#67862)
@ -555,24 +547,18 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
let right = self.eval_operand(right)?;
let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?;
let val =
self.use_ecx(|this| this.ecx.wrapping_binary_op(bin_op, &left, &right))?;
val.into()
}
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
let left = self.eval_operand(left)?;
let left = self.use_ecx(|this| this.ecx.read_immediate(&left))?;
let right = self.eval_operand(right)?;
let right = self.use_ecx(|this| this.ecx.read_immediate(&right))?;
let (val, overflowed) =
self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?;
let overflowed = ImmTy::from_bool(overflowed, self.tcx);
Value::Aggregate {
variant: VariantIdx::ZERO,
fields: [Value::from(val), overflowed.into()].into_iter().collect(),
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
let (val, overflowed) =
self.use_ecx(|this| this.ecx.overflowing_binary_op(bin_op, &left, &right))?;
let overflowed = ImmTy::from_bool(overflowed, self.tcx);
Value::Aggregate {
variant: VariantIdx::ZERO,
fields: [Value::from(val), overflowed.into()].into_iter().collect(),
}
} else {
let val =
self.use_ecx(|this| this.ecx.wrapping_binary_op(bin_op, &left, &right))?;
val.into()
}
}

View File

@ -140,16 +140,16 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
rhs = args.next().unwrap();
}
let bin_op = match intrinsic.name {
sym::add_with_overflow => BinOp::Add,
sym::sub_with_overflow => BinOp::Sub,
sym::mul_with_overflow => BinOp::Mul,
sym::add_with_overflow => BinOp::AddWithOverflow,
sym::sub_with_overflow => BinOp::SubWithOverflow,
sym::mul_with_overflow => BinOp::MulWithOverflow,
_ => bug!("unexpected intrinsic"),
};
block.statements.push(Statement {
source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new((
*destination,
Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
))),
});
terminator.kind = TerminatorKind::Goto { target };

View File

@ -470,7 +470,7 @@ impl<'tcx> Validator<'_, 'tcx> {
self.validate_operand(operand)?;
}
Rvalue::BinaryOp(op, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(op, box (lhs, rhs)) => {
Rvalue::BinaryOp(op, box (lhs, rhs)) => {
let op = *op;
let lhs_ty = lhs.ty(self.body, self.tcx);
@ -539,10 +539,13 @@ impl<'tcx> Validator<'_, 'tcx> {
| BinOp::Offset
| BinOp::Add
| BinOp::AddUnchecked
| BinOp::AddWithOverflow
| BinOp::Sub
| BinOp::SubUnchecked
| BinOp::SubWithOverflow
| BinOp::Mul
| BinOp::MulUnchecked
| BinOp::MulWithOverflow
| BinOp::BitXor
| BinOp::BitAnd
| BinOp::BitOr

View File

@ -1,5 +1,6 @@
//! Conversion of internal Rust compiler `mir` items to stable ones.
use rustc_middle::bug;
use rustc_middle::mir;
use rustc_middle::mir::interpret::alloc_range;
use rustc_middle::mir::mono::MonoItem;
@ -183,16 +184,21 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
op.stable(tables),
ty.stable(tables),
),
BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
bin_op.stable(tables),
ops.0.stable(tables),
ops.1.stable(tables),
),
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
bin_op.stable(tables),
ops.0.stable(tables),
ops.1.stable(tables),
),
BinaryOp(bin_op, ops) => {
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
stable_mir::mir::Rvalue::CheckedBinaryOp(
bin_op.stable(tables),
ops.0.stable(tables),
ops.1.stable(tables),
)
} else {
stable_mir::mir::Rvalue::BinaryOp(
bin_op.stable(tables),
ops.0.stable(tables),
ops.1.stable(tables),
)
}
}
NullaryOp(null_op, ty) => {
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
}
@ -485,10 +491,13 @@ impl<'tcx> Stable<'tcx> for mir::BinOp {
match self {
BinOp::Add => stable_mir::mir::BinOp::Add,
BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked,
BinOp::AddWithOverflow => bug!("AddWithOverflow should have been translated already"),
BinOp::Sub => stable_mir::mir::BinOp::Sub,
BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked,
BinOp::SubWithOverflow => bug!("AddWithOverflow should have been translated already"),
BinOp::Mul => stable_mir::mir::BinOp::Mul,
BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked,
BinOp::MulWithOverflow => bug!("AddWithOverflow should have been translated already"),
BinOp::Div => stable_mir::mir::BinOp::Div,
BinOp::Rem => stable_mir::mir::BinOp::Rem,
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,

View File

@ -81,9 +81,9 @@ fn destructure_const<'tcx>(
fn check_binop(op: mir::BinOp) -> bool {
use mir::BinOp::*;
match op {
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
| BitAnd | BitOr | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge
| Gt | Cmp => true,
Add | AddUnchecked | AddWithOverflow | Sub | SubUnchecked | SubWithOverflow | Mul
| MulUnchecked | MulWithOverflow | Div | Rem | BitXor | BitAnd | BitOr | Shl
| ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge | Gt | Cmp => true,
Offset => false,
}
}

View File

@ -149,7 +149,7 @@ impl TypeVisitor<TyCtxt<'_>> for ContainsRegion {
}
fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use};
use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, Repeat, UnaryOp, Use};
let mut visit_op = |op: &mir::Operand<'_>| match op {
mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local),
@ -159,7 +159,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
match rvalue {
Use(op) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op),
Aggregate(_, ops) => ops.iter().for_each(visit_op),
BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
BinaryOp(_, box (lhs, rhs)) => {
visit_op(lhs);
visit_op(rhs);
},

View File

@ -161,7 +161,7 @@ fn check_rvalue<'tcx>(
"transmute can attempt to turn pointers into integers, so is unstable in const fn".into(),
)),
// binops are fine on integers
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
Rvalue::BinaryOp(_, box (lhs, rhs)) => {
check_operand(tcx, lhs, span, body)?;
check_operand(tcx, rhs, span, body)?;
let ty = lhs.ty(body, tcx);

View File

@ -21,7 +21,7 @@ fn f(_1: i32, _2: bool) -> i32 {
_2 = Le(_1, _1);
_2 = Ge(_1, _1);
_2 = Gt(_1, _1);
_3 = CheckedAdd(_1, _1);
_3 = AddWithOverflow(_1, _1);
_2 = (_3.1: bool);
_1 = (_3.0: i32);
_0 = _1;

View File

@ -11,7 +11,7 @@
bb0: {
StorageLive(_1);
- _2 = CheckedAdd(const 1_u32, const 1_u32);
- _2 = AddWithOverflow(const 1_u32, const 1_u32);
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind unreachable];
+ _2 = const (2_u32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind unreachable];

View File

@ -11,7 +11,7 @@
bb0: {
StorageLive(_1);
- _2 = CheckedAdd(const 1_u32, const 1_u32);
- _2 = AddWithOverflow(const 1_u32, const 1_u32);
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind continue];
+ _2 = const (2_u32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> [success: bb1, unwind continue];

View File

@ -14,7 +14,7 @@
StorageLive(_1);
StorageLive(_2);
- _2 = const 2_u32 as u8 (IntToInt);
- _3 = CheckedAdd(_2, const 1_u8);
- _3 = AddWithOverflow(_2, const 1_u8);
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind unreachable];
+ _2 = const 2_u8;
+ _3 = const (3_u8, false);

View File

@ -14,7 +14,7 @@
StorageLive(_1);
StorageLive(_2);
- _2 = const 2_u32 as u8 (IntToInt);
- _3 = CheckedAdd(_2, const 1_u8);
- _3 = AddWithOverflow(_2, const 1_u8);
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> [success: bb1, unwind continue];
+ _2 = const 2_u8;
+ _3 = const (3_u8, false);

View File

@ -19,7 +19,7 @@
StorageLive(_3);
_3 = const 1_u8;
StorageLive(_4);
- _4 = CheckedAdd(_2, _3);
- _4 = AddWithOverflow(_2, _3);
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
+ _4 = const (0_u8, true);
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable];

View File

@ -19,7 +19,7 @@
StorageLive(_3);
_3 = const 1_u8;
StorageLive(_4);
- _4 = CheckedAdd(_2, _3);
- _4 = AddWithOverflow(_2, _3);
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
+ _4 = const (0_u8, true);
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue];

View File

@ -6,7 +6,7 @@
let mut _1: (u32, bool);
bb0: {
- _1 = CheckedAdd(const 2_u32, const 2_u32);
- _1 = AddWithOverflow(const 2_u32, const 2_u32);
- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind unreachable];
+ _1 = const (4_u32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind unreachable];

View File

@ -6,7 +6,7 @@
let mut _1: (u32, bool);
bb0: {
- _1 = CheckedAdd(const 2_u32, const 2_u32);
- _1 = AddWithOverflow(const 2_u32, const 2_u32);
- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue];
+ _1 = const (4_u32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> [success: bb1, unwind continue];

View File

@ -40,7 +40,7 @@
+ _4 = const 1_i32;
StorageLive(_5);
- _5 = _2;
- _6 = CheckedAdd(_4, _5);
- _6 = AddWithOverflow(_4, _5);
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable];
+ _5 = const 2_i32;
+ _6 = const (3_i32, false);
@ -57,7 +57,7 @@
StorageLive(_8);
StorageLive(_9);
- _9 = _7;
- _10 = CheckedAdd(_9, const 1_i32);
- _10 = AddWithOverflow(_9, const 1_i32);
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable];
+ _9 = const i32::MAX;
+ _10 = const (i32::MIN, true);

View File

@ -40,7 +40,7 @@
+ _4 = const 1_i32;
StorageLive(_5);
- _5 = _2;
- _6 = CheckedAdd(_4, _5);
- _6 = AddWithOverflow(_4, _5);
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue];
+ _5 = const 2_i32;
+ _6 = const (3_i32, false);
@ -57,7 +57,7 @@
StorageLive(_8);
StorageLive(_9);
- _9 = _7;
- _10 = CheckedAdd(_9, const 1_i32);
- _10 = AddWithOverflow(_9, const 1_i32);
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue];
+ _9 = const i32::MAX;
+ _10 = const (i32::MIN, true);

View File

@ -19,7 +19,7 @@
StorageLive(_3);
_3 = const 1_u8;
StorageLive(_4);
- _4 = CheckedAdd(_2, _3);
- _4 = AddWithOverflow(_2, _3);
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
+ _4 = const (0_u8, true);
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable];

View File

@ -19,7 +19,7 @@
StorageLive(_3);
_3 = const 1_u8;
StorageLive(_4);
- _4 = CheckedAdd(_2, _3);
- _4 = AddWithOverflow(_2, _3);
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
+ _4 = const (0_u8, true);
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue];

View File

@ -31,9 +31,9 @@
StorageLive(_3);
StorageLive(_4);
_4 = _1;
- _5 = CheckedAdd(_4, const 0_u64);
- _5 = AddWithOverflow(_4, const 0_u64);
- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable];
+ _5 = CheckedAdd(_1, const 0_u64);
+ _5 = AddWithOverflow(_1, const 0_u64);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable];
}
@ -52,7 +52,7 @@
StorageLive(_7);
StorageLive(_8);
_8 = _1;
- _9 = CheckedSub(_8, const 0_u64);
- _9 = SubWithOverflow(_8, const 0_u64);
- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable];
+ _9 = _5;
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable];
@ -76,7 +76,7 @@
_12 = _1;
StorageLive(_13);
_13 = _1;
- _14 = CheckedSub(_12, _13);
- _14 = SubWithOverflow(_12, _13);
- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind unreachable];
+ _14 = const (0_u64, false);
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind unreachable];
@ -99,7 +99,7 @@
StorageLive(_16);
StorageLive(_17);
_17 = _1;
- _18 = CheckedMul(_17, const 0_u64);
- _18 = MulWithOverflow(_17, const 0_u64);
- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind unreachable];
+ _18 = const (0_u64, false);
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind unreachable];
@ -120,7 +120,7 @@
StorageLive(_20);
StorageLive(_21);
_21 = _1;
- _22 = CheckedMul(_21, const 1_u64);
- _22 = MulWithOverflow(_21, const 1_u64);
- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind unreachable];
+ _22 = _5;
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind unreachable];

View File

@ -31,9 +31,9 @@
StorageLive(_3);
StorageLive(_4);
_4 = _1;
- _5 = CheckedAdd(_4, const 0_u64);
- _5 = AddWithOverflow(_4, const 0_u64);
- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue];
+ _5 = CheckedAdd(_1, const 0_u64);
+ _5 = AddWithOverflow(_1, const 0_u64);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue];
}
@ -52,7 +52,7 @@
StorageLive(_7);
StorageLive(_8);
_8 = _1;
- _9 = CheckedSub(_8, const 0_u64);
- _9 = SubWithOverflow(_8, const 0_u64);
- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue];
+ _9 = _5;
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue];
@ -76,7 +76,7 @@
_12 = _1;
StorageLive(_13);
_13 = _1;
- _14 = CheckedSub(_12, _13);
- _14 = SubWithOverflow(_12, _13);
- assert(!move (_14.1: bool), "attempt to compute `{} - {}`, which would overflow", move _12, move _13) -> [success: bb5, unwind continue];
+ _14 = const (0_u64, false);
+ assert(!const false, "attempt to compute `{} - {}`, which would overflow", _1, _1) -> [success: bb5, unwind continue];
@ -99,7 +99,7 @@
StorageLive(_16);
StorageLive(_17);
_17 = _1;
- _18 = CheckedMul(_17, const 0_u64);
- _18 = MulWithOverflow(_17, const 0_u64);
- assert(!move (_18.1: bool), "attempt to compute `{} * {}`, which would overflow", move _17, const 0_u64) -> [success: bb7, unwind continue];
+ _18 = const (0_u64, false);
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb7, unwind continue];
@ -120,7 +120,7 @@
StorageLive(_20);
StorageLive(_21);
_21 = _1;
- _22 = CheckedMul(_21, const 1_u64);
- _22 = MulWithOverflow(_21, const 1_u64);
- assert(!move (_22.1: bool), "attempt to compute `{} * {}`, which would overflow", move _21, const 1_u64) -> [success: bb9, unwind continue];
+ _22 = _5;
+ assert(!const false, "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb9, unwind continue];

View File

@ -5,7 +5,7 @@
let mut _1: (usize, bool);
bb0: {
_1 = CheckedAdd(const 1_usize, const 1_usize);
_1 = AddWithOverflow(const 1_usize, const 1_usize);
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb1, unwind: bb2];
}

View File

@ -184,9 +184,9 @@ pub fn assume() {
// EMIT_MIR lower_intrinsics.with_overflow.LowerIntrinsics.diff
pub fn with_overflow(a: i32, b: i32) {
// CHECK-LABEL: fn with_overflow(
// CHECK: CheckedAdd(
// CHECK: CheckedSub(
// CHECK: CheckedMul(
// CHECK: AddWithOverflow(
// CHECK: SubWithOverflow(
// CHECK: MulWithOverflow(
let _x = core::intrinsics::add_with_overflow(a, b);
let _y = core::intrinsics::sub_with_overflow(a, b);

View File

@ -31,7 +31,7 @@
StorageLive(_5);
_5 = _2;
- _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = CheckedAdd(move _4, move _5);
+ _3 = AddWithOverflow(move _4, move _5);
+ goto -> bb1;
}
@ -44,7 +44,7 @@
StorageLive(_8);
_8 = _2;
- _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
+ _6 = CheckedSub(move _7, move _8);
+ _6 = SubWithOverflow(move _7, move _8);
+ goto -> bb2;
}
@ -57,7 +57,7 @@
StorageLive(_11);
_11 = _2;
- _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
+ _9 = CheckedMul(move _10, move _11);
+ _9 = MulWithOverflow(move _10, move _11);
+ goto -> bb3;
}

View File

@ -31,7 +31,7 @@
StorageLive(_5);
_5 = _2;
- _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = CheckedAdd(move _4, move _5);
+ _3 = AddWithOverflow(move _4, move _5);
+ goto -> bb1;
}
@ -44,7 +44,7 @@
StorageLive(_8);
_8 = _2;
- _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
+ _6 = CheckedSub(move _7, move _8);
+ _6 = SubWithOverflow(move _7, move _8);
+ goto -> bb2;
}
@ -57,7 +57,7 @@
StorageLive(_11);
_11 = _2;
- _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
+ _9 = CheckedMul(move _10, move _11);
+ _9 = MulWithOverflow(move _10, move _11);
+ goto -> bb3;
}

View File

@ -24,7 +24,7 @@
bb0: {
StorageLive(_1);
- _2 = CheckedAdd(const 2_i32, const 2_i32);
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
+ _2 = const (4_i32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];

View File

@ -24,7 +24,7 @@
bb0: {
StorageLive(_1);
- _2 = CheckedAdd(const 2_i32, const 2_i32);
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
+ _2 = const (4_i32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];

View File

@ -24,7 +24,7 @@
bb0: {
StorageLive(_1);
- _2 = CheckedAdd(const 2_i32, const 2_i32);
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
+ _2 = const (4_i32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];

View File

@ -24,7 +24,7 @@
bb0: {
StorageLive(_1);
- _2 = CheckedAdd(const 2_i32, const 2_i32);
- _2 = AddWithOverflow(const 2_i32, const 2_i32);
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
+ _2 = const (4_i32, false);
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];

View File

@ -26,7 +26,7 @@
bb0: {
StorageLive(_1);
_2 = CheckedAdd(const 2_i32, const 2_i32);
_2 = AddWithOverflow(const 2_i32, const 2_i32);
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
}

View File

@ -26,7 +26,7 @@
bb0: {
StorageLive(_1);
_2 = CheckedAdd(const 2_i32, const 2_i32);
_2 = AddWithOverflow(const 2_i32, const 2_i32);
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
}

View File

@ -26,7 +26,7 @@
bb0: {
StorageLive(_1);
_2 = CheckedAdd(const 2_i32, const 2_i32);
_2 = AddWithOverflow(const 2_i32, const 2_i32);
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind unreachable];
}

View File

@ -26,7 +26,7 @@
bb0: {
StorageLive(_1);
_2 = CheckedAdd(const 2_i32, const 2_i32);
_2 = AddWithOverflow(const 2_i32, const 2_i32);
assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> [success: bb1, unwind continue];
}

View File

@ -5,7 +5,7 @@ fn foo() -> i32 {
let mut _1: (i32, bool);
bb0: {
_1 = CheckedAdd(const 5_i32, const 6_i32);
_1 = AddWithOverflow(const 5_i32, const 6_i32);
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> [success: bb1, unwind continue];
}
@ -21,7 +21,7 @@ fn foo() -> i32 {
let mut _1: (i32, bool);
bb0: {
_1 = CheckedAdd(const 5_i32, const 6_i32);
_1 = AddWithOverflow(const 5_i32, const 6_i32);
assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> [success: bb1, unwind continue];
}