Skip to content

Commit dd5c870

Browse files
update contracts
1 parent 16d5a06 commit dd5c870

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

library/core/src/ptr/non_null.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::slice::{self, SliceIndex};
99
use crate::ub_checks::assert_unsafe_precondition;
1010
use crate::{fmt, hash, intrinsics, ptr};
1111
use safety::{ensures, requires};
12-
use crate::{ub_checks};
12+
use crate::ub_checks;
1313

1414

1515
#[cfg(kani)]
@@ -373,6 +373,7 @@ impl<T: ?Sized> NonNull<T> {
373373
#[rustc_const_stable(feature = "const_nonnull_as_ref", since = "1.73.0")]
374374
#[must_use]
375375
#[inline(always)]
376+
#[kani::requires(ub_checks::can_dereference(self.as_ptr() as *const()))] // Ensure input is convertible to a reference
376377
#[ensures(|result: &&T| core::ptr::eq(*result, self.as_ptr()))] // Ensure returned reference matches pointer
377378
pub const unsafe fn as_ref<'a>(&self) -> &'a T {
378379
// SAFETY: the caller must guarantee that `self` meets all the
@@ -412,6 +413,7 @@ impl<T: ?Sized> NonNull<T> {
412413
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
413414
#[must_use]
414415
#[inline(always)]
416+
#[kani::requires(ub_checks::can_dereference(self.as_ptr() as *const()))]
415417
// verify result (a mutable reference) is still associated with the same memory address as the raw pointer stored in self
416418
#[ensures(|result: &&mut T| core::ptr::eq(*result, self.as_ptr()))]
417419
pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
@@ -1583,7 +1585,7 @@ impl<T> NonNull<[T]> {
15831585
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
15841586
#[requires(self.as_ptr().cast::<T>().align_offset(core::mem::align_of::<T>()) == 0)] // Ensure the pointer is properly aligned
15851587
#[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
15871589
#[ensures(|result: &&[MaybeUninit<T>]| core::ptr::eq(result.as_ptr(), self.cast().as_ptr()))] // Ensure the memory addresses match.
15881590
pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit<T>] {
15891591
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
@@ -1652,7 +1654,6 @@ impl<T> NonNull<[T]> {
16521654
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
16531655
#[requires(self.as_ptr().cast::<T>().align_offset(core::mem::align_of::<T>()) == 0)] // Ensure the pointer is properly aligned
16541656
#[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`
16561657
#[ensures(|result: &&mut [MaybeUninit<T>]| result.len() == self.len())] // Length check
16571658
#[ensures(|result: &&mut [MaybeUninit<T>]| core::ptr::eq(result.as_ptr(), self.cast().as_ptr()))] // Address check
16581659
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit<T>] {
@@ -1683,8 +1684,9 @@ impl<T> NonNull<[T]> {
16831684
/// ```
16841685
#[unstable(feature = "slice_ptr_get", issue = "74265")]
16851686
#[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+
)]
16881690
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output>
16891691
where
16901692
I: SliceIndex<[T]>,
@@ -1827,7 +1829,6 @@ mod verify {
18271829
pub fn non_null_check_as_mut() {
18281830
let mut x: i32 = kani::any();
18291831
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);
18311832
unsafe {
18321833
let result = ptr.as_mut();
18331834
}
@@ -1838,7 +1839,6 @@ mod verify {
18381839
pub fn non_null_check_as_ref() {
18391840
let mut x: i32 = kani::any();
18401841
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);
18421842
unsafe {
18431843
let _ = ptr.as_ref();
18441844
}
@@ -1912,9 +1912,14 @@ mod verify {
19121912
NonNull::new(raw_ptr).unwrap(),
19131913
ARR_SIZE,
19141914
);
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);
19161917
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);
19181923
}
19191924
}
19201925
}

0 commit comments

Comments
 (0)