Skip to content

Commit e1305c2

Browse files
authored
Rollup merge of rust-lang#98888 - RalfJung:interpret-checked-bin, r=oli-obk
interpret: fix CheckedBinOp behavior when overflow checking is disabled Adjusts the interpreter to rust-lang#98738. r? ``@oli-obk``
2 parents 8854492 + 2f6e996 commit e1305c2

File tree

5 files changed

+26
-4
lines changed

5 files changed

+26
-4
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
217217
sym::mul_with_overflow => BinOp::Mul,
218218
_ => bug!(),
219219
};
220-
self.binop_with_overflow(bin_op, &lhs, &rhs, dest)?;
220+
self.binop_with_overflow(
221+
bin_op, /*force_overflow_checks*/ true, &lhs, &rhs, dest,
222+
)?;
221223
}
222224
sym::saturating_add | sym::saturating_sub => {
223225
let l = self.read_immediate(&args[0])?;

compiler/rustc_const_eval/src/interpret/machine.rs

+8
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
144144
true
145145
}
146146

147+
/// Whether CheckedBinOp MIR statements should actually check for overflow.
148+
fn check_binop_checks_overflow(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
149+
147150
/// Entry point for obtaining the MIR of anything that should get evaluated.
148151
/// So not just functions and shims, but also const/static initializers, anonymous
149152
/// constants, ...
@@ -468,6 +471,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
468471
true
469472
}
470473

474+
#[inline(always)]
475+
fn check_binop_checks_overflow(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
476+
true
477+
}
478+
471479
#[inline(always)]
472480
fn call_extra_fn(
473481
_ecx: &mut InterpCx<$mir, $tcx, Self>,

compiler/rustc_const_eval/src/interpret/operator.rs

+9
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
1212
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1313
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
1414
/// and a boolean signifying the potential overflow to the destination.
15+
///
16+
/// `force_overflow_checks` indicates whether overflow checks should be done even when
17+
/// `tcx.sess.overflow_checks()` is `false`.
1518
pub fn binop_with_overflow(
1619
&mut self,
1720
op: mir::BinOp,
21+
force_overflow_checks: bool,
1822
left: &ImmTy<'tcx, M::PointerTag>,
1923
right: &ImmTy<'tcx, M::PointerTag>,
2024
dest: &PlaceTy<'tcx, M::PointerTag>,
@@ -26,6 +30,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
2630
"type mismatch for result of {:?}",
2731
op,
2832
);
33+
// As per https://github.com/rust-lang/rust/pull/98738, we always return `false` in the 2nd
34+
// component when overflow checking is disabled.
35+
let overflowed =
36+
overflowed && (force_overflow_checks || M::check_binop_checks_overflow(self));
37+
// Write the result to `dest`.
2938
if let Abi::ScalarPair(..) = dest.layout.abi {
3039
// We can use the optimized path and avoid `place_field` (which might do
3140
// `force_allocation`).

compiler/rustc_const_eval/src/interpret/step.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
185185
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
186186
let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
187187
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
188-
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
188+
self.binop_with_overflow(
189+
bin_op, /*force_overflow_checks*/ false, &left, &right, &dest,
190+
)?;
189191
}
190192

191193
UnaryOp(un_op, ref operand) => {

compiler/rustc_middle/src/mir/syntax.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -993,8 +993,9 @@ pub enum Rvalue<'tcx> {
993993

994994
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
995995
///
996-
/// When overflow checking is disabled, the error condition is false. Otherwise, the error
997-
/// condition is determined as described below.
996+
/// When overflow checking is disabled and we are generating run-time code, the error condition
997+
/// is false. Otherwise, and always during CTFE, the error condition is determined as described
998+
/// below.
998999
///
9991000
/// For addition, subtraction, and multiplication on integers the error condition is set when
10001001
/// the infinite precision result would be unequal to the actual result.

0 commit comments

Comments
 (0)