Skip to content

Commit 6c2610d

Browse files
committed
Contracts and harnesses for ptr::Unique
1 parent 4f4d032 commit 6c2610d

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

library/core/src/ptr/unique.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
use safety::{ensures, requires};
12
use crate::fmt;
23
use crate::marker::{PhantomData, Unsize};
34
use crate::ops::{CoerceUnsized, DispatchFromDyn};
45
use crate::ptr::NonNull;
56

7+
#[cfg(kani)]
8+
use crate::kani;
9+
610
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
711
/// of this wrapper owns the referent. Useful for building abstractions like
812
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
@@ -84,13 +88,16 @@ impl<T: ?Sized> Unique<T> {
8488
///
8589
/// `ptr` must be non-null.
8690
#[inline]
91+
#[requires(!ptr.is_null())]
8792
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
8893
// SAFETY: the caller must guarantee that `ptr` is non-null.
8994
unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } }
9095
}
9196

9297
/// Creates a new `Unique` if `ptr` is non-null.
9398
#[inline]
99+
#[ensures(|result| result.is_none() == result.unwrap().as_ptr().is_null())]
100+
#[ensures(|result| result.is_none() || result.unwrap().as_ptr() == ptr)]
94101
pub const fn new(ptr: *mut T) -> Option<Self> {
95102
if let Some(pointer) = NonNull::new(ptr) {
96103
Some(Unique { pointer, _marker: PhantomData })
@@ -102,6 +109,7 @@ impl<T: ?Sized> Unique<T> {
102109
/// Acquires the underlying `*mut` pointer.
103110
#[must_use = "`self` will be dropped if the result is not used"]
104111
#[inline]
112+
#[ensures(|result| !result.is_null())]
105113
pub const fn as_ptr(self) -> *mut T {
106114
self.pointer.as_ptr()
107115
}
@@ -201,3 +209,92 @@ impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
201209
Unique { pointer, _marker: PhantomData }
202210
}
203211
}
212+
213+
#[cfg(kani)]
214+
#[unstable(feature="kani", issue="none")]
215+
mod verify {
216+
use super::*;
217+
218+
// pub const unsafe fn new_unchecked(ptr: *mut T) -> Self
219+
#[kani::proof_for_contract(Unique::new_unchecked)]
220+
pub fn check_new_unchecked() {
221+
let mut x : i32 = 42;
222+
let xptr = &mut x;
223+
224+
unsafe {
225+
let unique = Unique::new_unchecked(xptr as *mut i32);
226+
assert_eq!(unique.as_ptr(), xptr as *mut i32);
227+
}
228+
}
229+
230+
// pub const fn new(ptr: *mut T) -> Option<Self>
231+
#[kani::proof_for_contract(Unique::new)]
232+
pub fn check_new() {
233+
let mut x : i32 = 42;
234+
let xptr = &mut x;
235+
236+
if let Some(unique) = Unique::new(xptr as *mut i32) {
237+
assert_eq!(unique.as_ptr(), xptr as *mut i32);
238+
}
239+
}
240+
241+
// pub const fn as_ptr(self) -> *mut T
242+
#[kani::proof_for_contract(Unique::as_ptr)]
243+
pub fn check_as_ptr() {
244+
let mut x : i32 = 42;
245+
let xptr = &mut x;
246+
247+
unsafe {
248+
let unique = Unique::new_unchecked(xptr as *mut i32);
249+
assert_eq!(unique.as_ptr(), xptr as *mut i32);
250+
}
251+
}
252+
253+
// pub const fn as_non_null_ptr(self) -> NonNull<T>
254+
#[kani::proof]
255+
pub fn check_as_non_null_ptr() {
256+
let mut x : i32 = 42;
257+
let xptr = &mut x;
258+
259+
unsafe {
260+
let unique = Unique::new_unchecked(xptr as *mut i32);
261+
assert_eq!(unique.as_non_null_ptr().as_ptr(), xptr as *mut i32);
262+
}
263+
}
264+
265+
// pub const unsafe fn as_ref(&self) -> &T
266+
#[kani::proof]
267+
pub fn check_as_ref() {
268+
let mut x : i32 = 42;
269+
let xptr = &mut x;
270+
271+
unsafe {
272+
let unique = Unique::new_unchecked(xptr as *mut i32);
273+
assert_eq!(*unique.as_ref(), x);
274+
}
275+
}
276+
277+
// pub const unsafe fn as_mut(&mut self) -> &mut T
278+
#[kani::proof]
279+
pub fn check_as_mut() {
280+
let mut x : i32 = 42;
281+
let xptr = &mut x;
282+
283+
unsafe {
284+
let mut unique = Unique::new_unchecked(xptr as *mut i32);
285+
assert_eq!(*unique.as_mut(), x);
286+
}
287+
}
288+
289+
// pub const fn cast<U>(self) -> Unique<U>
290+
#[kani::proof_for_contract(Unique::cast<U>)]
291+
pub fn check_cast<U>() {
292+
let mut x : i32 = 42;
293+
let xptr = &mut x;
294+
295+
unsafe {
296+
let unique = Unique::new_unchecked(xptr as *mut i32);
297+
assert_eq!(*unique.cast::<u32>().as_ref(), x as u32);
298+
}
299+
}
300+
}

0 commit comments

Comments
 (0)