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