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}