mutcy/lib.rs
1//! # Zero-Cost Mutable Cyclic Borrows #
2//!
3//! A `RefCell`-like dynamic borrowing system that permits recursive borrowing
4//! with zero runtime overhead.
5//!
6//! This crate implements [KeyCell] of which only a single instance can be
7//! mutably borrowed at a time using a [Key]. Simultaneous immutable borrows
8//! are permitted.
9//!
10//! [Key] is a ZST, and only a single instance can exist per thread. The only
11//! dynamic check this library performs is upon calling [Key::acquire] to ensure
12//! that there exists no other instance.
13//!
14//! # Comparison to `RefCell` #
15//!
16//! Unlike `RefCell`, borrows on [KeyCell]s will never fail. They also don't
17//! need to perform any runtime checks. All borrow checking is performed at
18//! compile time.
19//!
20//! 1. Borrowing is zero-cost.
21//! 2. Borrowing will never fail or panic.
22//! 3. Only a single [KeyCell] can be mutably borrowed per thread.
23//!
24//! # Examples #
25//!
26//! This crate uses [borrow](KeyCell::borrow) and
27//! [borrow_mut](KeyCell::borrow_mut) to access data.
28//!
29//! ```
30//! use mutcy::{Key, KeyCell, KeyMut};
31//!
32//! let mut key = Key::acquire();
33//!
34//! let kc1 = KeyCell::new(0i32, ());
35//! let kc2 = KeyCell::new(String::new(), ());
36//!
37//! *kc2.borrow_mut(&mut key) += "Hello";
38//! *kc1.borrow_mut(&mut key) += 1;
39//! *kc2.borrow_mut(&mut key) += "World";
40//!
41//! let item1 = kc1.borrow(&key);
42//! let item2 = kc1.borrow(&key);
43//!
44//! println!("{} - {}", *item1, *item2);
45//! ```
46//!
47//! With this library it's possible to define methods that take [KeyMut] and
48//! transfer mutability to other [KeyCell]s when needed. The compile-time borrow
49//! checker ensures that no mutable aliasing occurs.
50//!
51//! In the following example we show how a struct can accept a `self:
52//! KeyMut<Self>` and relinquish its own borrows to access some other
53//! `KeyCell`.
54//!
55//! ```
56//! #![feature(arbitrary_self_types)]
57//! use mutcy::{Key, KeyCell, KeyMut, Meta};
58//! use std::rc::Rc;
59//!
60//! struct MyStruct {
61//! value: i32,
62//! }
63//!
64//! impl MyStruct {
65//! fn my_function(self: KeyMut<Self>) {
66//! self.value += 1;
67//!
68//! // This relinquishes any borrows to `self`.
69//! let (this, key) = Key::split(self);
70//!
71//! // We can now access any other KeyCell using `key`.
72//! let mut string = this.meta().other.borrow_mut(key);
73//! *string += "Hello world";
74//!
75//! self.value += 1;
76//! }
77//! }
78//!
79//! struct MyStructMeta {
80//! other: Rc<KeyCell<String>>,
81//! }
82//!
83//! impl Meta for MyStruct {
84//! type Data = MyStructMeta;
85//! }
86//!
87//! let mut key = Key::acquire();
88//!
89//! let other = Rc::new(KeyCell::new(String::new(), ()));
90//!
91//! let my_struct = KeyCell::new(
92//! MyStruct { value: 0 },
93//! MyStructMeta {
94//! other: other.clone(),
95//! },
96//! );
97//!
98//! my_struct.borrow_mut(&mut key).my_function();
99//!
100//! println!("{}", *other.borrow(&key));
101//! println!("{}", my_struct.borrow(&key).value);
102//! ```
103//!
104//! For more information on metadata see [Meta].
105pub use self::meta::Meta;
106use std::{
107 cell::{Cell, UnsafeCell},
108 marker::PhantomData,
109 ops::{Deref, DerefMut},
110};
111
112mod meta;
113
114thread_local! {
115 static KEY: Cell<bool> = const { Cell::new(true) }
116}
117
118/// Reference to [KeyCellRef].
119pub type KeyRef<'a, T> = &'a KeyCellRef<'a, T>;
120
121/// Mutable reference to [KeyCellMut].
122pub type KeyMut<'a, T> = &'a mut KeyCellMut<'a, T>;
123
124/// A per-thread unique key used to access data inside [KeyCell]s.
125///
126/// This type enforces the existence of only a single instance of itself per
127/// thread. By doing so it guards against mutable aliasing when borrowing from
128/// `KeyCell`.
129pub struct Key(PhantomData<*mut ()>);
130
131impl Key {
132 /// Acquire the thread-local Key.
133 ///
134 /// # Panics #
135 ///
136 /// Panics if an instance already exists for the current thread. Calling
137 /// acquire after dropping the key will not panic.
138 ///
139 /// # Examples #
140 ///
141 /// ```
142 /// use mutcy::Key;
143 ///
144 /// let key = Key::acquire();
145 /// ```
146 pub fn acquire() -> Self {
147 KEY.with(|key| {
148 assert!(key.get());
149 key.set(false);
150 });
151
152 Key(PhantomData)
153 }
154
155 /// Split a [KeyMut] into its consitutuent [KeyCell] and [Key].
156 ///
157 /// Whenever we want to borrow another item while already holding a `KeyMut`
158 /// we need to unborrow. This function unborrows, granting you access to
159 /// the key that was used to borrow the initial `KeyCell`.
160 ///
161 /// # Examples #
162 ///
163 /// ```
164 /// use mutcy::{Key, KeyCell, KeyMut};
165 ///
166 /// fn function(kc1: KeyMut<i32>, kc2: &KeyCell<i32>) {
167 /// **kc1 += 1; // kc1 = 1
168 ///
169 /// let (kc1_ref, key) = Key::split(kc1);
170 ///
171 /// let mut kc2_mut = kc2.borrow_mut(key);
172 /// *kc2_mut += 1;
173 ///
174 /// // Relinquish the split.
175 /// **kc1 += 1;
176 ///
177 /// // Compile error.
178 /// // *kc2_mut += 1;
179 /// }
180 ///
181 /// let kc1 = KeyCell::new(0, ());
182 /// let kc2 = KeyCell::new(10, ());
183 ///
184 /// let mut key = Key::acquire();
185 ///
186 /// let mut kc1_borrow = kc1.borrow_mut(&mut key);
187 ///
188 /// function(&mut kc1_borrow, &kc2);
189 /// ```
190 pub fn split<'a: 'b, 'b, T: Meta>(
191 item: &'b mut KeyCellMut<'a, T>,
192 ) -> (&'b KeyCell<T>, &'b mut Key) {
193 KeyCellMut::split(item)
194 }
195}
196
197impl Drop for Key {
198 /// Drops the key. Once the key is dropped, the next [acquire](Key::acquire)
199 /// will not panic.
200 fn drop(&mut self) {
201 KEY.with(|key| {
202 key.set(true);
203 });
204 }
205}
206
207/// A `RefCell`-like wrapper that can only be accessed via
208/// [Key].
209pub struct KeyCell<T: Meta>(UnsafeCell<T>, T::Data);
210
211impl<T: Meta> KeyCell<T> {
212 /// Creates a new `KeyCell` from an object and its associated
213 /// [metadata](Meta).
214 ///
215 /// # Examples #
216 ///
217 /// ```
218 /// use mutcy::KeyCell;
219 ///
220 /// let kc = KeyCell::new(123, ());
221 /// ```
222 pub fn new(item: T, attached: T::Data) -> Self {
223 Self(UnsafeCell::new(item), attached)
224 }
225
226 /// Immutably borrows the wrapped value.
227 ///
228 /// # Examples #
229 ///
230 /// ```
231 /// use mutcy::{Key, KeyCell};
232 ///
233 /// let key = Key::acquire();
234 /// let kc = KeyCell::new(123, ());
235 ///
236 /// let borrowed1 = kc.borrow(&key);
237 /// let borrowed2 = kc.borrow(&key);
238 /// ```
239 pub fn borrow<'a>(&'a self, _key: &'a Key) -> KeyCellRef<'a, T> {
240 KeyCellRef(self)
241 }
242
243 /// Mutably borrows the wrapped value.
244 ///
245 /// Requires a `&mut Key` that ensures that no other borrows exist
246 /// simultaneously.
247 ///
248 /// # Examples #
249 ///
250 /// ```
251 /// use mutcy::{Key, KeyCell};
252 ///
253 /// let mut key = Key::acquire();
254 /// let kc = KeyCell::new(123, ());
255 ///
256 /// let borrowed1 = kc.borrow_mut(&mut key);
257 ///
258 /// let borrowed2 = kc.borrow(&key);
259 ///
260 /// // This does not compile.
261 /// // let _ = *borrowed1;
262 /// ```
263 pub fn borrow_mut<'a>(&'a self, key: &'a mut Key) -> KeyCellMut<'a, T> {
264 KeyCellMut(self, key)
265 }
266
267 /// Acquire metadata. See [Meta].
268 ///
269 /// # Examples #
270 ///
271 /// ```
272 /// use mutcy::{KeyCell, Meta};
273 /// struct A;
274 ///
275 /// impl Meta for A {
276 /// type Data = i32;
277 /// }
278 ///
279 /// let kc = KeyCell::new(A, 123);
280 ///
281 /// assert_eq!(*kc.meta(), 123);
282 /// ```
283 pub fn meta(&self) -> &T::Data {
284 &self.1
285 }
286}
287
288/// Wraps an immutably borrowed reference to a value in a `KeyCell`.
289///
290/// See [KeyCell::borrow].
291pub struct KeyCellRef<'a, T: Meta>(&'a KeyCell<T>);
292
293impl<'a, T: Meta> Deref for KeyCellRef<'a, T> {
294 type Target = T;
295 fn deref(&self) -> &Self::Target {
296 unsafe { &*self.0.0.get() }
297 }
298}
299
300/// Wraps a mutably borrowed reference to a value in a `KeyCell`.
301///
302/// See [KeyCell::borrow_mut].
303pub struct KeyCellMut<'a, T: Meta>(&'a KeyCell<T>, &'a mut Key);
304
305impl<'a, T: Meta> KeyCellMut<'a, T> {
306 fn split(this: &mut Self) -> (&KeyCell<T>, &mut Key) {
307 (this.0, this.1)
308 }
309}
310
311impl<'a, T: Meta> Deref for KeyCellMut<'a, T> {
312 type Target = T;
313 fn deref(&self) -> &Self::Target {
314 unsafe { &*self.0.0.get() }
315 }
316}
317
318impl<'a, T: Meta> DerefMut for KeyCellMut<'a, T> {
319 fn deref_mut(&mut self) -> &mut Self::Target {
320 unsafe { &mut *self.0.0.get() }
321 }
322}