Skip to content

Commit c155b26

Browse files
authored
Contracts and harnesses for ptr::Unique (rust-lang#45)
1 parent 24a0b16 commit c155b26

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

library/core/src/ptr/unique.rs

Lines changed: 89 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,17 @@ impl<T: ?Sized> Unique<T> {
8488
///
8589
/// `ptr` must be non-null.
8690
#[inline]
91+
#[requires(!ptr.is_null())]
92+
#[ensures(|result| result.as_ptr() == ptr)]
8793
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
8894
// SAFETY: the caller must guarantee that `ptr` is non-null.
8995
unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } }
9096
}
9197

9298
/// Creates a new `Unique` if `ptr` is non-null.
9399
#[inline]
100+
#[ensures(|result| result.is_none() == ptr.is_null())]
101+
#[ensures(|result| result.is_none() || result.unwrap().as_ptr() == ptr)]
94102
pub const fn new(ptr: *mut T) -> Option<Self> {
95103
if let Some(pointer) = NonNull::new(ptr) {
96104
Some(Unique { pointer, _marker: PhantomData })
@@ -102,13 +110,15 @@ impl<T: ?Sized> Unique<T> {
102110
/// Acquires the underlying `*mut` pointer.
103111
#[must_use = "`self` will be dropped if the result is not used"]
104112
#[inline]
113+
#[ensures(|result| !result.is_null())]
105114
pub const fn as_ptr(self) -> *mut T {
106115
self.pointer.as_ptr()
107116
}
108117

109118
/// Acquires the underlying `*mut` pointer.
110119
#[must_use = "`self` will be dropped if the result is not used"]
111120
#[inline]
121+
#[ensures(|result| result.as_ptr() == self.pointer.as_ptr())]
112122
pub const fn as_non_null_ptr(self) -> NonNull<T> {
113123
self.pointer
114124
}
@@ -201,3 +211,82 @@ impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
201211
Unique { pointer, _marker: PhantomData }
202212
}
203213
}
214+
215+
#[cfg(kani)]
216+
#[unstable(feature="kani", issue="none")]
217+
mod verify {
218+
use super::*;
219+
220+
// pub const unsafe fn new_unchecked(ptr: *mut T) -> Self
221+
#[kani::proof_for_contract(Unique::new_unchecked)]
222+
pub fn check_new_unchecked() {
223+
let mut x : i32 = kani::any();
224+
let xptr = &mut x;
225+
unsafe {
226+
let _ = Unique::new_unchecked(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 = kani::any();
234+
let xptr = &mut x;
235+
let _ = Unique::new(xptr as *mut i32);
236+
}
237+
238+
// pub const fn as_ptr(self) -> *mut T
239+
#[kani::proof_for_contract(Unique::as_ptr)]
240+
pub fn check_as_ptr() {
241+
let mut x : i32 = kani::any();
242+
let xptr = &mut x;
243+
unsafe {
244+
let unique = Unique::new_unchecked(xptr as *mut i32);
245+
assert_eq!(unique.as_ptr(), xptr as *mut i32);
246+
}
247+
}
248+
249+
// pub const fn as_non_null_ptr(self) -> NonNull<T>
250+
#[kani::proof_for_contract(Unique::as_non_null_ptr)]
251+
pub fn check_as_non_null_ptr() {
252+
let mut x : i32 = kani::any();
253+
let xptr = &mut x;
254+
unsafe {
255+
let unique = Unique::new_unchecked(xptr as *mut i32);
256+
let _ = unique.as_non_null_ptr();
257+
}
258+
}
259+
260+
// pub const unsafe fn as_ref(&self) -> &T
261+
#[kani::proof]
262+
pub fn check_as_ref() {
263+
let mut x : i32 = kani::any();
264+
let xptr = &mut x;
265+
unsafe {
266+
let unique = Unique::new_unchecked(xptr as *mut i32);
267+
assert_eq!(*unique.as_ref(), x);
268+
}
269+
}
270+
271+
// pub const unsafe fn as_mut(&mut self) -> &mut T
272+
#[kani::proof]
273+
pub fn check_as_mut() {
274+
let mut x : i32 = kani::any();
275+
let xptr = &mut x;
276+
unsafe {
277+
let mut unique = Unique::new_unchecked(xptr as *mut i32);
278+
assert_eq!(*unique.as_mut(), x);
279+
}
280+
}
281+
282+
// pub const fn cast<U>(self) -> Unique<U>
283+
#[kani::proof_for_contract(Unique::cast<U>)]
284+
pub fn check_cast<U>() {
285+
let mut x : i32 = kani::any();
286+
let xptr = &mut x;
287+
unsafe {
288+
let unique = Unique::new_unchecked(xptr as *mut i32);
289+
assert_eq!(*unique.cast::<u32>().as_ref(), x as u32);
290+
}
291+
}
292+
}

0 commit comments

Comments
 (0)