@@ -251,8 +251,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
251
251
}
252
252
253
253
"ptr_offset_from" => {
254
- let a = self . force_ptr ( self . read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?) ?;
255
- let b = self . force_ptr ( self . read_immediate ( args[ 1 ] ) ?. to_scalar ( ) ?) ?;
254
+ let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
255
+ let a = self . read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?;
256
+ let b = self . read_immediate ( args[ 1 ] ) ?. to_scalar ( ) ?;
257
+
258
+ // Special case: if both scalars are *equal integers*
259
+ // and not NULL, their offset is 0.
260
+ // This is the dual to the special exception for offset-by-0
261
+ // in the inbounds pointer offset operation.
262
+ if a. is_bits ( ) && b. is_bits ( ) {
263
+ let a = a. to_usize ( self ) ?;
264
+ let b = b. to_usize ( self ) ?;
265
+ if a == b && a != 0 {
266
+ self . write_scalar ( Scalar :: from_int ( 0 , isize_layout. size ) , dest) ?;
267
+ return Ok ( true ) ;
268
+ }
269
+ }
270
+
271
+ // General case: we need two pointers.
272
+ let a = self . force_ptr ( a) ?;
273
+ let b = self . force_ptr ( b) ?;
256
274
if a. alloc_id != b. alloc_id {
257
275
throw_ub_format ! (
258
276
"ptr_offset_from cannot compute offset of pointers into different \
@@ -266,7 +284,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
266
284
BinOp :: Sub , a_offset, b_offset,
267
285
) ?;
268
286
let pointee_layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
269
- let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
270
287
let val = ImmTy :: from_scalar ( val, isize_layout) ;
271
288
let size = ImmTy :: from_int ( pointee_layout. size . bytes ( ) , isize_layout) ;
272
289
self . exact_div ( val, size, dest) ?;
0 commit comments