@@ -674,6 +674,12 @@ impl<T: ?Sized> NonNull<T> {
674
674
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
675
675
#[ rustc_const_stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
676
676
#[ cfg_attr( bootstrap, rustc_allow_const_fn_unstable( unchecked_neg) ) ]
677
+ #[ requires(
678
+ count. checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) &&
679
+ count * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize &&
680
+ kani:: mem:: same_allocation( self . as_ptr( ) , self . as_ptr( ) . wrapping_sub( count) )
681
+ ) ]
682
+ #[ ensures( |result: & NonNull <T >| result. as_ptr( ) == self . as_ptr( ) . offset( -( count as isize ) ) ) ]
677
683
pub const unsafe fn sub ( self , count : usize ) -> Self
678
684
where
679
685
T : Sized ,
@@ -803,6 +809,11 @@ impl<T: ?Sized> NonNull<T> {
803
809
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
804
810
#[ stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
805
811
#[ rustc_const_stable( feature = "non_null_convenience" , since = "1.80.0" ) ]
812
+ #[ requires(
813
+ ( kani:: mem:: same_allocation( self . as_ptr( ) , origin. as_ptr( ) ) &&
814
+ ( ( self . as_ptr( ) . addr( ) - origin. as_ptr( ) . addr( ) ) % core:: mem:: size_of:: <T >( ) == 0 ) )
815
+ ) ] // Ensure both pointers meet safety conditions for offset_from
816
+ #[ ensures( |result: & isize | * result == ( self . as_ptr( ) as isize - origin. as_ptr( ) as isize ) / core:: mem:: size_of:: <T >( ) as isize ) ]
806
817
pub const unsafe fn offset_from ( self , origin : NonNull < T > ) -> isize
807
818
where
808
819
T : Sized ,
@@ -901,6 +912,13 @@ impl<T: ?Sized> NonNull<T> {
901
912
#[ cfg_attr( miri, track_caller) ] // even without panics, this helps for Miri backtraces
902
913
#[ unstable( feature = "ptr_sub_ptr" , issue = "95892" ) ]
903
914
#[ rustc_const_unstable( feature = "const_ptr_sub_ptr" , issue = "95892" ) ]
915
+ #[ requires(
916
+ self . as_ptr( ) . addr( ) . checked_sub( subtracted. as_ptr( ) . addr( ) ) . is_some( ) &&
917
+ kani:: mem:: same_allocation( self . as_ptr( ) , subtracted. as_ptr( ) ) &&
918
+ ( self . as_ptr( ) . addr( ) ) >= ( subtracted. as_ptr( ) . addr( ) ) &&
919
+ ( self . as_ptr( ) . addr( ) - subtracted. as_ptr( ) . addr( ) ) % core:: mem:: size_of:: <T >( ) == 0
920
+ ) ]
921
+ #[ ensures( |result: & usize | * result == self . as_ptr( ) . offset_from( subtracted. as_ptr( ) ) as usize ) ]
904
922
pub const unsafe fn sub_ptr ( self , subtracted : NonNull < T > ) -> usize
905
923
where
906
924
T : Sized ,
@@ -2402,6 +2420,75 @@ mod verify {
2402
2420
let result = non_null_ptr. is_aligned_to ( align) ;
2403
2421
}
2404
2422
2423
+ #[ kani:: proof_for_contract( NonNull :: sub) ]
2424
+ pub fn non_null_check_sub ( ) {
2425
+ const SIZE : usize = 10000 ;
2426
+ let mut generator = kani:: PointerGenerator :: < SIZE > :: new ( ) ;
2427
+ // Get a raw pointer from the generator within bounds
2428
+ let raw_ptr: * mut i32 = generator. any_in_bounds ( ) . ptr ;
2429
+ // Create a non-null pointer from the raw pointer
2430
+ let ptr = unsafe { NonNull :: new ( raw_ptr) . unwrap ( ) } ;
2431
+ // Create a non-deterministic count value
2432
+ let count: usize = kani:: any ( ) ;
2433
+
2434
+ unsafe {
2435
+ let result = ptr. sub ( count) ;
2436
+ }
2437
+ }
2438
+
2439
+ #[ kani:: proof_for_contract( NonNull :: sub_ptr) ]
2440
+ pub fn non_null_check_sub_ptr ( ) {
2441
+ const SIZE : usize = core:: mem:: size_of :: < i32 > ( ) * 1000 ;
2442
+ let mut generator1 = kani:: PointerGenerator :: < SIZE > :: new ( ) ;
2443
+ let mut generator2 = kani:: PointerGenerator :: < SIZE > :: new ( ) ;
2444
+
2445
+ let ptr: * mut i32 = if kani:: any ( ) {
2446
+ generator1. any_in_bounds ( ) . ptr as * mut i32
2447
+ } else {
2448
+ generator2. any_in_bounds ( ) . ptr as * mut i32
2449
+ } ;
2450
+
2451
+ let origin: * mut i32 = if kani:: any ( ) {
2452
+ generator1. any_in_bounds ( ) . ptr as * mut i32
2453
+ } else {
2454
+ generator2. any_in_bounds ( ) . ptr as * mut i32
2455
+ } ;
2456
+
2457
+ let ptr_nonnull = unsafe { NonNull :: new ( ptr) . unwrap ( ) } ;
2458
+ let origin_nonnull = unsafe { NonNull :: new ( origin) . unwrap ( ) } ;
2459
+
2460
+ unsafe {
2461
+ let distance = ptr_nonnull. sub_ptr ( origin_nonnull) ;
2462
+ }
2463
+ }
2464
+
2465
+ #[ kani:: proof_for_contract( NonNull :: offset_from) ]
2466
+ #[ kani:: should_panic]
2467
+ pub fn non_null_check_offset_from ( ) {
2468
+ const SIZE : usize = core:: mem:: size_of :: < i32 > ( ) * 1000 ;
2469
+ let mut generator1 = kani:: PointerGenerator :: < SIZE > :: new ( ) ;
2470
+ let mut generator2 = kani:: PointerGenerator :: < SIZE > :: new ( ) ;
2471
+
2472
+ let ptr: * mut i32 = if kani:: any ( ) {
2473
+ generator1. any_in_bounds ( ) . ptr as * mut i32
2474
+ } else {
2475
+ generator2. any_in_bounds ( ) . ptr as * mut i32
2476
+ } ;
2477
+
2478
+ let origin: * mut i32 = if kani:: any ( ) {
2479
+ generator1. any_in_bounds ( ) . ptr as * mut i32
2480
+ } else {
2481
+ generator2. any_in_bounds ( ) . ptr as * mut i32
2482
+ } ;
2483
+
2484
+ let ptr_nonnull = unsafe { NonNull :: new ( ptr) . unwrap ( ) } ;
2485
+ let origin_nonnull = unsafe { NonNull :: new ( origin) . unwrap ( ) } ;
2486
+
2487
+ unsafe {
2488
+ let distance = ptr_nonnull. offset_from ( origin_nonnull) ;
2489
+ }
2490
+ }
2491
+
2405
2492
#[ kani:: proof_for_contract( NonNull :: byte_add) ]
2406
2493
pub fn non_null_byte_add_proof ( ) {
2407
2494
const ARR_SIZE : usize = mem:: size_of :: < i32 > ( ) * 1000 ;
0 commit comments