Skip to content

Commit 305eadb

Browse files
committed
operator: implement binary_op strictly by first checking the type, then dispatching further; call ptr_op machine hook only for pointer types
1 parent 6bd7e16 commit 305eadb

File tree

3 files changed

+22
-24
lines changed

3 files changed

+22
-24
lines changed

src/librustc_mir/const_eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
397397
)
398398
}
399399

400-
fn ptr_op(
400+
fn binary_ptr_op(
401401
_ecx: &InterpCx<'mir, 'tcx, Self>,
402402
_bin_op: mir::BinOp,
403403
_left: ImmTy<'tcx>,

src/librustc_mir/interpret/machine.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
155155
def_id: DefId,
156156
) -> InterpResult<'tcx, Cow<'tcx, Allocation>>;
157157

158-
/// Called for all binary operations on integer(-like) types when one operand is a pointer
159-
/// value, and for the `Offset` operation that is inherently about pointers.
158+
/// Called for all binary operations where the LHS has pointer type.
160159
///
161160
/// Returns a (value, overflowed) pair if the operation succeeded
162-
fn ptr_op(
161+
fn binary_ptr_op(
163162
ecx: &InterpCx<'mir, 'tcx, Self>,
164163
bin_op: mir::BinOp,
165164
left: ImmTy<'tcx, Self::PointerTag>,

src/librustc_mir/interpret/operator.rs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -290,30 +290,29 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
290290
FloatTy::F64 => self.binary_float_op(bin_op, left.to_f64()?, right.to_f64()?),
291291
})
292292
}
293-
_ => {
294-
// Must be integer(-like) types. Don't forget about == on fn pointers.
295-
assert!(
296-
left.layout.ty.is_integral() ||
297-
left.layout.ty.is_unsafe_ptr() || left.layout.ty.is_fn_ptr(),
298-
"Unexpected LHS type {:?} for BinOp {:?}", left.layout.ty, bin_op);
293+
_ if left.layout.ty.is_integral() => {
294+
// the RHS type can be different, e.g. for shifts -- but it has to be integral, too
299295
assert!(
300-
right.layout.ty.is_integral() ||
301-
right.layout.ty.is_unsafe_ptr() || right.layout.ty.is_fn_ptr(),
302-
"Unexpected RHS type {:?} for BinOp {:?}", right.layout.ty, bin_op);
303-
304-
// Handle operations that support pointer values
305-
if left.to_scalar_ptr()?.is_ptr() ||
306-
right.to_scalar_ptr()?.is_ptr() ||
307-
bin_op == mir::BinOp::Offset
308-
{
309-
return M::ptr_op(self, bin_op, left, right);
310-
}
296+
right.layout.ty.is_integral(),
297+
"Unexpected types for BinOp: {:?} {:?} {:?}",
298+
left.layout.ty, bin_op, right.layout.ty
299+
);
311300

312-
// Everything else only works with "proper" bits
313-
let l = left.to_bits().expect("we checked is_ptr");
314-
let r = right.to_bits().expect("we checked is_ptr");
301+
let l = self.force_bits(left.to_scalar()?, left.layout.size)?;
302+
let r = self.force_bits(right.to_scalar()?, right.layout.size)?;
315303
self.binary_int_op(bin_op, l, left.layout, r, right.layout)
316304
}
305+
_ if left.layout.ty.is_unsafe_ptr() || left.layout.ty.is_fn_ptr() => {
306+
// The RHS type must be the same *or an integer type* (for `Offset`)
307+
assert!(
308+
right.layout.ty == left.layout.ty || right.layout.ty.is_integral(),
309+
"Unexpected types for BinOp: {:?} {:?} {:?}",
310+
left.layout.ty, bin_op, right.layout.ty
311+
);
312+
313+
M::binary_ptr_op(self, bin_op, left, right)
314+
}
315+
_ => bug!("Invalid MIR: bad LHS type for binop: {:?}", left.layout.ty),
317316
}
318317
}
319318

0 commit comments

Comments
 (0)