creusot_std/cell/
permcell.rs

1//! Shared mutation with a ghost token
2//!
3//! This allows a form of interior mutability, using [ghost](mod@crate::ghost) code to keep
4//! track of the logical value.
5
6use crate::{
7    ghost::perm::{Container, Perm},
8    prelude::*,
9};
10use core::cell::UnsafeCell;
11
12#[cfg(not(feature = "std"))]
13use alloc::boxed::Box;
14
15/// Cell with ghost permissions
16///
17/// When writing/reading the cell, you need to explicitly pass a [`Perm`] object.
18///
19/// # Safety
20///
21/// When using Creusot to verify the code, all methods should be safe to call. Indeed,
22/// Creusot ensures that every operation on the inner value uses the right [`Perm`] object
23/// created by [`PermCell::new`], ensuring safety in a manner similar to
24/// [ghost_cell](https://docs.rs/ghost-cell/latest/ghost_cell/).
25#[repr(transparent)]
26#[opaque]
27pub struct PermCell<T: ?Sized>(UnsafeCell<T>);
28
29impl<T: Sized> Container for PermCell<T> {
30    type Value = T;
31
32    #[logic(open, inline)]
33    fn is_disjoint(&self, _: &T, other: &Self, _: &T) -> bool {
34        self != other
35    }
36}
37
38impl<T: Sized> Invariant for Perm<PermCell<T>> {
39    #[logic(open, prophetic, inline)]
40    #[creusot::trusted_trivial_if_param_trivial]
41    fn invariant(self) -> bool {
42        pearlite! { inv(self.val()) }
43    }
44}
45
46impl<T> PermCell<T> {
47    /// Creates a new `PermCell` containing the given value.
48    #[trusted]
49    #[check(terminates)]
50    #[ensures(result.0 == *result.1.ward())]
51    #[ensures((*result.1)@ == value)]
52    pub fn new(value: T) -> (Self, Ghost<Box<Perm<PermCell<T>>>>) {
53        let this = Self(UnsafeCell::new(value));
54        let perm = Ghost::conjure();
55        (this, perm)
56    }
57
58    /// Sets the contained value.
59    ///
60    /// # Safety
61    ///
62    /// You must ensure that no other borrows to the inner value of `self` exists when calling
63    /// this function.
64    ///
65    /// Creusot will check that all calls to this function are indeed safe: see the
66    /// [type documentation](PermCell#safety).
67    #[trusted]
68    #[check(terminates)]
69    #[requires(self == perm.ward())]
70    #[ensures(val == (^perm)@)]
71    #[ensures(resolve(perm@))]
72    #[ensures(self == (^perm).ward())]
73    pub unsafe fn set(&self, perm: Ghost<&mut Perm<PermCell<T>>>, val: T) {
74        let _ = perm;
75        unsafe {
76            *self.0.get() = val;
77        }
78    }
79
80    /// Replaces the contained value with `val`, and returns the old contained value.
81    ///
82    /// # Safety
83    ///
84    /// You must ensure that no other borrows to the inner value of `self` exists when calling
85    /// this function.
86    ///
87    /// Creusot will check that all calls to this function are indeed safe: see the
88    /// [type documentation](PermCell#safety).
89    #[trusted]
90    #[check(terminates)]
91    #[requires(self == perm.ward())]
92    #[ensures(val == (^perm)@)]
93    #[ensures(result == perm@)]
94    #[ensures(self == (^perm).ward())]
95    pub unsafe fn replace(&self, perm: Ghost<&mut Perm<PermCell<T>>>, val: T) -> T {
96        let _ = perm;
97        unsafe { core::ptr::replace(self.0.get(), val) }
98    }
99
100    /// Unwraps the value, consuming the cell.
101    #[trusted]
102    #[check(terminates)]
103    #[requires(self == *perm.ward())]
104    #[ensures(result == perm@)]
105    pub fn into_inner(self, perm: Ghost<Box<Perm<PermCell<T>>>>) -> T {
106        let _ = perm;
107        self.0.into_inner()
108    }
109
110    /// Immutably borrows the wrapped value.
111    ///
112    /// The permission also acts as a guard, preventing writes to the underlying value
113    /// while it is borrowed.
114    ///
115    /// # Safety
116    ///
117    /// You must ensure that no mutable borrow to the inner value of `self` exists when calling
118    /// this function.
119    ///
120    /// Creusot will check that all calls to this function are indeed safe: see the
121    /// [type documentation](PermCell#safety).
122    #[trusted]
123    #[check(terminates)]
124    #[requires(self == perm.ward())]
125    #[ensures(*result == perm@)]
126    pub unsafe fn borrow<'a>(&'a self, perm: Ghost<&'a Perm<PermCell<T>>>) -> &'a T {
127        let _ = perm;
128        unsafe { &*self.0.get() }
129    }
130
131    /// Mutably borrows the wrapped value.
132    ///
133    /// The permission also acts as a guard, preventing accesses to the underlying value
134    /// while it is borrowed.
135    ///
136    /// # Safety
137    ///
138    /// You must ensure that no other borrows to the inner value of `self` exists when calling
139    /// this function.
140    ///
141    /// Creusot will check that all calls to this function are indeed safe: see the
142    /// [type documentation](PermCell#safety).
143    #[trusted]
144    #[check(terminates)]
145    #[requires(self == perm.ward())]
146    #[ensures(self == (^perm).ward())]
147    #[ensures(*result == perm@)]
148    #[ensures(^result == (^perm)@)]
149    pub unsafe fn borrow_mut<'a>(&'a self, perm: Ghost<&'a mut Perm<PermCell<T>>>) -> &'a mut T {
150        let _ = perm;
151        unsafe { &mut *self.0.get() }
152    }
153}
154
155impl<T: Copy> PermCell<T> {
156    /// Returns a copy of the contained value.
157    ///
158    /// # Safety
159    ///
160    /// You must ensure that no mutable borrow to the inner value of `self` exists when calling
161    /// this function.
162    ///
163    /// Creusot will check that all calls to this function are indeed safe: see the
164    /// [type documentation](PermCell#safety).
165    #[trusted]
166    #[check(terminates)]
167    #[requires(self == perm.ward())]
168    #[ensures(result == (**perm)@)]
169    pub unsafe fn get(&self, perm: Ghost<&Perm<PermCell<T>>>) -> T {
170        let _ = perm;
171        unsafe { *self.0.get() }
172    }
173}
174
175impl<T> PermCell<T> {
176    /// Returns a raw pointer to the underlying data in this cell.
177    #[trusted]
178    #[ensures(true)]
179    pub fn as_ptr(&self) -> *mut T {
180        self.0.get()
181    }
182
183    /// Returns a `&PermCell<T>` from a `&mut T`
184    #[trusted]
185    #[check(terminates)]
186    #[ensures(result.0 == result.1.ward())]
187    #[ensures(^t == (^result.1)@)]
188    #[ensures(*t == result.1@)]
189    pub fn from_mut(t: &mut T) -> (&PermCell<T>, Ghost<&mut Perm<PermCell<T>>>) {
190        // SAFETY: `PermCell` is layout-compatible with `Cell` and `T` because it is `repr(transparent)`.
191        // SAFETY: `&mut` ensures unique access
192        let cell: &PermCell<T> = unsafe { &*(t as *mut T as *const Self) };
193        let perm = Ghost::conjure();
194        (cell, perm)
195    }
196}
197
198impl<T: Default> PermCell<T> {
199    /// Takes the value of the cell, leaving `Default::default()` in its place.
200    ///
201    /// # Safety
202    ///
203    /// You must ensure that no other borrows to the inner value of `self` exists when calling
204    /// this function.
205    ///
206    /// Creusot will check that all calls to this function are indeed safe: see the
207    /// [type documentation](PermCell#safety).
208    #[requires(self == perm.ward())]
209    #[ensures(self == (^perm).ward())]
210    #[ensures(result == perm@)]
211    #[ensures(T::default.postcondition((), (^perm)@))]
212    pub unsafe fn take(&self, perm: Ghost<&mut Perm<PermCell<T>>>) -> T {
213        unsafe { self.replace(perm, T::default()) }
214    }
215}