diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-02-13 21:28:09 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-13 21:28:09 +0100 |
| commit | c8343b8653cdb0fb6cabf588ddee2fef07635b35 (patch) | |
| tree | 5198234d42056f95fe575335e61137dbd49f1c93 /src | |
| parent | 8e2772c0fdab55695d0a607f50e7deaa329e7189 (diff) | |
| parent | 10f342abae4e9aafb02c3adaaa050f43eb0e2dd0 (diff) | |
| download | rust-c8343b8653cdb0fb6cabf588ddee2fef07635b35.tar.gz rust-c8343b8653cdb0fb6cabf588ddee2fef07635b35.zip | |
Rollup merge of #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 https://github.com/rust-lang/rust/pull/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 https://github.com/rust-lang/rust/issues/69117 (then we also need to address build failures introduced by https://github.com/rust-lang/rust/pull/68969) r? @oli-obk
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/interpret/intrinsics.rs | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index a83b5412790..1085b85d7cd 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -384,8 +384,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx> { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`. - // First, check x % y != 0. - if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 { + // First, check x % y != 0 (or if that computation overflows). + let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?; + if overflow || res.to_bits(a.layout.size)? != 0 { // Then, check if `b` is -1, which is the "min_value / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); let b_scalar = b.to_scalar().unwrap(); @@ -395,6 +396,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b,) } } + // `Rem` says this is all right, so we can let `Div` do its job. self.binop_ignore_overflow(BinOp::Div, a, b, dest) } } |
