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