@@ -280,37 +280,25 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
280280        interp_ok ( match  ( a,  b)  { 
281281            // Comparisons between integers are always known. 
282282            ( Scalar :: Int ( a) ,  Scalar :: Int ( b) )  => ( a == b)  as  u8 , 
283-             // Comparisons of null with an arbitrary scalar can be known  if `scalar_may_be_null`  
284-             // indicates  that the scalar can definitely *not* be null.  
285-             ( Scalar :: Int ( int ) ,  ptr )  |  ( ptr ,   Scalar :: Int ( int ) ) 
286-                  if  int . is_null ( )  && ! self . scalar_may_be_null ( ptr ) ? => 
287-             { 
288-                  0 
289-             } 
290-             // Other ways of comparing integers and pointers can never be known for sure,  
291-             // except for alignment, e.g. `1 as *const _` can never be equal to an even offset  
292-             // in an `align(2)` allocation . 
283+             // A pointer can be known to be unequal to an integer  if them being equal would imply  
284+             // that the null pointer is in-bounds (including one-past-the-end) of the pointer's  
285+             // allocation (as the null pointer is never in-bounds of any allocation), or is 
286+             // misaligned (as `0` is a multiple of any alignment), or that the pointer's 
287+             // allocation would wrap around the address space. 
288+             // Concretely, if `scalar_may_be_null` indicates that `ptr.wrapping_sub(int)` cannot 
289+             // be equal to `0`, then we know that `ptr != int`. 
290+             // For the specific case where `int == 0`, this checks if the pointer itself  
291+             // can definitely not be null, and this behavior is exposed on stable as  
292+             // `pointer::is_null` . 
293293            ( Scalar :: Int ( int) ,  Scalar :: Ptr ( ptr,  _) )  | ( Scalar :: Ptr ( ptr,  _) ,  Scalar :: Int ( int) )  => { 
294294                let  int = int. to_target_usize ( * self . tcx ) ; 
295-                 let  ( ptr_prov,  ptr_offset)  = ptr. prov_and_relative_offset ( ) ; 
296-                 let  allocid = ptr_prov. alloc_id ( ) ; 
297-                 let  allocinfo = self . get_alloc_info ( allocid) ; 
298- 
299-                 // Check if the pointer cannot be equal to the integer due to alignment. 
300-                 // For this purpose, an integer can be thought of as an offset into a 
301-                 // maximally-aligned "allocation" (the whole address space), 
302-                 // so the least common alignment is the alignment of the pointer's allocation. 
303-                 let  min_align = allocinfo. align . bytes ( ) ; 
304-                 let  ptr_residue = ptr_offset. bytes ( )  % min_align; 
305-                 let  int_residue = int % min_align; 
306-                 if  ptr_residue != int_residue { 
307-                     // The pointer and integer have a different residue modulo their common 
308-                     // alignment, they can never be equal. 
295+                 let  offset_ptr = ptr. wrapping_offset ( Size :: from_bytes ( int. wrapping_neg ( ) ) ,  self ) ; 
296+                 if  !self . scalar_may_be_null ( Scalar :: from_pointer ( offset_ptr,  self ) ) ? { 
297+                     // `ptr.wrapping_sub(int)` is definitely not equal to `0`, so `ptr != int` 
309298                    0 
310299                }  else  { 
311-                     // The pointer and integer have the same residue modulo their common alignment, 
312-                     // so the pointer could end up equal to the integer at runtime; 
313-                     // we can't know for sure. 
300+                     // `ptr.wrapping_sub(int)` could be equal to `0`, but might not be, 
301+                     // so we cannot know for sure if `ptr == int` or not 
314302                    2 
315303                } 
316304            } 
0 commit comments