ghost_cell/
ghost_cell.rs

1//! `GhostCell` and `GhostToken`, as per <https://plv.mpi-sws.org/rustbelt/ghostcell/>.
2//!
3//! Reference implementation at <https://gitlab.mpi-sws.org/FP/ghostcell/-/tree/master/ghostcell>.
4
5use core::{cell::UnsafeCell, marker::PhantomData, mem};
6
7/// A `GhostToken<'x>` is _the_ key to access the content of any `&GhostCell<'x, _>` sharing the same brand.
8///
9/// Each `GhostToken<'x>` is created alongside a unique brand (its lifetime), and each `GhostCell<'x, T>` is associated
10/// to one, and only one, `GhostToken` at a time via this brand. The entire set of `GhostCell<'x, T>` associated to a
11/// given `GhostToken<'x>` creates a pool of cells all being accessible solely through the one token they are associated
12/// to.
13///
14/// The pool of `GhostCell` associated to a token need not be homogeneous, each may own a value of a different type.
15pub struct GhostToken<'brand> {
16    _marker: InvariantLifetime<'brand>,
17}
18
19impl<'brand> GhostToken<'brand> {
20    /// Creates a fresh token to which `GhostCell`s can be tied to later.
21    ///
22    /// Due to the use of a lifetime, the `GhostCell`s tied to a given token can only live within the confines of the
23    /// invocation of the `fun` closure.
24    ///
25    /// #   Example
26    ///
27    /// ```rust
28    /// use ghost_cell::{GhostToken, GhostCell};
29    ///
30    /// let n = 12;
31    ///
32    /// let value = GhostToken::new(|mut token| {
33    ///     let cell = GhostCell::new(42);
34    ///
35    ///     let vec: Vec<_> = (0..n).map(|_| &cell).collect();
36    ///
37    ///     *vec[n / 2].borrow_mut(&mut token) = 33;
38    ///
39    ///     *cell.borrow(&token)
40    /// });
41    ///
42    /// assert_eq!(33, value);
43    /// ```
44    #[allow(clippy::new_ret_no_self)]
45    pub fn new<R, F>(fun: F) -> R
46    where
47        for<'new_brand> F: FnOnce(GhostToken<'new_brand>) -> R,
48    {
49        let token = Self {
50            _marker: InvariantLifetime::default(),
51        };
52        fun(token)
53    }
54}
55
56/// A `GhostToken` is stateless, therefore it can safely be passed across threads.
57unsafe impl<'brand> Send for GhostToken<'brand> {}
58
59/// A `GhostToken` is stateless, therefore it can safely be accessed from different threads.
60unsafe impl<'brand> Sync for GhostToken<'brand> {}
61
62/// Branded wrapper for a value, whose type is `T`.
63///
64/// A `GhostCell<'x, T>` owns an instance of type `T`:
65/// -   Unique access to the cell allows unimpeded access to the contained value.
66/// -   Shared access to the cell requires mediating access through the associated `GhostToken<'x, T>` which will
67///     enforce at compile-time the aliasing XOR mutability safety property.
68#[repr(transparent)]
69pub struct GhostCell<'brand, T: ?Sized> {
70    _marker: InvariantLifetime<'brand>,
71    value: UnsafeCell<T>,
72}
73
74impl<'brand, T> GhostCell<'brand, T> {
75    /// Wraps some `T` into a `GhostCell` with brand `'brand` which associates it to one, and only one, `GhostToken`.
76    ///
77    /// #   Example
78    ///
79    /// ```rust
80    /// use ghost_cell::{GhostToken, GhostCell};
81    ///
82    /// GhostToken::new(|token| {
83    ///     let cell = GhostCell::new(42);
84    ///
85    ///     assert_eq!(42, *cell.borrow(&token));
86    /// });
87    /// ```
88    pub const fn new(value: T) -> Self {
89        let _marker = PhantomData;
90        let value = UnsafeCell::new(value);
91
92        Self { _marker, value }
93    }
94
95    /// Turns an owned `GhostCell` back into owned data.
96    ///
97    /// #   Example
98    ///
99    /// ```rust
100    /// use ghost_cell::{GhostToken, GhostCell};
101    ///
102    /// let value = GhostToken::new(|mut token| {
103    ///     let cell = GhostCell::new(42);
104    ///
105    ///     cell.into_inner()
106    /// });
107    ///
108    /// assert_eq!(42, value);
109    /// ```
110    pub fn into_inner(self) -> T {
111        self.value.into_inner()
112    }
113}
114
115impl<'brand, T: ?Sized> GhostCell<'brand, T> {
116    /// Immutably borrows the `GhostCell` with the same-branded token.
117    ///
118    /// #   Example
119    ///
120    /// ```rust
121    /// use ghost_cell::{GhostToken, GhostCell};
122    ///
123    /// let n = 12;
124    ///
125    /// let value = GhostToken::new(|mut token| {
126    ///     let cell = GhostCell::new(42);
127    ///
128    ///     let vec: Vec<_> = (0..n).map(|_| &cell).collect();
129    ///
130    ///     let one: &i32 = vec[1].borrow(&token);
131    ///     let two: &i32 = vec[2].borrow(&token);
132    ///
133    ///     *one + *two
134    /// });
135    ///
136    /// assert_eq!(84, value);
137    /// ```
138    pub fn borrow<'a>(&'a self, _: &'a GhostToken<'brand>) -> &'a T {
139        //  Safety:
140        //  -   The cell is borrowed immutably by this call, it therefore cannot already be borrowed mutably.
141        //  -   The token is borrowed immutably by this call, it therefore cannot be already borrowed mutably.
142        //  -   `self.value` therefore cannot be already borrowed mutably, as doing so requires calling either:
143        //      -   `borrow_mut`, which would borrow the token mutably.
144        //      -   `get_mut`, which would borrow the cell mutably.
145        unsafe { &*self.value.get() }
146    }
147
148    /// Mutably borrows the `GhostCell` with the same-branded token.
149    ///
150    /// #   Example
151    ///
152    /// ```rust
153    /// use ghost_cell::{GhostToken, GhostCell};
154    ///
155    /// let n = 12;
156    ///
157    /// let value = GhostToken::new(|mut token| {
158    ///     let cell = GhostCell::new(42);
159    ///
160    ///     let vec: Vec<_> = (0..n).map(|_| &cell).collect();
161    ///
162    ///     let reference: &mut i32 = vec[n / 2].borrow_mut(&mut token);
163    ///     *reference = 33;
164    ///
165    ///     *cell.borrow(&token)
166    /// });
167    ///
168    /// assert_eq!(33, value);
169    /// ```
170    pub fn borrow_mut<'a>(&'a self, _: &'a mut GhostToken<'brand>) -> &'a mut T {
171        //  Safety:
172        //  -   The cell is borrowed immutably by this call, it therefore cannot already be borrowed mutably.
173        //  -   The token is borrowed mutably by this call, it therefore cannot be already borrowed.
174        //  -   `self.value` therefore cannot already be borrowed, as doing so requires calling either:
175        //      -   `borrow` or `borrow_mut`, which would borrow the token.
176        //      -   `get_mut`, which would borrow the cell mutably.
177        unsafe { &mut *self.value.get() }
178    }
179
180    /// Returns a raw pointer to the contained value.
181    pub const fn as_ptr(&self) -> *mut T {
182        self.value.get()
183    }
184
185    /// Turns a mutably borrowed `GhostCell` into mutably borrowed data.
186    ///
187    /// `self` is mutably borrowed for the lifetime of the result, ensuring the absence of aliasing.
188    ///
189    /// #   Example
190    ///
191    /// ```rust
192    /// use ghost_cell::{GhostToken, GhostCell};
193    ///
194    /// let value = GhostToken::new(|mut token| {
195    ///     let mut cell = GhostCell::new(42);
196    ///
197    ///     *cell.get_mut() = 33;
198    ///
199    ///     *cell.borrow(&token)
200    /// });
201    ///
202    /// assert_eq!(33, value);
203    /// ```
204    pub fn get_mut(&mut self) -> &mut T {
205        //  Safety:
206        //  -   `self` is mutably borrowed for the duration.
207        //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
208        unsafe { mem::transmute(self) }
209    }
210
211    /// Turns mutably borrowed data into a mutably borrowed `GhostCell`.
212    ///
213    /// `t` is mutably borrowed for the lifetime of the result, ensuring the absence of aliasing.
214    ///
215    /// #   Example
216    ///
217    /// ```rust
218    /// use ghost_cell::{GhostToken, GhostCell};
219    ///
220    /// let n = 12;
221    /// let mut value = 42;
222    ///
223    /// GhostToken::new(|mut token| {
224    ///     let cell = GhostCell::from_mut(&mut value);
225    ///
226    ///     let vec: Vec<_> = (0..n).map(|_| &cell).collect();
227    ///
228    ///     *vec[n / 2].borrow_mut(&mut token) = 33;
229    /// });
230    ///
231    /// assert_eq!(33, value);
232    /// ```
233    pub fn from_mut(t: &mut T) -> &mut Self {
234        //  Safety:
235        //  -   `t` is mutably borrowed for the duration.
236        //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
237        unsafe { mem::transmute(t) }
238    }
239}
240
241//  Safe convenience methods
242#[forbid(unsafe_code)]
243impl<'brand, T> GhostCell<'brand, T> {
244    /// Returns the value, replacing it by the supplied one.
245    ///
246    /// #   Example
247    ///
248    /// ```rust
249    /// use ghost_cell::{GhostToken, GhostCell};
250    ///
251    /// let n = 12;
252    ///
253    /// let value = GhostToken::new(|mut token| {
254    ///     let cell = GhostCell::new(42);
255    ///
256    ///     let vec: Vec<_> = (0..n).map(|_| &cell).collect();
257    ///
258    ///     let previous = vec[n / 2].replace(33, &mut token);
259    ///     assert_eq!(42, previous);
260    ///
261    ///     *cell.borrow(&token)
262    /// });
263    ///
264    /// assert_eq!(33, value);
265    /// ```
266    pub fn replace(&self, value: T, token: &mut GhostToken<'brand>) -> T {
267        mem::replace(self.borrow_mut(token), value)
268    }
269
270    /// Returns the value, replacing it with the default value.
271    ///
272    /// #   Example
273    ///
274    /// ```rust
275    /// use ghost_cell::{GhostToken, GhostCell};
276    ///
277    /// let n = 12;
278    ///
279    /// let value = GhostToken::new(|mut token| {
280    ///     let cell = GhostCell::new(42);
281    ///
282    ///     let vec: Vec<_> = (0..n).map(|_| &cell).collect();
283    ///
284    ///     let previous = vec[n / 2].take(&mut token);
285    ///     assert_eq!(42, previous);
286    ///
287    ///     *cell.borrow(&token)
288    /// });
289    ///
290    /// assert_eq!(0, value);
291    /// ```
292    pub fn take(&self, token: &mut GhostToken<'brand>) -> T
293    where
294        T: Default,
295    {
296        self.replace(T::default(), token)
297    }
298
299    /// Swaps the values of two cells.
300    ///
301    /// If the cells fully overlap, i.e. they have the same address, they are "swapped" (a no-op) and `Ok` is returned.
302    /// `Err` is returned if they overlap in any other way and can't be swapped.
303    ///
304    /// #   Example
305    ///
306    /// ```rust
307    /// use ghost_cell::{GhostToken, GhostCell};
308    ///
309    /// let n = 12;
310    ///
311    /// let value = GhostToken::new(|mut token| {
312    ///     let cell1 = GhostCell::new(42);
313    ///     let cell2 = GhostCell::new(33);
314    ///
315    ///     let vec: Vec<_> = (0..n).flat_map(|_| [&cell1, &cell2]).collect();
316    ///
317    ///     vec[n / 2].swap(&vec[n / 2 + 1], &mut token).expect("overlapping references");
318    ///
319    ///     *cell1.borrow(&token)
320    /// });
321    ///
322    /// assert_eq!(33, value);
323    /// ```
324    #[cfg(feature = "experimental-multiple-mutable-borrows")]
325    pub fn swap(
326        &self,
327        other: &Self,
328        token: &mut GhostToken<'brand>,
329    ) -> Result<(), crate::ghost_borrow_mut::GhostAliasingError> {
330        // Ignore full overlap.
331        if core::ptr::eq(self, other) {
332            return Ok(());
333        }
334
335        crate::ghost_borrow_mut::GhostBorrowMut::borrow_mut((self, other), token).map(|(a, b)| mem::swap(a, b))
336    }
337}
338
339impl<'brand, T: Default> Default for GhostCell<'brand, T> {
340    fn default() -> Self {
341        Self::new(T::default())
342    }
343}
344
345impl<'brand, T> GhostCell<'brand, [T]> {
346    /// Returns a slice of cells from a cell containing a slice.
347    ///
348    /// #   Example
349    ///
350    /// ```rust
351    /// use ghost_cell::{GhostToken, GhostCell};
352    ///
353    /// let n = 12;
354    ///
355    /// let value = GhostToken::new(|mut token| {
356    ///     let mut vec: Vec<_> = (0..n).collect();
357    ///     let cell = GhostCell::from_mut(&mut vec[..]);
358    ///
359    ///     let slice = cell.as_slice_of_cells();
360    ///
361    ///     *slice[n / 2].borrow_mut(&mut token) = 33;
362    ///
363    ///     vec[n / 2]
364    /// });
365    ///
366    /// assert_eq!(33, value);
367    /// ```
368    pub fn as_slice_of_cells(&self) -> &[GhostCell<'brand, T>] {
369        //  Safety:
370        //  -   Same lifetime.
371        //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
372        unsafe { &*(self.as_ptr() as *mut [GhostCell<'brand, T>]) }
373    }
374
375    /// Returns a cell containing a slice from slice of cells.
376    ///
377    /// #   Example
378    ///
379    /// ```rust
380    /// use ghost_cell::{GhostToken, GhostCell};
381    ///
382    /// let n = 12;
383    ///
384    /// let value = GhostToken::new(|mut token| {
385    ///     let mut vec: Vec<_> = (0..n).collect();
386    ///     let cell = GhostCell::from_mut(&mut vec[..]);
387    ///     let all_elements = cell.as_slice_of_cells();
388    ///
389    ///     let quad = GhostCell::from_slice_of_cells(&all_elements[4..][..4]);
390    ///     quad.borrow_mut(&mut token).copy_from_slice(&33u32.to_be_bytes());
391    ///
392    ///     vec.iter().position(|&v| v == 33)
393    /// });
394    ///
395    /// assert_eq!(Some(7), value);
396    /// ```
397    pub fn from_slice_of_cells<'slice>(slice: &'slice [GhostCell<'brand, T>]) -> &'slice Self {
398        //  Safety:
399        //  -   Same lifetime.
400        //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
401        unsafe { &*(slice as *const _ as *const GhostCell<'brand, [T]>) }
402    }
403}
404
405impl<'brand, T, const N: usize> GhostCell<'brand, [T; N]> {
406    /// Returns a reference to an array of cells from a cell containing an array.
407    ///
408    /// #   Example
409    ///
410    /// ```rust
411    /// use ghost_cell::{GhostToken, GhostCell};
412    ///
413    /// let value = GhostToken::new(|mut token| {
414    ///     let mut array = [0, 1, 2, 3, 5];
415    ///     let n = array.len();
416    ///
417    ///     let cell = GhostCell::from_mut(&mut array);
418    ///
419    ///     let inner = cell.as_array_of_cells();
420    ///
421    ///     *inner[n / 2].borrow_mut(&mut token) = 33;
422    ///
423    ///     array[n / 2]
424    /// });
425    ///
426    /// assert_eq!(33, value);
427    /// ```
428    pub fn as_array_of_cells(&self) -> &[GhostCell<'brand, T>; N] {
429        //  Safety:
430        //  -   Same lifetime.
431        //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
432        unsafe { &*(self.as_ptr() as *mut [GhostCell<'brand, T>; N]) }
433    }
434
435    /// Returns a cell containing an array from an array of cells.
436    ///
437    /// #   Example
438    ///
439    /// ```rust
440    /// use ghost_cell::{GhostToken, GhostCell};
441    ///
442    /// let value = GhostToken::new(|mut token| {
443    ///     let mut array = [0, 1, 2, 3, 5];
444    ///     let n = array.len();
445    ///
446    ///     let cell = GhostCell::from_mut(&mut array);
447    ///
448    ///     let inner = cell.as_array_of_cells();
449    ///
450    ///     let inner = GhostCell::from_array_of_cells(&inner);
451    ///
452    ///     inner.borrow_mut(&mut token)[n / 2] = 33;
453    ///
454    ///     array[n / 2]
455    /// });
456    ///
457    /// assert_eq!(33, value);
458    /// ```
459    pub fn from_array_of_cells<'a>(array: &'a [GhostCell<'brand, T>; N]) -> &'a Self {
460        //  Safety:
461        //  -   Same lifetime.
462        //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
463        unsafe { &*(array as *const [GhostCell<'brand, T>; N] as *const Self) }
464    }
465}
466
467macro_rules! ghost_cell_transpose_tuple {
468    ($($t:ident),*) => {
469        impl<'brand, $($t),*> GhostCell<'brand, ($($t,)*)> {
470            /// Returns a reference to a tuple of cells from a cell containing a tuple.
471            pub fn as_tuple_of_cells(&self) -> &($(GhostCell<'brand, $t>,)*) {
472                //  Safety:
473                //  -   Same lifetime.
474                //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
475                unsafe { &*(self.as_ptr() as *mut ($(GhostCell<'brand, $t>,)*)) }
476            }
477
478            /// Returns a cell containing a tuple from a tuple of cells.
479            #[allow(clippy::needless_lifetimes)]
480            pub fn from_tuple_of_cells<'a>(tuple: &'a ($(GhostCell<'brand, $t>,)*)) -> &'a Self {
481                //  Safety:
482                //  -   Same lifetime.
483                //  -   `GhostCell<'_, T>` has the same in-memory representation as `T`.
484                unsafe { &*(tuple as *const ($(GhostCell<'brand, $t>,)*) as *const Self) }
485            }
486        }
487    }
488}
489
490ghost_cell_transpose_tuple!();
491ghost_cell_transpose_tuple!(T0);
492ghost_cell_transpose_tuple!(T0, T1);
493ghost_cell_transpose_tuple!(T0, T1, T2);
494ghost_cell_transpose_tuple!(T0, T1, T2, T3);
495ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4);
496ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5);
497ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5, T6);
498ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
499ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
500ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
501ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
502ghost_cell_transpose_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
503
504impl<'brand, T: ?Sized> AsMut<T> for GhostCell<'brand, T> {
505    fn as_mut(&mut self) -> &mut T {
506        self.get_mut()
507    }
508}
509
510impl<'brand, T> From<T> for GhostCell<'brand, T> {
511    fn from(t: T) -> Self {
512        Self::new(t)
513    }
514}
515
516/// A `GhostCell<'_, T>` owns a `T`, so it cannot be sent across threads if `T` cannot.
517///
518/// Conversely, a `GhostCell` does not add any state on top of `T`, so if `T` can be sent across threads, so can
519/// `GhostCell<'_, T>`
520unsafe impl<'brand, T: ?Sized + Send> Send for GhostCell<'brand, T> {}
521
522/// A `GhostCell<'_, T>` owns a `T`, so it cannot be accessed from different threads if `T` cannot.
523///
524/// Conversely, a `GhostCell` does not add any state on top of `T`, so if `T` can be accessed from different threads,
525/// so can `GhostCell<'_, T>`. `T` also needs to be sendable across threads,
526/// because a `T` can be extracted from a `&GhostCell<'brand, T>` via [`GhostCell::replace`].
527unsafe impl<'brand, T: ?Sized + Send + Sync> Sync for GhostCell<'brand, T> {}
528
529//
530//  Implementation
531//
532
533type InvariantLifetime<'brand> = PhantomData<fn(&'brand ()) -> &'brand ()>;
534
535#[doc(hidden)]
536pub mod compile_tests {
537
538    /// ```compile_fail
539    /// use ghost_cell::{GhostToken, GhostCell};
540    ///
541    /// GhostToken::new(|token| token);
542    /// ```
543    pub fn token_noescape() {}
544
545    /// ```compile_fail
546    /// use ghost_cell::{GhostToken, GhostCell};
547    ///
548    /// GhostToken::new(|mut token| {
549    ///     let cell = GhostCell::new(42);
550    ///
551    ///     *cell.borrow_mut(&mut token) = 33;
552    ///
553    ///     cell
554    /// });
555    /// ```
556    pub fn cell_noescape() {}
557
558    /// ```compile_fail,E0505
559    /// use ghost_cell::{GhostToken, GhostCell};
560    ///
561    /// GhostToken::new(|token| {
562    ///     let cell = GhostCell::new(42);
563    ///
564    ///     let r = cell.borrow(&token);
565    ///     std::mem::drop(token);
566    ///
567    ///     *r
568    /// });
569    /// ```
570    pub fn cell_borrow_borrows_token() {}
571
572    /// ```compile_fail,E0502
573    /// use ghost_cell::{GhostToken, GhostCell};
574    ///
575    /// GhostToken::new(|mut token| {
576    ///     let one = GhostCell::new(1);
577    ///     let two = GhostCell::new(2);
578    ///
579    ///     let r = one.borrow_mut(&mut token);
580    ///     assert_eq!(2, *two.borrow(&token));
581    ///
582    ///     *r = 33;
583    /// });
584    /// ```
585    pub fn cell_borrow_mut_borrows_token_mutably() {}
586
587    /// ```compile_fail,E0505
588    /// use ghost_cell::{GhostToken, GhostCell};
589    ///
590    /// GhostToken::new(|token| {
591    ///     let cell = GhostCell::new(42);
592    ///
593    ///     let r = cell.borrow(&token);
594    ///     std::mem::drop(cell);
595    ///
596    ///     *r
597    /// });
598    /// ```
599    pub fn cell_borrow_borrows_cell() {}
600
601    /// ```compile_fail,E0505
602    /// use ghost_cell::{GhostToken, GhostCell};
603    ///
604    /// GhostToken::new(|mut token| {
605    ///     let cell = GhostCell::new(42);
606    ///
607    ///     let r = cell.borrow_mut(&mut token);
608    ///     std::mem::drop(cell);
609    ///
610    ///     *r
611    /// });
612    /// ```
613    pub fn cell_borrow_mut_borrows_cell() {}
614
615    /// ```compile_fail,E0502
616    /// use ghost_cell::{GhostToken, GhostCell};
617    ///
618    /// GhostToken::new(|token| {
619    ///     let mut cell = GhostCell::new(42);
620    ///
621    ///     let r = cell.get_mut();
622    ///     assert_eq!(42, *cell.borrow(&token));
623    ///
624    ///     *r = 33;
625    /// });
626    /// ```
627    pub fn cell_get_mut_borrows_cell_mutably() {}
628
629    /// ```compile_fail,E0502
630    /// use ghost_cell::{GhostToken, GhostCell};
631    ///
632    /// GhostToken::new(|token| {
633    ///     let mut value = 42;
634    ///
635    ///     let cell = GhostCell::from_mut(&mut value);
636    ///
637    ///     assert_eq!(42, value);
638    ///     assert_eq!(42, *cell.borrow(&token));
639    /// });
640    /// ```
641    pub fn cell_from_mut_borrows_value_mutably() {}
642} // mod compile_tests