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