@@ -251,8 +251,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
251251 }
252252
253253 "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) ?;
256274 if a. alloc_id != b. alloc_id {
257275 throw_ub_format ! (
258276 "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> {
266284 BinOp :: Sub , a_offset, b_offset,
267285 ) ?;
268286 let pointee_layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
269- let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
270287 let val = ImmTy :: from_scalar ( val, isize_layout) ;
271288 let size = ImmTy :: from_int ( pointee_layout. size . bytes ( ) , isize_layout) ;
272289 self . exact_div ( val, size, dest) ?;
0 commit comments