@@ -9,7 +9,7 @@ use crate::slice::{self, SliceIndex};
9
9
use crate :: ub_checks:: assert_unsafe_precondition;
10
10
use crate :: { fmt, hash, intrinsics, ptr} ;
11
11
use safety:: { ensures, requires} ;
12
- use crate :: { ub_checks} ;
12
+ use crate :: ub_checks;
13
13
14
14
15
15
#[ cfg( kani) ]
@@ -373,6 +373,7 @@ impl<T: ?Sized> NonNull<T> {
373
373
#[ rustc_const_stable( feature = "const_nonnull_as_ref" , since = "1.73.0" ) ]
374
374
#[ must_use]
375
375
#[ inline( always) ]
376
+ #[ kani:: requires( ub_checks:: can_dereference( self . as_ptr( ) as * const ( ) ) ) ] // Ensure input is convertible to a reference
376
377
#[ ensures( |result: &&T | core:: ptr:: eq( * result, self . as_ptr( ) ) ) ] // Ensure returned reference matches pointer
377
378
pub const unsafe fn as_ref < ' a > ( & self ) -> & ' a T {
378
379
// SAFETY: the caller must guarantee that `self` meets all the
@@ -412,6 +413,7 @@ impl<T: ?Sized> NonNull<T> {
412
413
#[ rustc_const_unstable( feature = "const_ptr_as_ref" , issue = "91822" ) ]
413
414
#[ must_use]
414
415
#[ inline( always) ]
416
+ #[ kani:: requires( ub_checks:: can_dereference( self . as_ptr( ) as * const ( ) ) ) ]
415
417
// verify result (a mutable reference) is still associated with the same memory address as the raw pointer stored in self
416
418
#[ ensures( |result: &&mut T | core:: ptr:: eq( * result, self . as_ptr( ) ) ) ]
417
419
pub const unsafe fn as_mut < ' a > ( & mut self ) -> & ' a mut T {
@@ -1583,7 +1585,7 @@ impl<T> NonNull<[T]> {
1583
1585
#[ rustc_const_unstable( feature = "const_ptr_as_ref" , issue = "91822" ) ]
1584
1586
#[ requires( self . as_ptr( ) . cast:: <T >( ) . align_offset( core:: mem:: align_of:: <T >( ) ) == 0 ) ] // Ensure the pointer is properly aligned
1585
1587
#[ requires( self . len( ) . checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) && self . len( ) * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize ) ] // Ensure the slice size does not exceed isize::MAX
1586
- // TODO: add a require to check the slice belong to same allocated object with `same_allocation`
1588
+ # [ ensures ( |result : && [ MaybeUninit < T > ] | result . len ( ) == self . len ( ) ) ] // Length check
1587
1589
#[ ensures( |result: &&[ MaybeUninit <T >] | core:: ptr:: eq( result. as_ptr( ) , self . cast( ) . as_ptr( ) ) ) ] // Ensure the memory addresses match.
1588
1590
pub const unsafe fn as_uninit_slice < ' a > ( self ) -> & ' a [ MaybeUninit < T > ] {
1589
1591
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
@@ -1652,7 +1654,6 @@ impl<T> NonNull<[T]> {
1652
1654
#[ rustc_const_unstable( feature = "const_ptr_as_ref" , issue = "91822" ) ]
1653
1655
#[ requires( self . as_ptr( ) . cast:: <T >( ) . align_offset( core:: mem:: align_of:: <T >( ) ) == 0 ) ] // Ensure the pointer is properly aligned
1654
1656
#[ requires( self . len( ) . checked_mul( core:: mem:: size_of:: <T >( ) ) . is_some( ) && self . len( ) * core:: mem:: size_of:: <T >( ) <= isize :: MAX as usize ) ] // Ensure the slice size does not exceed isize::MAX
1655
- // TODO: add a require to check the slice belong to same allocated object with `same_allocation`
1656
1657
#[ ensures( |result: &&mut [ MaybeUninit <T >] | result. len( ) == self . len( ) ) ] // Length check
1657
1658
#[ ensures( |result: &&mut [ MaybeUninit <T >] | core:: ptr:: eq( result. as_ptr( ) , self . cast( ) . as_ptr( ) ) ) ] // Address check
1658
1659
pub const unsafe fn as_uninit_slice_mut < ' a > ( self ) -> & ' a mut [ MaybeUninit < T > ] {
@@ -1683,8 +1684,9 @@ impl<T> NonNull<[T]> {
1683
1684
/// ```
1684
1685
#[ unstable( feature = "slice_ptr_get" , issue = "74265" ) ]
1685
1686
#[ inline]
1686
- #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure self is dereferenceable
1687
- #[ ensures( |result: & NonNull <I :: Output >| result. as_ptr( ) as * mut ( ) != core:: ptr:: null_mut( ) ) ] // Ensure valid non-null pointer
1687
+ #[ requires(
1688
+ ub_checks:: can_dereference( self . as_ptr( ) ) // Ensure self can be dereferenced
1689
+ ) ]
1688
1690
pub unsafe fn get_unchecked_mut < I > ( self , index : I ) -> NonNull < I :: Output >
1689
1691
where
1690
1692
I : SliceIndex < [ T ] > ,
@@ -1827,7 +1829,6 @@ mod verify {
1827
1829
pub fn non_null_check_as_mut ( ) {
1828
1830
let mut x: i32 = kani:: any ( ) ;
1829
1831
if let Some ( mut ptr) = NonNull :: new ( & mut x as * mut i32 ) {
1830
- kani:: assume ( ptr. as_ptr ( ) . align_offset ( core:: mem:: align_of :: < i32 > ( ) ) == 0 ) ;
1831
1832
unsafe {
1832
1833
let result = ptr. as_mut ( ) ;
1833
1834
}
@@ -1838,7 +1839,6 @@ mod verify {
1838
1839
pub fn non_null_check_as_ref ( ) {
1839
1840
let mut x: i32 = kani:: any ( ) ;
1840
1841
if let Some ( ptr) = NonNull :: new ( & mut x as * mut i32 ) {
1841
- kani:: assume ( ptr. as_ptr ( ) . align_offset ( core:: mem:: align_of :: < i32 > ( ) ) == 0 ) ;
1842
1842
unsafe {
1843
1843
let _ = ptr. as_ref ( ) ;
1844
1844
}
@@ -1912,9 +1912,14 @@ mod verify {
1912
1912
NonNull :: new ( raw_ptr) . unwrap ( ) ,
1913
1913
ARR_SIZE ,
1914
1914
) ;
1915
- let index = kani:: any_where ( |x| * x < ARR_SIZE - 1 ) ;
1915
+ let lower = kani:: any_where ( |x| * x < ARR_SIZE ) ;
1916
+ let upper = kani:: any_where ( |x| * x < ARR_SIZE && * x >= lower) ;
1916
1917
unsafe {
1917
- let _ = ptr. get_unchecked_mut ( index..index + 1 ) ;
1918
+ // NOTE: The `index` parameter cannot be used in the function contracts without being moved.
1919
+ // Since `SliceIndex` does not guarantee that `index` implements `Clone` or `Copy`. To ensure 'index' is only used once,
1920
+ // we put the in-bound check in proof harness as a workaround
1921
+ kani:: assume ( ptr. as_ref ( ) . get ( lower..upper) . is_some ( ) ) ;
1922
+ let _ = ptr. get_unchecked_mut ( lower..upper) ;
1918
1923
}
1919
1924
}
1920
1925
}
0 commit comments