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}