Skip to content

Commit c8343b8

Browse files
authored
Rollup merge of rust-lang#69126 - RalfJung:exact-div, r=oli-obk
miri: fix exact_div Turns out `exact_div` was relying on the broken behavior of `Rem` for `int_min % -1` that was fixed in rust-lang#69002. This PR fixes `exact_div`. Inside rustc, `exact_div` is only used in a single place where the divisor is always positive (in `ptr_offset_from`), so we cannot test the fix in rustc. The Miri test suite covers this through the `exact_div` intrinsic, though (and it is how I found out). One step to rust-lang#69117 (then we also need to address build failures introduced by rust-lang#68969) r? @oli-obk
2 parents 8e2772c + 10f342a commit c8343b8

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

src/librustc_mir/interpret/intrinsics.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
384384
) -> InterpResult<'tcx> {
385385
// Performs an exact division, resulting in undefined behavior where
386386
// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`.
387-
// First, check x % y != 0.
388-
if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 {
387+
// First, check x % y != 0 (or if that computation overflows).
388+
let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?;
389+
if overflow || res.to_bits(a.layout.size)? != 0 {
389390
// Then, check if `b` is -1, which is the "min_value / -1" case.
390391
let minus1 = Scalar::from_int(-1, dest.layout.size);
391392
let b_scalar = b.to_scalar().unwrap();
@@ -395,6 +396,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
395396
throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b,)
396397
}
397398
}
399+
// `Rem` says this is all right, so we can let `Div` do its job.
398400
self.binop_ignore_overflow(BinOp::Div, a, b, dest)
399401
}
400402
}

0 commit comments

Comments
 (0)