pin_cell/
lib.rs

1#![no_std]
2#![deny(warnings, missing_docs, missing_debug_implementations)]
3//! This library defines the `PinCell` type, a pinning variant of the standard
4//! library's `RefCell`.
5//!
6//! It is not safe to "pin project" through a `RefCell` - getting a pinned
7//! reference to something inside the `RefCell` when you have a pinned
8//! refernece to the `RefCell` - because `RefCell` is too powerful.
9//!
10//! A `PinCell` is slightly less powerful than `RefCell`: unlike a `RefCell`,
11//! one cannot get a mutable reference into a `PinCell`, only a pinned mutable
12//! reference (`Pin<&mut T>`). This makes pin projection safe, allowing you
13//! to use interior mutability with the knowledge that `T` will never actually
14//! be moved out of the `RefCell` that wraps it.
15
16mod pin_mut;
17mod pin_ref;
18
19use core::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut};
20use core::pin::Pin;
21
22pub use crate::pin_mut::PinMut;
23pub use crate::pin_ref::PinRef;
24
25/// A mutable memory location with dynamically checked borrow rules
26///
27/// Unlike `RefCell`, this type only allows *pinned* mutable access to the
28/// inner value, enabling a "pin-safe" version of interior mutability.
29///
30/// See the standard library documentation for more information.
31#[derive(Default, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
32pub struct PinCell<T: ?Sized> {
33    inner: RefCell<T>,
34}
35
36impl<T> PinCell<T> {
37    /// Creates a new `PinCell` containing `value`.
38    pub const fn new(value: T) -> PinCell<T> {
39        PinCell {
40            inner: RefCell::new(value),
41        }
42    }
43}
44
45impl<T: ?Sized> PinCell<T> {
46    /// Immutably borrows the wrapped value.
47    ///
48    /// The borrow lasts until the returned `Ref` exits scope. Multiple
49    /// immutable borrows can be taken out at the same time (both pinned and
50    /// unpinned).
51    pub fn borrow(&self) -> Ref<'_, T> {
52        self.inner.borrow()
53    }
54
55    /// Immutably borrows the wrapped value, returning an error if the value is
56    /// currently mutably borrowed.
57    ///
58    /// The borrow lasts until the returned `Ref` exits scope. Multiple
59    /// immutable borrows can be taken out at the same time (both pinned and
60    /// unpinned).
61    ///
62    /// This is the non-panicking variant of `borrow`.
63    pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
64        self.inner.try_borrow()
65    }
66
67    /// Mutably borrows the wrapped value, preserving its pinnedness.
68    ///
69    /// The borrow lasts until the returned `PinMut` or all `PinMut`s derived
70    /// from it exit scope. The value cannot be borrowed while this borrow is
71    /// active.
72    pub fn borrow_mut<'a>(self: Pin<&'a Self>) -> PinMut<'a, T> {
73        self.try_borrow_mut().expect("already borrowed")
74    }
75
76    /// Mutably borrows the wrapped value, preserving its pinnedness,
77    /// returning an error if the value is currently borrowed.
78    ///
79    /// The borrow lasts until the returned `PinMut` or all `PinMut`s derived
80    /// from it exit scope. The value cannot be borrowed while this borrow is
81    /// active.
82    ///
83    /// This is the non-panicking variant of `borrow_mut`.
84    pub fn try_borrow_mut<'a>(self: Pin<&'a Self>) -> Result<PinMut<'a, T>, BorrowMutError> {
85        let ref_mut: RefMut<'a, T> = Pin::get_ref(self).inner.try_borrow_mut()?;
86
87        // this is a pin projection from Pin<&PinCell<T>> to Pin<RefMut<T>>
88        // projecting is safe because:
89        //
90        // - for<T: ?Sized> (PinCell<T>: Unpin) imples (RefMut<T>: Unpin)
91        //   holds true
92        // - PinCell does not implement Drop
93        //
94        // see discussion on tracking issue #49150 about pin projection
95        // invariants
96        let pin_ref_mut: Pin<RefMut<'a, T>> = unsafe { Pin::new_unchecked(ref_mut) };
97
98        Ok(PinMut { inner: pin_ref_mut })
99    }
100
101    /// Immutably borrows the wrapped value, preserving its pinnedness.
102    ///
103    /// The borrow lasts until the returned `PinRef` exits scope. Multiple
104    /// immutable borrows can be taken out at the same time (both pinned and
105    /// unpinned).
106    pub fn borrow_pin<'a>(self: Pin<&'a Self>) -> PinRef<'a, T> {
107        self.try_borrow_pin().expect("already mutably borrowed")
108    }
109
110    /// Immutably borrows the wrapped value, preserving its pinnedness,
111    /// returning an error if the value is currently mutably borrowed.
112    ///
113    /// The borrow lasts until the returned `PinRef` exits scope. Multiple
114    /// immutable borrows can be taken out at the same time (both pinned and
115    /// unpinned).
116    ///
117    /// This is the non-panicking variant of `borrow_pin`.
118    pub fn try_borrow_pin<'a>(self: Pin<&'a Self>) -> Result<PinRef<'a, T>, BorrowError> {
119        let r: Ref<'a, T> = Pin::get_ref(self).inner.try_borrow()?;
120
121        // this is a pin projection from Pin<&PinCell<T>> to Pin<Ref<T>>
122        // projecting is safe because:
123        //
124        // - for<T: ?Sized> (PinCell<T>: Unpin) imples (Ref<T>: Unpin)
125        //   holds true
126        // - PinCell does not implement Drop
127        //
128        // see discussion on tracking issue #49150 about pin projection
129        // invariants
130        let pin_ref: Pin<Ref<'a, T>> = unsafe { Pin::new_unchecked(r) };
131
132        Ok(PinRef { inner: pin_ref })
133    }
134
135    /// Returns a raw pointer to the underlying data in this cell.
136    pub fn as_ptr(&self) -> *mut T {
137        self.inner.as_ptr()
138    }
139
140    /// Returns a mutable reference to the underlying data.
141    ///
142    /// This call borrows `PinCell` mutably (at compile-time) so there is no
143    /// need for dynamic checks.
144    ///
145    /// However be cautious: this method expects self to be mutable, which is
146    /// generally not the case when using a `PinCell`. Take a look at the
147    /// `borrow_mut` method instead if self isn't mutable.
148    ///
149    /// Also, please be aware that this method is only for special
150    /// circumstances and is usually not what you want. In case of doubt, use
151    /// `borrow_mut` instead.
152    pub fn get_mut(&mut self) -> &mut T {
153        self.inner.get_mut()
154    }
155}
156
157impl<T> From<T> for PinCell<T> {
158    fn from(value: T) -> PinCell<T> {
159        PinCell::new(value)
160    }
161}
162
163impl<T> From<RefCell<T>> for PinCell<T> {
164    fn from(cell: RefCell<T>) -> PinCell<T> {
165        PinCell { inner: cell }
166    }
167}
168
169impl<T> Into<RefCell<T>> for PinCell<T> {
170    fn into(self) -> RefCell<T> {
171        self.inner
172    }
173}
174
175// TODO CoerceUnsized