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