Skip to main content

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::{
8        NotObjective,
9        perm::{Perm, PermTarget},
10    },
11    prelude::*,
12};
13use core::{cell::UnsafeCell, marker::PhantomData};
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#[trusted(positive(T))]
26#[opaque]
27#[repr(transparent)]
28pub struct PermCell<T: ?Sized>(UnsafeCell<T>);
29
30impl<T: ?Sized> PermTarget for PermCell<T> {
31    type Value<'a>
32        = &'a T
33    where
34        Self: 'a;
35    type PermPayload = (NotObjective, PhantomData<T>);
36}
37
38#[trusted]
39unsafe impl<T: ?Sized> Send for PermCell<T> {}
40#[trusted]
41unsafe impl<T: ?Sized> Sync for PermCell<T> {}
42
43impl<T: ?Sized> Invariant for Perm<PermCell<T>> {
44    #[logic(open, prophetic, inline)]
45    #[creusot::trusted_trivial_if_param_trivial]
46    fn invariant(self) -> bool {
47        pearlite! { inv(self.val()) }
48    }
49}
50
51impl<T: ?Sized> PermCell<T> {
52    /// Creates a new `PermCell` containing the given value.
53    #[trusted]
54    #[check(terminates)]
55    #[ensures(result.0 == *result.1.ward())]
56    #[ensures(*result.1.val() == value)]
57    pub fn new(value: T) -> (Self, Ghost<Perm<PermCell<T>>>)
58    where
59        T: Sized,
60    {
61        let this = Self(UnsafeCell::new(value));
62        let perm = Ghost::conjure();
63        (this, perm)
64    }
65
66    /// Sets the contained value.
67    ///
68    /// # Safety
69    ///
70    /// You must ensure that no other borrows to the inner value of `self` exists when calling
71    /// this function.
72    ///
73    /// Creusot will check that all calls to this function are indeed safe: see the
74    /// [type documentation](PermCell#safety).
75    #[trusted]
76    #[check(terminates)]
77    #[requires(self == perm.ward())]
78    #[ensures(val == *(^perm).val())]
79    #[ensures(resolve(*perm.val()))]
80    #[ensures(self == (^perm).ward())]
81    pub unsafe fn set(&self, perm: Ghost<&mut Perm<PermCell<T>>>, val: T)
82    where
83        T: Sized,
84    {
85        let _ = perm;
86        unsafe {
87            *self.0.get() = val;
88        }
89    }
90
91    /// Replaces the contained value with `val`, and returns the old contained value.
92    ///
93    /// # Safety
94    ///
95    /// You must ensure that no other borrows to the inner value of `self` exists when calling
96    /// this function.
97    ///
98    /// Creusot will check that all calls to this function are indeed safe: see the
99    /// [type documentation](PermCell#safety).
100    #[trusted]
101    #[check(terminates)]
102    #[requires(self == perm.ward())]
103    #[ensures(val == *(^perm).val())]
104    #[ensures(result == *perm.val())]
105    #[ensures(self == (^perm).ward())]
106    pub unsafe fn replace(&self, perm: Ghost<&mut Perm<PermCell<T>>>, val: T) -> T
107    where
108        T: Sized,
109    {
110        let _ = perm;
111        unsafe { core::ptr::replace(self.0.get(), val) }
112    }
113
114    /// Unwraps the value, consuming the cell.
115    #[trusted]
116    #[check(terminates)]
117    #[requires(self == *perm.ward())]
118    #[ensures(result == *perm.val())]
119    pub fn into_inner(self, perm: Ghost<Perm<PermCell<T>>>) -> T
120    where
121        T: Sized,
122    {
123        let _ = perm;
124        self.0.into_inner()
125    }
126
127    /// Immutably borrows the wrapped value.
128    ///
129    /// The permission also acts as a guard, preventing writes to the underlying value
130    /// while it is borrowed.
131    ///
132    /// # Safety
133    ///
134    /// You must ensure that no mutable borrow to the inner value of `self` exists when calling
135    /// this function.
136    ///
137    /// Creusot will check that all calls to this function are indeed safe: see the
138    /// [type documentation](PermCell#safety).
139    #[trusted]
140    #[check(terminates)]
141    #[requires(self == perm.ward())]
142    #[ensures(*result == *perm.val())]
143    pub unsafe fn borrow<'a>(&'a self, perm: Ghost<&'a Perm<PermCell<T>>>) -> &'a T {
144        let _ = perm;
145        unsafe { &*self.0.get() }
146    }
147
148    /// Mutably borrows the wrapped value.
149    ///
150    /// The permission also acts as a guard, preventing accesses to the underlying value
151    /// while it is borrowed.
152    ///
153    /// # Safety
154    ///
155    /// You must ensure that no other borrows to the inner value of `self` exists when calling
156    /// this function.
157    ///
158    /// Creusot will check that all calls to this function are indeed safe: see the
159    /// [type documentation](PermCell#safety).
160    #[trusted]
161    #[check(terminates)]
162    #[requires(self == perm.ward())]
163    #[ensures(self == (^perm).ward())]
164    #[ensures(*result == *perm.val())]
165    #[ensures(^result == *(^perm).val())]
166    pub unsafe fn borrow_mut<'a>(&'a self, perm: Ghost<&'a mut Perm<PermCell<T>>>) -> &'a mut T {
167        let _ = perm;
168        unsafe { &mut *self.0.get() }
169    }
170
171    /// Returns a copy of the contained value.
172    ///
173    /// # Safety
174    ///
175    /// You must ensure that no mutable borrow to the inner value of `self` exists when calling
176    /// this function.
177    ///
178    /// Creusot will check that all calls to this function are indeed safe: see the
179    /// [type documentation](PermCell#safety).
180    #[trusted]
181    #[check(terminates)]
182    #[requires(self == perm.ward())]
183    #[ensures(result == *perm.val())]
184    pub unsafe fn get(&self, perm: Ghost<&Perm<PermCell<T>>>) -> T
185    where
186        T: Copy + Sized,
187    {
188        let _ = perm;
189        unsafe { *self.0.get() }
190    }
191
192    /// Returns a raw pointer to the underlying data in this cell.
193    #[trusted]
194    #[ensures(true)]
195    pub fn as_ptr(&self) -> *mut T {
196        self.0.get()
197    }
198
199    /// Returns a `&PermCell<T>` from a `&mut T`
200    #[trusted]
201    #[check(terminates)]
202    #[ensures(result.0 == result.1.ward())]
203    #[ensures(^t == *(^result.1).val())]
204    #[ensures(*t == *result.1.val())]
205    pub fn from_mut(t: &mut T) -> (&PermCell<T>, Ghost<&mut Perm<PermCell<T>>>) {
206        // SAFETY: `PermCell` is layout-compatible with `Cell` and `T` because it is `repr(transparent)`.
207        // SAFETY: `&mut` ensures unique access
208        let cell: &PermCell<T> = unsafe { &*(t as *mut T as *const Self) };
209        let perm = Ghost::conjure();
210        (cell, perm)
211    }
212
213    /// Takes the value of the cell, leaving `Default::default()` in its place.
214    ///
215    /// # Safety
216    ///
217    /// You must ensure that no other borrows to the inner value of `self` exists when calling
218    /// this function.
219    ///
220    /// Creusot will check that all calls to this function are indeed safe: see the
221    /// [type documentation](PermCell#safety).
222    #[requires(self == perm.ward())]
223    #[ensures(self == (^perm).ward())]
224    #[ensures(result == *perm.val())]
225    #[ensures(T::default.postcondition((), *(^perm).val()))]
226    pub unsafe fn take(&self, perm: Ghost<&mut Perm<PermCell<T>>>) -> T
227    where
228        T: Default,
229    {
230        unsafe { self.replace(perm, T::default()) }
231    }
232}