@@ -139,6 +139,8 @@ impl<T: Sized> NonNull<T> {
139139 #[ must_use]
140140 #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
141141 #[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
142+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure the pointer is valid to create a reference.
143+ #[ ensures( |result: &&MaybeUninit <T >| core:: ptr:: eq( * result, self . cast( ) . as_ptr( ) ) ) ] // Ensure returned reference points to the correct memory location.
142144 pub const unsafe fn as_uninit_ref < ' a > ( self ) -> & ' a MaybeUninit < T > {
143145 // SAFETY: the caller must guarantee that `self` meets all the
144146 // requirements for a reference.
@@ -163,6 +165,8 @@ impl<T: Sized> NonNull<T> {
163165 #[ must_use]
164166 #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
165167 #[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
168+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure pointer is valid to create a mutable reference.
169+ #[ ensures( |result: &&mut MaybeUninit <T >| core:: ptr:: eq( * result, self . cast( ) . as_ptr( ) ) ) ] // Ensure the returned reference points to the correct memory.
166170 pub const unsafe fn as_uninit_mut < ' a > ( self ) -> & ' a mut MaybeUninit < T > {
167171 // SAFETY: the caller must guarantee that `self` meets all the
168172 // requirements for a reference.
@@ -386,6 +390,8 @@ impl<T: ?Sized> NonNull<T> {
386390 #[ rustc_const_stable( feature = "const_nonnull_as_ref" , since = "1.73.0" ) ]
387391 #[ must_use]
388392 #[ inline( always) ]
393+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) as * const ( ) ) ) ] // Ensure input is convertible to a reference
394+ #[ ensures( |result: &&T | core:: ptr:: eq( * result, self . as_ptr( ) ) ) ] // Ensure returned reference matches pointer
389395 pub const unsafe fn as_ref < ' a > ( & self ) -> & ' a T {
390396 // SAFETY: the caller must guarantee that `self` meets all the
391397 // requirements for a reference.
@@ -424,6 +430,9 @@ impl<T: ?Sized> NonNull<T> {
424430 #[ rustc_const_stable( feature = "const_ptr_as_ref" , since = "1.83.0" ) ]
425431 #[ must_use]
426432 #[ inline( always) ]
433+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) as * const ( ) ) ) ]
434+ // verify result (a mutable reference) is still associated with the same memory address as the raw pointer stored in self
435+ #[ ensures( |result: &&mut T | core:: ptr:: eq( * result, self . as_ptr( ) ) ) ]
427436 pub const unsafe fn as_mut < ' a > ( & mut self ) -> & ' a mut T {
428437 // SAFETY: the caller must guarantee that `self` meets all the
429438 // requirements for a mutable reference.
@@ -1642,6 +1651,11 @@ impl<T> NonNull<[T]> {
16421651 #[ must_use]
16431652 #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
16441653 #[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1654+ #[ requires( self . as_ptr( ) . cast:: <T >( ) . align_offset( core:: mem:: align_of:: <T >( ) ) == 0 ) ] // Ensure the pointer is properly aligned
1655+ #[ 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
1656+ #[ requires( kani:: mem:: same_allocation( self . as_ptr( ) as * const ( ) , self . as_ptr( ) . byte_add( self . len( ) * core:: mem:: size_of:: <T >( ) ) as * const ( ) ) ) ] // Ensure the slice is contained within a single allocation
1657+ #[ ensures( |result: &&[ MaybeUninit <T >] | result. len( ) == self . len( ) ) ] // Length check
1658+ #[ ensures( |result: &&[ MaybeUninit <T >] | core:: ptr:: eq( result. as_ptr( ) , self . cast( ) . as_ptr( ) ) ) ] // Ensure the memory addresses match.
16451659 pub const unsafe fn as_uninit_slice < ' a > ( self ) -> & ' a [ MaybeUninit < T > ] {
16461660 // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
16471661 unsafe { slice:: from_raw_parts ( self . cast ( ) . as_ptr ( ) , self . len ( ) ) }
@@ -1707,6 +1721,11 @@ impl<T> NonNull<[T]> {
17071721 #[ must_use]
17081722 #[ unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
17091723 #[ rustc_const_unstable( feature = "ptr_as_uninit" , issue = "75402" ) ]
1724+ #[ requires( self . as_ptr( ) . cast:: <T >( ) . align_offset( core:: mem:: align_of:: <T >( ) ) == 0 ) ] // Ensure the pointer is properly aligned
1725+ #[ 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
1726+ #[ requires( kani:: mem:: same_allocation( self . as_ptr( ) as * const ( ) , self . as_ptr( ) . byte_add( self . len( ) * core:: mem:: size_of:: <T >( ) ) as * const ( ) ) ) ] // Ensure the slice is contained within a single allocation
1727+ #[ ensures( |result: &&mut [ MaybeUninit <T >] | result. len( ) == self . len( ) ) ] // Length check
1728+ #[ ensures( |result: &&mut [ MaybeUninit <T >] | core:: ptr:: eq( result. as_ptr( ) , self . cast( ) . as_ptr( ) ) ) ] // Address check
17101729 pub const unsafe fn as_uninit_slice_mut < ' a > ( self ) -> & ' a mut [ MaybeUninit < T > ] {
17111730 // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
17121731 unsafe { slice:: from_raw_parts_mut ( self . cast ( ) . as_ptr ( ) , self . len ( ) ) }
@@ -1735,6 +1754,7 @@ impl<T> NonNull<[T]> {
17351754 /// ```
17361755 #[ unstable( feature = "slice_ptr_get" , issue = "74265" ) ]
17371756 #[ inline]
1757+ #[ requires( ub_checks:: can_dereference( self . as_ptr( ) ) ) ] // Ensure self can be dereferenced
17381758 pub unsafe fn get_unchecked_mut < I > ( self , index : I ) -> NonNull < I :: Output >
17391759 where
17401760 I : SliceIndex < [ T ] > ,
@@ -1871,7 +1891,7 @@ mod verify {
18711891 let maybe_null_ptr = if kani:: any ( ) { xptr as * mut i32 } else { null_mut ( ) } ;
18721892 let _ = NonNull :: new ( maybe_null_ptr) ;
18731893 }
1874-
1894+
18751895 // pub const unsafe fn read(self) -> T where T: Sized
18761896 #[ kani:: proof_for_contract( NonNull :: read) ]
18771897 pub fn non_null_check_read ( ) {
@@ -1996,4 +2016,106 @@ mod verify {
19962016 // Trigger panic
19972017 let offset = nonnull_xptr. align_offset ( invalid_align) ;
19982018 }
2019+
2020+ #[ kani:: proof_for_contract( NonNull :: as_mut) ]
2021+ pub fn non_null_check_as_mut ( ) {
2022+ let mut x: i32 = kani:: any ( ) ;
2023+ if let Some ( mut ptr) = NonNull :: new ( & mut x as * mut i32 ) {
2024+ unsafe {
2025+ let result = ptr. as_mut ( ) ;
2026+ }
2027+ }
2028+ }
2029+
2030+ #[ kani:: proof_for_contract( NonNull :: as_ref) ]
2031+ pub fn non_null_check_as_ref ( ) {
2032+ let mut x: i32 = kani:: any ( ) ;
2033+ if let Some ( ptr) = NonNull :: new ( & mut x as * mut i32 ) {
2034+ unsafe {
2035+ let _ = ptr. as_ref ( ) ;
2036+ }
2037+ }
2038+ }
2039+
2040+ #[ kani:: proof_for_contract( NonNull :: as_uninit_mut) ]
2041+ pub fn non_null_check_as_uninit_mut ( ) {
2042+ use core:: mem:: MaybeUninit ;
2043+
2044+ // Create an uninitialized MaybeUninit value
2045+ let mut uninit: MaybeUninit < i32 > = MaybeUninit :: uninit ( ) ;
2046+ let mut ptr = NonNull :: new ( uninit. as_mut_ptr ( ) ) . unwrap ( ) ;
2047+
2048+ unsafe {
2049+ let _ = ptr. as_uninit_mut ( ) ;
2050+ }
2051+ }
2052+
2053+ #[ kani:: proof_for_contract( NonNull :: as_uninit_ref) ]
2054+ pub fn non_null_check_as_uninit_ref ( ) {
2055+ use core:: mem:: MaybeUninit ;
2056+
2057+ // Create an uninitialized MaybeUninit value
2058+ let mut uninit: MaybeUninit < i32 > = MaybeUninit :: uninit ( ) ;
2059+ let ptr = NonNull :: new ( uninit. as_mut_ptr ( ) ) . unwrap ( ) ;
2060+
2061+ unsafe {
2062+ let uninit_ref = ptr. as_uninit_ref ( ) ;
2063+ }
2064+ }
2065+
2066+ #[ kani:: proof_for_contract( NonNull :: as_uninit_slice) ]
2067+ pub fn non_null_check_as_uninit_slice ( ) {
2068+ use core:: mem:: MaybeUninit ;
2069+
2070+ const SIZE : usize = 100000 ;
2071+ let arr: [ MaybeUninit < i32 > ; SIZE ] = MaybeUninit :: uninit_array ( ) ;
2072+ let slice: & [ MaybeUninit < i32 > ] = kani:: slice:: any_slice_of_array ( & arr) ;
2073+ let ptr = NonNull :: slice_from_raw_parts (
2074+ NonNull :: new ( slice. as_ptr ( ) as * mut MaybeUninit < i32 > ) . unwrap ( ) ,
2075+ slice. len ( ) ,
2076+ ) ;
2077+
2078+ unsafe {
2079+ let _ = ptr. as_uninit_slice ( ) ;
2080+ }
2081+ }
2082+
2083+ #[ kani:: proof_for_contract( NonNull :: as_uninit_slice_mut) ]
2084+ pub fn non_null_check_as_uninit_slice_mut ( ) {
2085+ use core:: mem:: MaybeUninit ;
2086+
2087+ const SIZE : usize = 100000 ;
2088+ let mut arr: [ MaybeUninit < i32 > ; SIZE ] = MaybeUninit :: uninit_array ( ) ;
2089+ let slice: & [ MaybeUninit < i32 > ] = kani:: slice:: any_slice_of_array ( & mut arr) ;
2090+ let ptr = NonNull :: slice_from_raw_parts (
2091+ NonNull :: new ( slice. as_ptr ( ) as * mut MaybeUninit < i32 > ) . unwrap ( ) ,
2092+ SIZE ,
2093+ ) ;
2094+
2095+ unsafe {
2096+ let _ = ptr. as_uninit_slice_mut ( ) ;
2097+ }
2098+ }
2099+
2100+ #[ kani:: proof_for_contract( NonNull :: get_unchecked_mut) ]
2101+ pub fn non_null_check_get_unchecked_mut ( ) {
2102+ const ARR_SIZE : usize = 100000 ;
2103+ let mut arr: [ i32 ; ARR_SIZE ] = kani:: any ( ) ;
2104+ let raw_ptr = arr. as_mut_ptr ( ) ;
2105+ let ptr = NonNull :: slice_from_raw_parts (
2106+ NonNull :: new ( raw_ptr) . unwrap ( ) ,
2107+ ARR_SIZE ,
2108+ ) ;
2109+ let lower = kani:: any_where ( |x| * x < ARR_SIZE ) ;
2110+ let upper = kani:: any_where ( |x| * x < ARR_SIZE && * x >= lower) ;
2111+ unsafe {
2112+ // NOTE: The `index` parameter cannot be used in the function contracts without being moved.
2113+ // Since the `SliceIndex` trait does not guarantee that `index` implements `Clone` or `Copy`,
2114+ // it cannot be reused after being consumed in the precondition. To comply with Rust's ownership
2115+ // rules and ensure `index` is only used once, the in-bounds check is moved to the proof harness
2116+ // as a workaround.
2117+ kani:: assume ( ptr. as_ref ( ) . get ( lower..upper) . is_some ( ) ) ;
2118+ let _ = ptr. get_unchecked_mut ( lower..upper) ;
2119+ }
2120+ }
19992121}
0 commit comments