@@ -3,6 +3,10 @@ use crate::cmp::Ordering::{Equal, Greater, Less};
33use  crate :: intrinsics:: const_eval_select; 
44use  crate :: mem:: SizedTypeProperties ; 
55use  crate :: slice:: { self ,  SliceIndex } ; 
6+ use  safety:: { ensures,  requires} ; 
7+ 
8+ #[ cfg( kani) ]  
9+ use  crate :: kani; 
610
711impl < T :  ?Sized >  * const  T  { 
812    /// Returns `true` if the pointer is null. 
@@ -667,6 +671,16 @@ impl<T: ?Sized> *const T {
667671    #[ rustc_const_stable( feature = "const_ptr_offset_from" ,  since = "1.65.0" ) ]  
668672    #[ inline]  
669673    #[ cfg_attr( miri,  track_caller) ]   // even without panics, this helps for Miri backtraces 
674+     #[ requires(  
675+         // Ensures subtracting `origin` from `self` doesn't overflow  
676+         ( self  as  isize ) . checked_sub( origin as  isize ) . is_some( )  && 
677+         // Ensure the distance between `self` and `origin` is aligned to `T`  
678+         ( self  as  isize  - origin as  isize )  % ( mem:: size_of:: <T >( )  as  isize )  == 0  && 
679+         // Ensure both pointers are in the same allocation or are pointing to the same address  
680+         ( self  as  isize  == origin as  isize  || kani:: mem:: same_allocation( self ,  origin) )  
681+     ) ]  
682+     // The result should equal the distance in terms of elements of type `T` as per the documentation above 
683+     #[ ensures( |result| * result == ( self  as  isize  - origin as  isize )  / ( mem:: size_of:: <T >( )  as  isize ) ) ]  
670684    pub  const  unsafe  fn  offset_from ( self ,  origin :  * const  T )  -> isize 
671685    where 
672686        T :  Sized , 
@@ -1899,3 +1913,149 @@ impl<T: ?Sized> PartialOrd for *const T {
18991913        * self  >= * other
19001914    } 
19011915} 
1916+ 
1917+ #[ cfg( kani) ]  
1918+ #[ unstable( feature = "kani" ,  issue = "none" ) ]  
1919+ mod  verify { 
1920+     use  crate :: kani; 
1921+     use  core:: mem; 
1922+     use  kani:: PointerGenerator ; 
1923+ 
1924+     // Proof for unit size will panic as offset_from needs the pointee size to be greater then 0 
1925+     #[ kani:: proof_for_contract( <* const  ( ) >:: offset_from) ]  
1926+     #[ kani:: should_panic]  
1927+     pub  fn  check_const_offset_from_unit ( )  { 
1928+         let  val:  ( )  = ( ) ; 
1929+         let  src_ptr:  * const  ( )  = & val; 
1930+         let  dest_ptr:  * const  ( )  = & val; 
1931+         unsafe  { 
1932+             dest_ptr. offset_from ( src_ptr) ; 
1933+         } 
1934+     } 
1935+ 
1936+     // Array size bound for kani::any_array 
1937+     const  ARRAY_LEN :  usize  = 40 ; 
1938+ 
1939+     macro_rules!  generate_offset_from_harness { 
1940+         ( $type:  ty,  $proof_name1:  ident,  $proof_name2:  ident)  => { 
1941+             // Proof for a single element 
1942+             #[ kani:: proof_for_contract( <* const  $type>:: offset_from) ] 
1943+             pub  fn  $proof_name1( )  { 
1944+                 const  gen_size:  usize  = mem:: size_of:: <$type>( ) ; 
1945+                 let  mut  generator1 = PointerGenerator :: <gen_size>:: new( ) ; 
1946+                 let  mut  generator2 = PointerGenerator :: <gen_size>:: new( ) ; 
1947+                 let  ptr1:  * const  $type = generator1. any_in_bounds( ) . ptr; 
1948+                 let  ptr2:  * const  $type = if  kani:: any( )  { 
1949+                     generator1. any_alloc_status( ) . ptr
1950+                 }  else { 
1951+                     generator2. any_alloc_status( ) . ptr
1952+                 } ; 
1953+ 
1954+                 unsafe  { 
1955+                     ptr1. offset_from( ptr2) ; 
1956+                 } 
1957+             } 
1958+ 
1959+             // Proof for large arrays 
1960+             #[ kani:: proof_for_contract( <* const  $type>:: offset_from) ] 
1961+             pub  fn  $proof_name2( )  { 
1962+                 const  gen_size:  usize  = mem:: size_of:: <$type>( ) ; 
1963+                 let  mut  generator1 = PointerGenerator :: <{  gen_size *  ARRAY_LEN  } >:: new( ) ; 
1964+                 let  mut  generator2 = PointerGenerator :: <{  gen_size *  ARRAY_LEN  } >:: new( ) ; 
1965+                 let  ptr1:  * const  $type = generator1. any_in_bounds( ) . ptr; 
1966+                 let  ptr2:  * const  $type = if  kani:: any( )  { 
1967+                     generator1. any_alloc_status( ) . ptr
1968+                 }  else { 
1969+                     generator2. any_alloc_status( ) . ptr
1970+                 } ; 
1971+ 
1972+                 unsafe  { 
1973+                     ptr1. offset_from( ptr2) ; 
1974+                 } 
1975+             } 
1976+         } ; 
1977+     } 
1978+ 
1979+     generate_offset_from_harness ! ( 
1980+         u8 , 
1981+         check_const_offset_from_u8, 
1982+         check_const_offset_from_u8_arr
1983+     ) ; 
1984+     generate_offset_from_harness ! ( 
1985+         u16 , 
1986+         check_const_offset_from_u16, 
1987+         check_const_offset_from_u16_arr
1988+     ) ; 
1989+     generate_offset_from_harness ! ( 
1990+         u32 , 
1991+         check_const_offset_from_u32, 
1992+         check_const_offset_from_u32_arr
1993+     ) ; 
1994+     generate_offset_from_harness ! ( 
1995+         u64 , 
1996+         check_const_offset_from_u64, 
1997+         check_const_offset_from_u64_arr
1998+     ) ; 
1999+     generate_offset_from_harness ! ( 
2000+         u128 , 
2001+         check_const_offset_from_u128, 
2002+         check_const_offset_from_u128_arr
2003+     ) ; 
2004+     generate_offset_from_harness ! ( 
2005+         usize , 
2006+         check_const_offset_from_usize, 
2007+         check_const_offset_from_usize_arr
2008+     ) ; 
2009+ 
2010+     generate_offset_from_harness ! ( 
2011+         i8 , 
2012+         check_const_offset_from_i8, 
2013+         check_const_offset_from_i8_arr
2014+     ) ; 
2015+     generate_offset_from_harness ! ( 
2016+         i16 , 
2017+         check_const_offset_from_i16, 
2018+         check_const_offset_from_i16_arr
2019+     ) ; 
2020+     generate_offset_from_harness ! ( 
2021+         i32 , 
2022+         check_const_offset_from_i32, 
2023+         check_const_offset_from_i32_arr
2024+     ) ; 
2025+     generate_offset_from_harness ! ( 
2026+         i64 , 
2027+         check_const_offset_from_i64, 
2028+         check_const_offset_from_i64_arr
2029+     ) ; 
2030+     generate_offset_from_harness ! ( 
2031+         i128 , 
2032+         check_const_offset_from_i128, 
2033+         check_const_offset_from_i128_arr
2034+     ) ; 
2035+     generate_offset_from_harness ! ( 
2036+         isize , 
2037+         check_const_offset_from_isize, 
2038+         check_const_offset_from_isize_arr
2039+     ) ; 
2040+ 
2041+     generate_offset_from_harness ! ( 
2042+         ( i8 ,  i8 ) , 
2043+         check_const_offset_from_tuple_1, 
2044+         check_const_offset_from_tuple_1_arr
2045+     ) ; 
2046+     generate_offset_from_harness ! ( 
2047+         ( f64 ,  bool ) , 
2048+         check_const_offset_from_tuple_2, 
2049+         check_const_offset_from_tuple_2_arr
2050+     ) ; 
2051+     generate_offset_from_harness ! ( 
2052+         ( u32 ,  i16 ,  f32 ) , 
2053+         check_const_offset_from_tuple_3, 
2054+         check_const_offset_from_tuple_3_arr
2055+     ) ; 
2056+     generate_offset_from_harness ! ( 
2057+         ( ( ) ,  bool ,  u8 ,  u16 ,  i32 ,  f64 ,  i128 ,  usize ) , 
2058+         check_const_offset_from_tuple_4, 
2059+         check_const_offset_from_tuple_4_arr
2060+     ) ; 
2061+ } 
0 commit comments