@@ -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