@@ -287,8 +287,33 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
287287 {
288288 0
289289 }
290- // Other ways of comparing integers and pointers can never be known for sure.
291- ( Scalar :: Int { .. } , Scalar :: Ptr ( ..) ) | ( Scalar :: Ptr ( ..) , Scalar :: Int { .. } ) => 2 ,
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.
293+ ( Scalar :: Int ( int) , Scalar :: Ptr ( ptr, _) ) | ( Scalar :: Ptr ( ptr, _) , Scalar :: Int ( int) ) => {
294+ 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.
309+ 0
310+ } 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.
314+ 2
315+ }
316+ }
292317 ( Scalar :: Ptr ( a, _) , Scalar :: Ptr ( b, _) ) => {
293318 let ( a_prov, a_offset) = a. prov_and_relative_offset ( ) ;
294319 let ( b_prov, b_offset) = b. prov_and_relative_offset ( ) ;
@@ -303,7 +328,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
303328 let a_residue = a_offset. bytes ( ) % min_align;
304329 let b_residue = b_offset. bytes ( ) % min_align;
305330 if a_residue != b_residue {
306- // If the two pointers have a different residue from their
331+ // If the two pointers have a different residue modulo their
307332 // common alignment, they cannot be equal.
308333 return interp_ok ( 0 ) ;
309334 }
0 commit comments