mutcy/
lib.rs

1//! # Mutable Cyclic Borrows #
2//!
3//! Safe mutable cyclic borrows using borrow relinquishing.
4//!
5//! This crate enables objects to mutably reference each
6//! other in cycles while adhering to Rust's borrowing rules.
7//!
8//! Rust does not permit call chains as `A -> B -> A` on objects `A`
9//! and `B` using `&mut self` because that mutably aliases `A`
10//! which is immediate undefined behavior.
11//!
12//! `Mutcy` provides an API to work around this constraint by making you
13//! relinquish all borrows to `A` when you call `B`. Thus, at the point `B`
14//! calls `A` (`B -> A`), there are no live references to `A`. When `B`
15//! returns, `A`'s borrow is reacquired.
16//!
17//! # Note #
18//!
19//! This crate currently requires *nightly* Rust.
20//!
21//! Note that arbitrary self types `fn name(self: &mut Mut<T>)` are not yet
22//! stable. These can be used on nightly using
23//! `#![feature(arbitrary_self_types)]`.
24//!
25//! While it is possible to use this crate without `arbitrary_self_types`, it
26//! makes working with this crate impractical.
27//!
28//! # Example #
29//!
30//! ```
31//! #![feature(arbitrary_self_types)]
32//! use mutcy::{Assoc, Mut, Res};
33//!
34//! // Create a new association for our data. Every `Res` is associated with some `Assoc`.
35//! let mut assoc = Assoc::new();
36//!
37//! // Create two associated objects.
38//! let a = Res::new_in(A { b: None, x: 0 }, &assoc);
39//! let b = Res::new_in(B { a: a.clone(), y: 0 }, &assoc);
40//!
41//! // Enter the association. This gives us a `Mut` which allows us to convert `Res` into `Mut`.
42//! assoc.enter(|x: &mut Mut<()>| {
43//!     // Before we can mutate `a`, we need to call `mutate().via(x)`. This relinquishes all existing
44//!     // borrows acquired via `x`'s Deref/DerefMut implementation.
45//!     a.mutate().via(x).b = Some(b);
46//!
47//!     // Call a method on `A`
48//!     a.mutate().via(x).call_a(5);
49//!
50//!     // You can store the created `Mut` from `via` onto the stack.
51//!     let mut a_mut: Mut<A> = a.mutate().via(x);
52//!
53//!     // Note, the following fails to compile because of `a_mut`'s dependency on `x`. This prevents
54//!     // Rust's requirements for references from being violated.
55//!
56//!     // let _: () = **x;
57//!
58//!     // error[E0502]: cannot borrow `*x` as immutable because it is also borrowed as mutable
59//!     //   --> src/lib.rs:38:18
60//!     //    |
61//!     // 26 |     let mut a_mut: Mut<A> = a.mutate().via(x);
62//!     //    |                                    - mutable borrow occurs here
63//!     // ...
64//!     // 31 |     let _: () = **x;
65//!     //    |                  ^^ immutable borrow occurs here
66//!     // ...
67//!     // 46 |     a_mut.my_method();
68//!     //    |     ----- mutable borrow later used here
69//!
70//!     // Because this `Mut` (`a_mut`) still exists.
71//!     a_mut.my_method();
72//! });
73//!
74//! struct A {
75//!     b: Option<Res<B>>,
76//!     x: i32,
77//! }
78//!
79//! impl A {
80//!     fn call_a(self: &mut Mut<Self>, count: usize) {
81//!         // Mutate through &mut Self.
82//!         self.x += 1;
83//!
84//!         println!(">>> A: {}", count);
85//!         self.b
86//!             .as_ref()
87//!             .unwrap()
88//!             .mutate()
89//!             .via(self)
90//!             .call_b(count - 1);
91//!         println!("<<< A: {}", count);
92//!
93//!         // Mutate again, this is valid after the call to `b` which has called back into here
94//!         // because we reborrow &mut Self here.
95//!         self.x -= 1;
96//!     }
97//!
98//!     fn remove_b(self: &mut Mut<Self>) {
99//!         // This does not drop `B` yet even though it's the only direct `Res<B>` object referring
100//!         // to the underlying data.
101//!         // The call stack will still refer to this `B` after this call finishes.
102//!         // Because `b` was invoked on as `self.b.as_ref().unwrap().mutate().via(self)`, we have
103//!         // created a clone of the `Res<B>` at multiple locations on the call stack.
104//!         // This ensures that `B` will exist as long as some part of the call stack is still
105//!         // using it.
106//!         self.b = None;
107//!     }
108//!
109//!     fn my_method(self: &mut Mut<Self>) {
110//!         self.x += 1;
111//!     }
112//! }
113//!
114//! impl Drop for A {
115//!     fn drop(&mut self) {
116//!         println!("A dropped");
117//!     }
118//! }
119//!
120//! struct B {
121//!     a: Res<A>,
122//!     y: u64,
123//! }
124//!
125//! impl B {
126//!     fn call_b(self: &mut Mut<Self>, count: usize) {
127//!         self.y += 1;
128//!
129//!         println!(">>> B: {}", count);
130//!         let mut a = self.a.mutate().via(self);
131//!         if count > 1 {
132//!             a.call_a(count - 1);
133//!         } else {
134//!             a.remove_b();
135//!         }
136//!         println!("<<< B: {}", count);
137//!
138//!         self.y -= 1;
139//!     }
140//! }
141//!
142//! impl Drop for B {
143//!     fn drop(&mut self) {
144//!         println!("B dropped");
145//!     }
146//! }
147//! ```
148//!
149//! # Drop guarantees
150//!
151//! The system maintains object validity through two invariants:
152//!
153//! 1. An object `T` will only be dropped when:
154//!    - All [`Res<T>`] handles pointing to it have been dropped
155//!    - All active [`Mut<T>`] borrow guards to it have been dropped
156//!
157//! This prevents dangling references in call chains like:
158//! ```text
159//! A → B → C → B // Last B access can remove C, into which we return. Will stay valid.
160//! ```
161//!
162//! ## Example Scenario
163//! ```
164//! # use mutcy::{Mut, Res};
165//! struct Node {
166//!     name: String,
167//!     child: Option<Res<Node>>,
168//!     parent: Option<Res<Node>>,
169//! }
170//!
171//! fn traverse(node: &mut Mut<Node>) {
172//!     if let Some(child) = &node.child {
173//!         child.mutate().via(node).parent = None; // Would invalidate parent
174//!         // Without guarantees, this could access freed memory:
175//!         println!("Parent data: {:?}", node.name);
176//!     }
177//! }
178//! ```
179//!
180//! The guarantees ensure:
181//! - Original `node` (parent) persists until its first `traverse` call
182//!   completes.
183//! - `parent = None` only marks the relationship, doesn't drop immediately.
184//! - Final `println` safely accesses still-allocated parent.
185//!
186//! Dropping `T` occurs immediately when all `Res<T>` and `Mut<T>` objects
187//! for that instance of `T` have been dropped.
188//!
189//! Deallocation of memory backing that
190//! `T` occurs immediately if `T` was dropped and no [WeakRes] instances to that
191//! `T` exist.
192#![feature(arbitrary_self_types)]
193#![feature(coerce_unsized)]
194#![feature(unsize)]
195use std::{
196    cell::UnsafeCell,
197    marker::Unsize,
198    ops::{CoerceUnsized, Deref, DerefMut},
199    rc::{Rc, Weak},
200};
201
202/// Association of pointers.
203pub struct Assoc(Rc<AssocInner>, Res<()>);
204
205impl Assoc {
206    /// Create new association.
207    pub fn new() -> Self {
208        Self::default()
209    }
210
211    /// Enters the association context to perform mutations.
212    ///
213    /// Grants you the initial [Mut] used to transform [Res] using
214    /// [via](Res::via).
215    pub fn enter<F: FnOnce(&mut Mut<()>) -> R, R>(&mut self, work: F) -> R {
216        let mut item: Mut<()> = Mut {
217            scope: &self.0,
218            data: self.1.clone(),
219        };
220        (work)(&mut item)
221    }
222}
223
224impl Default for Assoc {
225    fn default() -> Self {
226        let inner = Rc::new(AssocInner);
227        let root = Res::new(inner.clone(), ());
228        Self(inner, root)
229    }
230}
231
232mod seal {
233    use crate::AssocInner;
234    use std::rc::Rc;
235
236    pub trait Sealed {
237        #[allow(private_interfaces)]
238        fn assoc_inner(&self) -> &Rc<AssocInner>;
239    }
240}
241
242/// Sealed trait to allow [Res::new_in] and [Res::new_cyclic_in] to use [Assoc],
243/// [Mut], or [Res] as an association source.
244pub trait Associated: seal::Sealed {}
245
246#[allow(private_interfaces)]
247impl seal::Sealed for Assoc {
248    fn assoc_inner(&self) -> &Rc<AssocInner> {
249        &self.0
250    }
251}
252
253#[allow(private_interfaces)]
254impl<'a, T: 'static> seal::Sealed for Mut<'a, T> {
255    fn assoc_inner(&self) -> &Rc<AssocInner> {
256        self.scope
257    }
258}
259
260#[allow(private_interfaces)]
261impl<T> seal::Sealed for Res<T> {
262    fn assoc_inner(&self) -> &Rc<AssocInner> {
263        &self.scope
264    }
265}
266
267impl Associated for Assoc {}
268impl<T: 'static> Associated for Res<T> {}
269impl<'a, T: 'static> Associated for Mut<'a, T> {}
270
271pub(crate) struct AssocInner;
272
273/// [Assoc]iated reference-counted handle to data.
274///
275/// This item can only mutably accessed using [via](Res::via).
276///
277/// `Res` stands for resource.
278///
279/// ```
280/// use mutcy::{Assoc, Res};
281///
282/// let mut assoc = Assoc::new();
283/// let item = Res::new_in(41, &assoc);
284///
285/// let value: i32 = assoc.enter(|x| {
286///     let mut data = item.via(x);
287///     *data += 1;
288///     *data
289/// });
290///
291/// assert_eq!(value, 42);
292/// ```
293pub struct Res<T: ?Sized + 'static> {
294    scope: Rc<AssocInner>,
295    data: Rc<UnsafeCell<T>>,
296}
297
298impl<T: 'static> Res<T> {
299    fn new(scope: Rc<AssocInner>, data: T) -> Self {
300        Self {
301            scope,
302            data: Rc::new(UnsafeCell::new(data)),
303        }
304    }
305}
306
307impl<T: 'static> Res<T> {
308    /// Create a new `Res` with the same association as `A`.
309    pub fn new_in<A: Associated>(value: T, assoc: &A) -> Self {
310        Self {
311            scope: assoc.assoc_inner().clone(),
312            data: Rc::new(UnsafeCell::new(value)),
313        }
314    }
315
316    /// Create a new cyclic `Res` with the same association as `A`.
317    ///
318    /// `data_fn` is given a reference to a [WeakRes].
319    ///
320    /// See also [Rc::new_cyclic].
321    /// ```
322    /// use mutcy::{Assoc, Res, WeakRes};
323    ///
324    /// let mut assoc = Assoc::new();
325    ///
326    /// struct MyItem(i32, WeakRes<Self>);
327    /// let item = Res::new_cyclic_in(|weak| MyItem(41, weak.clone()), &assoc);
328    ///
329    /// assoc.enter(|x| {
330    ///     let mut data = item.via(x);
331    ///     data.0 += 1;
332    ///
333    ///     let data_reborrow = data.1.upgrade().unwrap().mutate().via(x);
334    ///     assert_eq!(data_reborrow.0, 42);
335    /// });
336    /// ```
337    pub fn new_cyclic_in<F, A>(data_fn: F, assoc: &A) -> Self
338    where
339        F: FnOnce(&WeakRes<T>) -> T,
340        A: Associated,
341    {
342        let assoc = assoc.assoc_inner().clone();
343        Self {
344            scope: assoc.clone(),
345            data: Rc::new_cyclic(move |weak| {
346                let weak = WeakRes::new(assoc, weak.clone());
347                UnsafeCell::new((data_fn)(&weak))
348            }),
349        }
350    }
351}
352
353impl<T: ?Sized + 'static> Res<T> {
354    fn new_raw(scope: Rc<AssocInner>, data: Rc<UnsafeCell<T>>) -> Self {
355        Self { scope, data }
356    }
357
358    /// Creates a new handle for mutation chaining
359    ///
360    /// Equivalent to [`Clone::clone`] but provides clearer semantics when
361    /// establishing new mutation chains through [`via`].
362    ///
363    /// # Why use this instead of `clone()`?
364    /// Avoids double-borrow scenarios in method chains:
365    /// ```
366    /// # #![feature(arbitrary_self_types)]
367    /// # use mutcy::{Mut, Res};
368    /// # struct MyType {
369    /// #    inner: Res<()>,
370    /// # }
371    /// impl MyType {
372    ///     fn method(self: &mut Mut<Self>) {
373    ///         // ERROR: Cannot borrow `self` mutably more than once
374    ///         // self.inner.via(self);
375    ///
376    ///         // OK
377    ///         let inner = self.inner.mutate().via(self);
378    ///     }
379    /// }
380    /// ```
381    ///
382    /// Correct usage with cloning:
383    /// ```
384    /// # #![feature(arbitrary_self_types)]
385    /// # use mutcy::{Mut,Res};
386    /// # struct MyType { inner: Res<u8> }
387    /// impl MyType {
388    ///     fn method(self: &mut Mut<Self>) {
389    ///         // Clone first to avoid overlapping borrows
390    ///         self.inner.mutate().via(self);
391    ///     }
392    /// }
393    /// ```
394    ///
395    /// [`via`]: Res::via
396    pub fn mutate(&self) -> Self {
397        self.clone()
398    }
399
400    /// Relinquish a previous `Mut` and creates a `Mut` of `self`.
401    ///
402    /// Since references to `T` a `Mut<T>` require [Deref] or [DerefMut],
403    /// calling this function will relinquish all such borrows on `Mut<T>`.
404    /// This makes it safe to acquire a mutable reference recursively.
405    ///
406    /// In effect, there exists only a single accessible `Mut<T>` for any
407    /// `Res<T>` in a single association. This function checks if the
408    /// association matches to prevent multiple `Mut<T>` being accessible
409    /// for a `Res<T>` in the same [Assoc]. [Assoc::enter] borrows the
410    /// association mutably, thus guaranteeing that only one `Mut<T>` can be
411    /// live per association.
412    ///
413    /// # Panics #
414    ///
415    /// Will panic if the arguments' associated [Assoc]s differ.
416    ///
417    /// ```
418    /// # #![feature(arbitrary_self_types)]
419    /// # use mutcy::{Mut, Res};
420    /// struct MyType {
421    ///     this: Res<Self>,
422    ///     value: i32,
423    /// }
424    ///
425    /// impl MyType {
426    ///     fn method(self: &mut Mut<Self>) {
427    ///         let value_reference: &mut i32 = &mut self.value;
428    ///
429    ///         // `via` relinquishes `value_reference`, because it has a dependency on
430    ///         // `self` that conflicts with `via`.
431    ///         self.this.mutate().via(self);
432    ///
433    ///         // ERROR: We cannot now use `value_reference`.
434    ///         // *value_reference += 1;
435    ///
436    ///         // We need to reborrow instead.
437    ///         let value_reference: &mut i32 = &mut self.value;
438    ///     }
439    /// }
440    /// ```
441    pub fn via<'a: 'b, 'b, A: 'static>(self, source: &'a mut Mut<A>) -> Mut<'b, T> {
442        assert!(
443            Rc::ptr_eq(&self.scope, source.scope),
444            "assoc is not identical"
445        );
446
447        Mut {
448            scope: source.scope,
449            data: self,
450        }
451    }
452
453    /// Create a weakly referencing to this `Res`.
454    ///
455    /// See [Rc::downgrade].
456    pub fn downgrade(this: &Res<T>) -> WeakRes<T> {
457        WeakRes::new(this.scope.clone(), Rc::downgrade(&this.data))
458    }
459
460    // SAFETY: Caller must ensure no mutable reference to `T` is live.
461    unsafe fn as_ref(&self) -> &T {
462        // SAFETY: Function is marked as unsafe. See function comment.
463        unsafe { &*self.data.get() }
464    }
465
466    // SAFETY: Caller must ensure no other reference to `T` is live.
467    #[allow(clippy::mut_from_ref)]
468    unsafe fn as_mut(&self) -> &mut T {
469        // SAFETY: Function is marked as unsafe. See function comment.
470        unsafe { &mut *self.data.get() }
471    }
472}
473
474impl<T: ?Sized + 'static> Clone for Res<T> {
475    fn clone(&self) -> Self {
476        Self {
477            scope: self.scope.clone(),
478            data: self.data.clone(),
479        }
480    }
481}
482
483impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Res<U>> for Res<T> {}
484
485/// Non-owning version of [Res] similar to [Weak].
486pub struct WeakRes<T: ?Sized + 'static> {
487    scope: Rc<AssocInner>,
488    data: Weak<UnsafeCell<T>>,
489}
490
491impl<T: ?Sized + 'static> WeakRes<T> {
492    fn new(scope: Rc<AssocInner>, data: Weak<UnsafeCell<T>>) -> Self {
493        Self { scope, data }
494    }
495
496    /// Attempts to upgrade to a strong reference
497    pub fn upgrade(&self) -> Option<Res<T>> {
498        self.data
499            .upgrade()
500            .map(|strong| Res::new_raw(self.scope.clone(), strong))
501    }
502}
503
504impl<T: ?Sized + 'static> Clone for WeakRes<T> {
505    fn clone(&self) -> Self {
506        Self {
507            scope: self.scope.clone(),
508            data: self.data.clone(),
509        }
510    }
511}
512
513impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<WeakRes<U>> for WeakRes<T> {}
514
515/// Mutable borrow guard providing access to associated data.
516///
517/// Implements [`Deref`]/[`DerefMut`] for direct access to the underlying value.
518/// While this guard exists, other borrows through the same association are
519/// suspended to prevent aliasing.
520pub struct Mut<'a, T: ?Sized + 'static> {
521    scope: &'a Rc<AssocInner>,
522    data: Res<T>,
523}
524
525impl<'a, T: ?Sized + 'static> Deref for Mut<'a, T> {
526    type Target = T;
527
528    fn deref(&self) -> &Self::Target {
529        // SAFETY: The existence and accessibility of this `Mut` guarantees that there
530        // is no other live reference to this data.
531        //
532        // Using a different `Assoc` followed by `Res::via` will result in a panic as
533        // documented in `Res::via`. This guarantees that there exists only one
534        // accessible `Mut<T>` for a set or `Res` associated with an `Assoc`.
535        unsafe { self.data.as_ref() }
536    }
537}
538
539impl<'a, T: ?Sized + 'static> DerefMut for Mut<'a, T> {
540    fn deref_mut(&mut self) -> &mut Self::Target {
541        // SAFETY: The existence and accessibility of this `Mut` guarantees that there
542        // is no other live reference to this data.
543        //
544        // Using a different `Assoc` followed by `Res::via` will result in a panic as
545        // documented in `Res::via`. This guarantees that there exists only one
546        // accessible `Mut<T>` for a set or `Res` associated with an `Assoc`.
547        unsafe { self.data.as_mut() }
548    }
549}