@@ -502,6 +502,11 @@ impl<T: ?Sized> NonNull<T> {
502
502
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
503
503
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
504
504
#[ rustc_const_stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
505
+ #[ requires( !origin. as_ptr( ) . is_null( ) ) ]
506
+ #[ ensures(
507
+ |result: & isize |
508
+ * result == ( self . as_ptr( ) as * const u8 ) . offset_from( origin. as_ptr( ) as * const u8 )
509
+ ) ]
505
510
pub const unsafe fn byte_offset ( self , count : isize ) -> Self {
506
511
// SAFETY: the caller must uphold the safety contract for `offset` and `byte_offset` has
507
512
// the same safety contract.
@@ -579,6 +584,11 @@ impl<T: ?Sized> NonNull<T> {
579
584
#[ rustc_allow_const_fn_unstable( set_ptr_value) ]
580
585
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
581
586
#[ rustc_const_stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
587
+ #[ requires( !self . as_ptr( ) . is_null( ) ) ]
588
+ #[ ensures(
589
+ |result: & NonNull <T >|
590
+ ( result. as_ptr( ) as * const ( ) as usize ) == ( ( self . as_ptr( ) as * const ( ) as usize ) + count)
591
+ ) ]
582
592
pub const unsafe fn byte_add ( self , count : usize ) -> Self {
583
593
// SAFETY: the caller must uphold the safety contract for `add` and `byte_add` has the same
584
594
// safety contract.
@@ -783,6 +793,11 @@ impl<T: ?Sized> NonNull<T> {
783
793
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
784
794
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
785
795
#[ rustc_const_stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
796
+ #[ requires( !origin. as_ptr( ) . is_null( ) ) ]
797
+ #[ ensures(
798
+ |result: & isize |
799
+ * result == ( self . as_ptr( ) as * const u8 ) . offset_from( origin. as_ptr( ) as * const u8 )
800
+ ) ]
786
801
pub const unsafe fn byte_offset_from < U : ?Sized > ( self , origin : NonNull < U > ) -> isize {
787
802
// SAFETY: the caller must uphold the safety contract for `byte_offset_from`.
788
803
unsafe { self . pointer . byte_offset_from ( origin. pointer ) }
@@ -1803,4 +1818,63 @@ mod verify {
1803
1818
let maybe_null_ptr = if kani:: any ( ) { xptr as * mut i32 } else { null_mut ( ) } ;
1804
1819
let _ = NonNull :: new ( maybe_null_ptr) ;
1805
1820
}
1821
+
1822
+ #[ kani:: proof_for_contract( NonNull :: byte_add) ]
1823
+ pub fn non_null_byte_add_proof ( ) {
1824
+ const ARR_SIZE : usize = 100000 ;
1825
+ let arr: [ i32 ; ARR_SIZE ] = kani:: any ( ) ;
1826
+ let offset = kani:: any_where ( |x| * x <= ARR_SIZE ) ;
1827
+ let raw_ptr: * mut i32 = arr. as_ptr ( ) as * mut i32 ;
1828
+ let ptr = unsafe { NonNull :: new ( raw_ptr. add ( offset) ) . unwrap ( ) } ;
1829
+ let count: usize = kani:: any ( ) ;
1830
+
1831
+ kani:: assume ( count < usize:: MAX ) ;
1832
+ kani:: assume ( count. checked_mul ( mem:: size_of :: < i32 > ( ) ) . is_some ( ) ) ;
1833
+ kani:: assume ( count * mem:: size_of :: < i32 > ( ) <= ( isize:: MAX as usize ) ) ;
1834
+ kani:: assume ( count < ARR_SIZE - offset) ;
1835
+
1836
+ unsafe {
1837
+ let result = ptr. byte_add ( count) ;
1838
+ }
1839
+ }
1840
+
1841
+ #[ kani:: proof_for_contract( NonNull :: byte_offset) ]
1842
+ pub fn non_null_byte_offset_proof ( ) {
1843
+ const ARR_SIZE : usize = 100000 ;
1844
+ let arr: [ i32 ; ARR_SIZE ] = kani:: any ( ) ;
1845
+ let offset = kani:: any_where ( |x| * x <= ARR_SIZE ) ;
1846
+ let raw_ptr: * mut i32 = arr. as_ptr ( ) as * mut i32 ;
1847
+ let ptr = unsafe { NonNull :: new ( raw_ptr. add ( offset) ) . unwrap ( ) } ;
1848
+ let count: isize = kani:: any ( ) ;
1849
+
1850
+ kani:: assume ( count >= isize:: MIN ) ;
1851
+ kani:: assume ( count <= isize:: MAX ) ;
1852
+ kani:: assume ( count. checked_mul ( mem:: size_of :: < i32 > ( ) as isize ) . is_some ( ) ) ;
1853
+ kani:: assume ( count * ( mem:: size_of :: < i32 > ( ) as isize ) <= ( isize:: MAX as isize ) ) ;
1854
+ kani:: assume ( ( offset as isize + count) < ( ARR_SIZE as isize ) ) ;
1855
+
1856
+ unsafe {
1857
+ let result = ptr. byte_offset ( count) ;
1858
+ }
1859
+ }
1860
+
1861
+ #[ kani:: proof_for_contract( NonNull :: byte_offset_from) ]
1862
+ pub fn non_null_byte_offset_from_proof ( ) {
1863
+ const ARR_SIZE : usize = 100000 ;
1864
+ let arr: [ i32 ; ARR_SIZE ] = kani:: any ( ) ;
1865
+
1866
+ // Randomly generate offsets for the pointers
1867
+ let offset = kani:: any_where ( |x| * x < ARR_SIZE ) ;
1868
+ let origin_offset = kani:: any_where ( |x| * x < ARR_SIZE ) ;
1869
+
1870
+ let raw_ptr: * mut i32 = arr. as_ptr ( ) as * mut i32 ;
1871
+ let origin_ptr: * mut i32 = arr. as_ptr ( ) as * mut i32 ;
1872
+
1873
+ let ptr = unsafe { NonNull :: new ( raw_ptr. add ( offset) ) . unwrap ( ) } ;
1874
+ let origin = unsafe { NonNull :: new ( origin_ptr. add ( origin_offset) ) . unwrap ( ) } ;
1875
+
1876
+ unsafe {
1877
+ let result = ptr. byte_offset_from ( origin) ;
1878
+ }
1879
+ }
1806
1880
}
0 commit comments