refbox/
lib.rs

1//! A `Box` with weak references.
2//!
3//! A [`RefBox`] is a smart pointer that owns the data, just like a standard
4//! [`Box`]. Similarly, a RefBox cannot be cloned cheaply, and when it is
5//! dropped, the data it points to is dropped as well. However, a RefBox may
6//! have many [`Weak`] pointers to the same data. These pointers don't own the
7//! data and are reference counted, comparable to the standard library's
8//! [`std::rc::Weak`]. As long as the RefBox is alive, Weak pointers can be used to
9//! access the data from multiple places without lifetime parameters.
10//!
11//! A RefBox could be seen as a lighter alternative to the standard library's
12//! [`Rc`], [`std::rc::Weak`] and [`RefCell`] combination, in cases where there is one
13//! Rc with many Weak pointers to the same data.
14//!
15//! Note: this crate is currently **experimental**.
16//!
17//! [`Rc`]: std::rc::Rc
18//! [`RefCell`]: std::cell::RefCell
19//!
20//! ## Tradeoffs
21//!
22//! A RefBox does not differentiate between strong and weak pointers and
23//! immutable and mutable borrows. There is always a *single* strong pointer,
24//! zero, one or many weak pointers, and all borrows are mutable. This means
25//! there can only be one borrow active at any given time. In return,
26//! RefBox uses less memory, is faster to borrow from, and a Weak does not need
27//! to be upgraded to access the data.
28//!
29//! # Rc + Refcell vs. RefBox
30//!
31//! |                  | `Rc<RefCell<T>>`                                               | `RefBox<T>`                                     |
32//! |------------------|----------------------------------------------------------------|-------------------------------------------------|
33//! | Pointer kinds    | Many `Rc` pointers and many `Weak` pointers                    | One `RefBox` pointer and many `Weak` pointers   |
34//! | Clonable         | Both `Rc` and `Weak` are cheap to clone                        | Only `Weak` is cheap to clone                   |
35//! | Up-/Downgrading  | `Rc` is downgradable, `Weak` is upgradable                     | `RefBox` is downgradable                        |
36//! | Data access through strong pointer | `RefCell::try_borrow_mut`                    | `RefBox::try_borrow_mut`                        |
37//! | Data access through weak pointer | 1. `Weak::upgrade`<br>2. `RefCell::try_borrow_mut`<br>3. Drop temporary `Rc` | `Weak::try_borrow_mut` |
38//! | Simultaneous borrows | One mutable OR multiple immutable                          | One (mutable or immutable)                      |
39//! | `T::drop` happens when | When all `Rc`s are dropped                               | When the single `RefBox` is dropped             |
40//! | Max number of `Weak` pointers | `usize::MAX`                                      | `u32::MAX`                                      |
41//! | Heap overhead | 64-bit: 24 bytes<br>32-bit: 12 bytes | 8 bytes<br>With cyclic_stable enabled on 64-bit: 24 bytes<br>With cyclic_stable enabled on 32-bit: 12 bytes |
42//! | Performance      | Cloning is fast, mutating is slow                        | Cloning is a tiny bit slower, mutating is much faster |
43//!
44//! # Examples
45//!
46//! ```
47//! use refbox::RefBox;
48//!
49//! fn main() {
50//!     // Create a RefBox.
51//!     let ref_box = RefBox::new(100);
52//!
53//!     // Create a weak reference.
54//!     let weak = RefBox::downgrade(&ref_box);
55//!
56//!     // Access the data.
57//!     let borrow = weak.try_borrow_mut().unwrap();
58//!     assert_eq!(*borrow, 100);
59//! }
60//! ```
61//!
62//! # Optional Features
63//!
64//! * **cyclic_stable**: Enables the `RefBox::new_cyclic()` method on the stable release channel
65//!   of Rust. This allows you to create data structures that contain weak references to (parts of)
66//!   themselves in one go. To make it work, the memory layout of the type `T` is saved in the heap
67//!   part of the `RefBox`. This increases the memory size of the heap part with `2 * usize`.
68//! * **cyclic**: Enables the `RefBox::new_cyclic()` method on the nightly release channel without
69//!   increasing the memory size of the heap part. This allows you to create data structures that
70//!   contain weak references to (parts of) themselves in one go. Requires the nightly feature
71//!   [layout_for_ptr].
72//!
73//! [layout_for_ptr]: https://github.com/rust-lang/rust/issues/69835
74
75// The optional "cyclic" feature, which activates the `RefBox::<T>::new_cyclic()`
76// method, requires the Nightly feature "layout_for_ptr", as we need to be able
77// to get the layout of `T` through a raw pointer to deallocate it.
78#![cfg_attr(feature = "cyclic", feature(layout_for_ptr))]
79
80mod internals;
81
82use core::fmt;
83use core::marker::PhantomData;
84use core::ops::{Deref, DerefMut};
85use core::ptr::NonNull;
86use std::error;
87
88use internals::{RefBoxHeap, RefBoxHeapInner, Status, WeakCount};
89
90///////////////////////////////////////////////////////////////////////////////
91// Helpers
92///////////////////////////////////////////////////////////////////////////////
93
94/// Coerces a `RefBox<T>` into a `RefBox<dyn Trait>` on stable Rust.
95///
96/// Normally, performing custom coercions requires the [`CoerceUnsized`] trait
97/// which is only available on Nightly Rust. This macro bypasses this trait by
98/// performing the actual coercion in the raw pointer domain, which is
99/// perfectly possible on Stable Rust.
100///
101/// # Examples
102///
103/// ```
104/// use std::any::Any;
105/// use refbox::{coerce, RefBox};
106///
107/// struct SomeStruct;
108/// trait SomeTrait {}
109/// impl SomeTrait for SomeStruct {}
110///
111/// let ref_box = RefBox::new(SomeStruct);
112///
113/// let dyn_ref_box = coerce!(ref_box => dyn SomeTrait);
114///
115/// ```
116///
117/// [`CoerceUnsized`]: std::ops::CoerceUnsized
118#[macro_export]
119macro_rules! coerce {
120    ($ref_box:expr => $into_type:ty) => {{
121        let __raw = $crate::RefBox::into_raw($ref_box);
122        let __out: $crate::RefBox<$into_type> = unsafe { $crate::RefBox::from_raw(__raw) };
123        __out
124    }};
125}
126
127/// Coerces a `Weak<T>` into a `Weak<dyn Trait>` on stable Rust.
128///
129/// Normally, performing custom coercions requires the [`CoerceUnsized`] trait
130/// which is only available on Nightly Rust. This macro bypasses this trait by
131/// performing the actual coercion in the raw pointer domain, which is
132/// perfectly possible on Stable Rust.
133///
134/// # Examples
135///
136/// ```
137/// use std::any::Any;
138/// use refbox::{coerce_weak, RefBox, Weak};
139///
140/// struct SomeStruct;
141/// trait SomeTrait {}
142/// impl SomeTrait for SomeStruct {}
143///
144/// let ref_box = RefBox::new(SomeStruct);
145/// let weak_box = RefBox::downgrade(&ref_box);
146///
147/// let dyn_weak = coerce_weak!(weak_box => dyn SomeTrait);
148///
149/// ```
150///
151/// [`CoerceUnsized`]: std::ops::CoerceUnsized
152#[macro_export]
153macro_rules! coerce_weak {
154    ($weak:expr => $into_type:ty) => {{
155        let __raw = $crate::Weak::into_raw($weak);
156        let __out: $crate::Weak<$into_type> = unsafe { $crate::Weak::from_raw(__raw) };
157        __out
158    }};
159}
160
161///////////////////////////////////////////////////////////////////////////////
162// RefBox
163///////////////////////////////////////////////////////////////////////////////
164
165/// A smart pointer with many reference-counted weak references.
166///
167/// See the [module](crate) documentation for more information.
168///
169/// # Accessing the data behind the RefBox
170///
171/// See [`RefBox::try_borrow_mut`], [`RefBox::try_borrow_mut_or_else`] and
172/// [`RefBox::try_access_mut`].
173///
174/// Note: because all borrows are guarded by a single flag, only one borrow is possible at a time
175/// and all borrows are mutable.
176pub struct RefBox<T: ?Sized> {
177    ptr: NonNull<RefBoxHeap<T>>,
178    /// A RefBox owns the data and may call `T::drop`.
179    _p: PhantomData<RefBoxHeap<T>>,
180}
181
182impl<T: ?Sized> Drop for RefBox<T> {
183    fn drop(&mut self) {
184        unsafe { internals::drop_ref_box(self.ptr) };
185    }
186}
187
188impl<T: ?Sized + fmt::Debug> fmt::Debug for RefBox<T> {
189    /// Tries to access the data and write a debug representation of it.
190    /// If accessing fails, it only writes the pointer value.
191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192        match self.try_borrow_mut() {
193            Ok(this) => f
194                .debug_tuple("RefBox")
195                .field(&self.ptr)
196                .field(&&*this)
197                .finish(),
198            Err(_) => f.debug_tuple("RefBox").field(&self.ptr).finish(),
199        }
200    }
201}
202
203impl<T: ?Sized> PartialEq<Weak<T>> for RefBox<T> {
204    fn eq(&self, other: &Weak<T>) -> bool {
205        other.is(self)
206    }
207}
208
209impl<T: Default> Default for RefBox<T> {
210    #[inline]
211    fn default() -> Self {
212        Self::new(T::default())
213    }
214}
215
216impl<T> From<T> for RefBox<T> {
217    #[inline]
218    fn from(val: T) -> Self {
219        Self::new(val)
220    }
221}
222
223impl<T> RefBox<T> {
224    /// Creates a new `RefBox` reference counted pointer.
225    pub fn new(value: T) -> Self {
226        internals::new_ref_box(value)
227    }
228
229    /// Creates a new `RefBox` pointer through a closure which receives a
230    /// [`Weak`] pointer to the same data. Use this to create data structures
231    /// that contain weak references to themselves.
232    ///
233    /// Note: if you try to borrow the data in the closure, you will get a
234    /// [`BorrowError::Dropped`] error.
235    ///
236    /// Note: only available if either the `cyclic` or `cyclic_stable` feature is enabled.
237    ///
238    /// # Examples
239    ///
240    /// ```
241    /// use refbox::{Weak, RefBox};
242    ///
243    /// struct Node {
244    ///     parent: Option<Weak<Node>>,
245    ///     child: Option<RefBox<Node>>,
246    /// }
247    ///
248    /// let node = RefBox::new_cyclic(|me| {
249    ///     let child = RefBox::new(Node {
250    ///         parent: Some(me.clone()),
251    ///         child: None,
252    ///     });
253    ///
254    ///     Node {
255    ///         parent: None,
256    ///         child: Some(child),
257    ///     }
258    /// });
259    /// ```
260    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
261    pub fn new_cyclic<F: FnOnce(&Weak<T>) -> T>(op: F) -> Self {
262        internals::new_cyclic_ref_box(op)
263    }
264}
265
266impl<T: ?Sized> RefBox<T> {
267    /// Returns a read-only reference to the heap part of the `RefBox`.
268    #[inline(always)]
269    fn heap(&self) -> &RefBoxHeapInner {
270        // SAFETY (1): RefBox guarantees the heap memory stays alive at least
271        // as long as the RefBox is alive.
272        // SAFETY (2): We only ever access this through a shared reference so
273        // we don't have to account for possible mutable references.
274        // SAFETY (3): Because this is a `RefBox` we know the data field
275        // is initialized.
276        let ptr = self.ptr.as_ptr();
277        unsafe { &(*ptr).inner }
278    }
279
280    /// Tries to borrow the data mutably.
281    ///
282    /// # Returns
283    ///
284    /// * `Ok(Borrow)` if the borrow was successful
285    /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
286    #[inline]
287    pub fn try_borrow_mut(&self) -> Result<Borrow<T>, BorrowError> {
288        self.try_borrow_mut_or_else(|| BorrowError::Borrowed)
289    }
290
291    /// Tries to borrow the data mutably and returns a custom error if
292    /// borrowing fails.
293    pub fn try_borrow_mut_or_else<E>(
294        &self,
295        err_borrowed: impl FnOnce() -> E,
296    ) -> Result<Borrow<T>, E> {
297        match self.heap().status() {
298            Status::Available => Ok(unsafe { Borrow::new(self.ptr.as_ref()) }),
299            Status::Borrowed => Err(err_borrowed()),
300            Status::Dropped | Status::DroppedWhileBorrowed => unreachable!(),
301        }
302    }
303
304    /// Provides access to the data through a closure.
305    ///
306    /// If the data is already borrowed, the closure is not executed and an
307    /// error is returned. Otherwise, the closure is executed and the output of
308    /// the closure is returned.
309    ///
310    /// # Returns
311    ///
312    /// * `Ok(R)` if the access was successful
313    /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
314    pub fn try_access_mut<R, F: FnOnce(&mut T) -> R>(&self, op: F) -> Result<R, BorrowError> {
315        let mut borrow = self.try_borrow_mut()?;
316        Ok(op(&mut *borrow))
317    }
318
319    /// Creates a [`Weak`] reference to the data.
320    ///
321    /// # Panics
322    ///
323    /// Panics if the number of Refs overflows `u32::MAX`.
324    ///
325    /// See [`Self::try_downgrade`] for a version that does not panic.
326    pub fn downgrade(&self) -> Weak<T> {
327        self.heap().increase_weak_count();
328        Weak { ptr: self.ptr }
329    }
330
331    /// Tries to create a [`Weak`] pointer to the data.
332    ///
333    /// # Returns
334    ///
335    /// * `Some(Weak)` if it was successful.
336    /// * `None` if the number of weak pointers overflowed `u32::MAX`.
337    pub fn try_downgrade(&self) -> Option<Weak<T>> {
338        if self.heap().try_increase_weak_count() {
339            Some(Weak { ptr: self.ptr })
340        } else {
341            None
342        }
343    }
344
345    /// Returns the number of [`Weak`]s pointing to this RefBox.
346    pub fn weak_count(&self) -> WeakCount {
347        self.heap().weak_count()
348    }
349
350    /// Returns an immutable reference to the data without checking if
351    /// the data is already mutably borrowed.
352    ///
353    /// # Safety
354    ///
355    /// Ensure there are no mutable references to `T`.
356    pub unsafe fn get_unchecked(&self) -> &T {
357        // SAFETY: the caller must uphold the safety requirements
358        unsafe { self.ptr.as_ref().data_ref() }
359    }
360
361    /// Returns a mutable reference to the data without checking if
362    /// the data is already mutably borrowed.
363    ///
364    /// # Safety
365    ///
366    /// Ensure there are no other references to `T`.
367    pub unsafe fn get_mut_unchecked(&mut self) -> &mut T {
368        // SAFETY: the caller must uphold the safety requirements
369        unsafe { self.ptr.as_ref().data_mut() }
370    }
371
372    /// Returns a raw pointer to `T`.
373    pub fn as_ptr(&self) -> *const T {
374        let ptr = self.ptr.as_ptr();
375
376        // SAFETY (1): ptr is safe to dereference, see Self::heap().
377        // SAFETY (2): UnsafeCell is `#[repr(transparent)]`, which means
378        // a pointer to the cell is also a pointer to its only field.
379        // SAFETY (3): RefBox could be borrowed, so use &raw to ensure no reference is created
380        // while there is a mutable reference.
381        unsafe { &raw const (*ptr).data as *const T }
382    }
383
384    /// Turns the `RefBox` into a raw pointer.
385    pub fn into_raw(self) -> *mut RefBoxHeap<T> {
386        let ptr = self.ptr.as_ptr();
387        std::mem::forget(self);
388        ptr
389    }
390
391    /// Creates a `RefBox` from a raw pointer.
392    ///
393    /// # Safety
394    ///
395    /// Ensure `ptr` is a valid pointer to a `RefBoxHeap<T>` instance.
396    pub unsafe fn from_raw(ptr: *mut RefBoxHeap<T>) -> Self {
397        // SAFETY: the caller must uphold the safety requirements
398        Self {
399            ptr: unsafe { NonNull::new_unchecked(ptr) },
400            _p: PhantomData,
401        }
402    }
403
404    /// Casts a `RefBox<T>` to a `RefBox<U>`.
405    ///
406    /// # Safety
407    ///
408    /// Ensure `T` can be safely cast to `U`.
409    pub unsafe fn cast<U>(self) -> RefBox<U> {
410        let raw_ptr = self.into_raw();
411
412        // SAFETY: the caller must uphold the safety requirements
413        unsafe { RefBox::from_raw(raw_ptr as _) }
414    }
415
416    /// Returns the current status of the heap part for testing purposes.
417    #[cfg(test)]
418    fn status(&self) -> Status {
419        self.heap().status()
420    }
421}
422
423///////////////////////////////////////////////////////////////////////////////
424// Weak
425///////////////////////////////////////////////////////////////////////////////
426
427/// A weak reference-counted reference to a [`RefBox`].
428///
429/// See the [module](crate) documentation for more information.
430///
431/// # Accessing the data behind the Weak
432///
433/// See [`Weak::try_borrow_mut`], [`Weak::try_borrow_mut_or_else`] and
434/// [`Weak::try_access_mut`].
435///
436/// Note: because all borrows are guarded by a single flag, only one borrow is possible at a time
437/// and all borrows are mutable.
438pub struct Weak<T: ?Sized> {
439    ptr: NonNull<RefBoxHeap<T>>,
440}
441
442impl<T: ?Sized> Drop for Weak<T> {
443    fn drop(&mut self) {
444        // SAFETY: the `Weak` cannot be used anymore after this point.
445        unsafe { internals::drop_weak(self.ptr) };
446    }
447}
448
449impl<T: ?Sized> Clone for Weak<T> {
450    /// Copies the reference and increases the reference counter.
451    ///
452    /// # Panics
453    ///
454    /// Panics if the number of Refs overflows `u32::MAX`.
455    fn clone(&self) -> Self {
456        self.heap().increase_weak_count();
457        Weak { ptr: self.ptr }
458    }
459}
460
461impl<T: ?Sized> fmt::Debug for Weak<T> {
462    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
463        f.debug_tuple("Weak").field(&self.ptr).finish()
464    }
465}
466
467impl<T: ?Sized> PartialEq for Weak<T> {
468    /// Returns true if both `Weak` pointers point to the same instance.
469    ///
470    /// This compares the pointer addresses, not the actual objects themselves,
471    /// which makes it very fast.
472    fn eq(&self, other: &Self) -> bool {
473        std::ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
474    }
475}
476
477impl<T: ?Sized> PartialEq<RefBox<T>> for Weak<T> {
478    fn eq(&self, other: &RefBox<T>) -> bool {
479        self.is(other)
480    }
481}
482
483impl<T: ?Sized> Eq for Weak<T> {}
484
485impl<T: ?Sized> Weak<T> {
486    /// Returns a read-only reference to the heap part of the `Weak`.
487    #[inline(always)]
488    fn heap(&self) -> &RefBoxHeapInner {
489        // SAFETY (1): Weak guarantees the heap memory stays alive at
490        // least as long as the Weak is alive.
491        // SAFETY (2): We only ever access this through a shared reference so
492        // we don't have to account for possible mutable references.
493        // SAFETY (3): We make sure not to create a reference covering the
494        // `data` field of `RefBoxHeap` as it may contain uninitialized data.
495        let ptr = self.ptr.as_ptr();
496        unsafe { &(*ptr).inner }
497    }
498
499    /// Tries to borrow the data mutably.
500    ///
501    /// # Returns
502    ///
503    /// * `Ok(Borrow)` if the borrow was successful
504    /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
505    /// * `Err(BorrowError::Dropped)` if the owning [`RefBox`] was dropped
506    #[inline]
507    pub fn try_borrow_mut(&self) -> Result<Borrow<T>, BorrowError> {
508        self.try_borrow_mut_or_else(|| BorrowError::Borrowed, || BorrowError::Dropped)
509    }
510
511    /// Tries to borrow the data mutably and returns a custom error if
512    /// borrowing fails.
513    pub fn try_borrow_mut_or_else<E>(
514        &self,
515        err_borrowed: impl FnOnce() -> E,
516        err_dropped: impl FnOnce() -> E,
517    ) -> Result<Borrow<T>, E> {
518        match self.heap().status() {
519            Status::Available => Ok(unsafe { Borrow::new(self.ptr.as_ref()) }),
520            Status::Borrowed => Err(err_borrowed()),
521            Status::Dropped | Status::DroppedWhileBorrowed => Err(err_dropped()),
522        }
523    }
524
525    /// Provides access to the data through a closure.
526    ///
527    /// If the data is already borrowed or the owning [`RefBox`] is dropped,
528    /// the closure is not executed and an error is returned. Otherwise, the
529    /// closure is executed and the output of the closure is returned.
530    ///
531    /// # Returns
532    ///
533    /// * `Ok(R)` if the access was successful
534    /// * `Err(BorrowError::Borrowed)` if the data was already borrowed
535    /// * `Err(BorrowError::Dropped)` if the owning [`RefBox`] was dropped
536    pub fn try_access_mut<R, F: FnOnce(&mut T) -> R>(&self, op: F) -> Result<R, BorrowError> {
537        let mut borrow = self.try_borrow_mut()?;
538        Ok(op(&mut *borrow))
539    }
540
541    /// Tries to clone the weak reference to the data.
542    ///
543    /// # Returns
544    ///
545    /// * `Some(Weak)` if it was successful.
546    /// * `None` if the number of weak pointers overflowed `u32::MAX`.
547    pub fn try_clone(&self) -> Option<Weak<T>> {
548        if self.heap().try_increase_weak_count() {
549            Some(Weak { ptr: self.ptr })
550        } else {
551            None
552        }
553    }
554
555    /// Returns the total number of [`Weak`] pointers that point to the same instance as this one.
556    pub fn weak_count(&self) -> WeakCount {
557        self.heap().weak_count()
558    }
559
560    /// Returns true if the owner of the data is alive.
561    pub fn is_alive(&self) -> bool {
562        self.heap().is_alive()
563    }
564
565    /// Returns true if the data is currently mutably borrowed.
566    pub fn is_borrowed(&self) -> bool {
567        self.heap().is_borrowed()
568    }
569
570    /// Returns true if this `Weak` and the supplied [`RefBox`] point to the same instance.
571    pub fn is(&self, owner: &RefBox<T>) -> bool {
572        std::ptr::addr_eq(self.ptr.as_ptr(), owner.ptr.as_ptr())
573    }
574
575    /// Returns an immutable reference to the data without checking if
576    /// the data is already mutably borrowed or dropped.
577    ///
578    /// # Safety
579    ///
580    /// 1. Ensure there are no mutable references to `T`.
581    /// 2. Ensure `T` is fully initialized (don't use this in
582    ///    `RefBox::new_cyclic`).
583    /// 3. Ensure the owning `RefBox` is alive for the entire lifetime
584    ///    of the returned reference.
585    pub unsafe fn get_unchecked(&self) -> &T {
586        // SAFETY: the caller must uphold the safety requirements
587        unsafe { self.ptr.as_ref().data_ref() }
588    }
589
590    /// Returns a mutable reference to the data without checking if
591    /// the data is already mutably borrowed or dropped.
592    ///
593    /// # Safety
594    ///
595    /// 1. Ensure there are no other references to `T`.
596    /// 2. Ensure `T` is fully initialized (don't use this in
597    ///    `RefBox::new_cyclic`).
598    /// 3. Ensure the owning `RefBox` is alive for the entire lifetime
599    ///    of the returned reference.
600    pub unsafe fn get_mut_unchecked(&mut self) -> &mut T {
601        // SAFETY: the caller must uphold the safety requirements
602        unsafe { self.ptr.as_ref().data_mut() }
603    }
604
605    /// Returns a raw pointer to `T`.
606    pub fn as_ptr(&self) -> *const T {
607        let ptr = self.ptr.as_ptr();
608
609        // SAFETY (1): ptr is safe to dereference, see Self::heap().
610        // SAFETY (2): UnsafeCell is `#[repr(transparent)]`, which means
611        // a pointer to the cell is also a pointer to its only field.
612        // SAFETY (3): data could be uninitialized, so use &raw to ensure no reference is created
613        unsafe { &raw const (*ptr).data as *const T }
614    }
615
616    /// Turns the `Weak` into a raw pointer.
617    pub fn into_raw(self) -> *mut RefBoxHeap<T> {
618        let ptr = self.ptr.as_ptr();
619        std::mem::forget(self);
620        ptr
621    }
622
623    /// Creates a `Weak` from a raw pointer.
624    ///
625    /// # Safety
626    ///
627    /// Ensure `ptr` is a valid pointer to a `RefBoxHeap<T>`.
628    pub unsafe fn from_raw(ptr: *mut RefBoxHeap<T>) -> Self {
629        // SAFETY: the caller must uphold the safety requirements
630        let ptr = unsafe { NonNull::new_unchecked(ptr) };
631        Self { ptr }
632    }
633
634    /// Casts a `Weak<T>` to a `Weak<U>`.
635    ///
636    /// # Safety
637    ///
638    /// Ensure `T` can be safely cast to `U`.
639    pub unsafe fn cast<U>(self) -> Weak<U> {
640        let raw_ptr = self.into_raw();
641
642        // SAFETY: the caller must uphold the safety requirements
643        unsafe { Weak::from_raw(raw_ptr as _) }
644    }
645
646    /// Returns the current status of the heap part for testing purposes.
647    #[cfg(test)]
648    fn status(&self) -> Status {
649        self.heap().status()
650    }
651}
652
653///////////////////////////////////////////////////////////////////////////////
654// Borrow
655///////////////////////////////////////////////////////////////////////////////
656
657/// A mutable borrow as a RAII-guard of a [`RefBox`] or [`Weak`].
658///
659/// See the [module](crate) documentation for more information.
660pub struct Borrow<'ptr, T: ?Sized> {
661    pub(crate) heap: &'ptr RefBoxHeap<T>,
662    /// A borrow is a mutable reference to the data.
663    pub(crate) _p: PhantomData<&'ptr mut T>,
664}
665
666impl<'ptr, T: ?Sized> Borrow<'ptr, T> {
667    /// Creates a new borrow.
668    #[inline]
669    unsafe fn new(heap: &'ptr RefBoxHeap<T>) -> Self {
670        heap.inner.start_borrow();
671        Self {
672            heap,
673            _p: PhantomData,
674        }
675    }
676}
677
678impl<'ptr, T: ?Sized> Drop for Borrow<'ptr, T> {
679    fn drop(&mut self) {
680        // SAFETY: The borrow cannot be used anymore after this point.
681        unsafe { internals::drop_borrow(self.heap) };
682    }
683}
684
685impl<'ptr, T: ?Sized> Deref for Borrow<'ptr, T> {
686    type Target = T;
687
688    fn deref(&self) -> &Self::Target {
689        // SAFETY: There can only ever be one `Borrow` to the same
690        // data, so we're sure there are no mutable references.
691        unsafe { self.heap.data_ref() }
692    }
693}
694
695impl<'ptr, T: ?Sized> DerefMut for Borrow<'ptr, T> {
696    fn deref_mut(&mut self) -> &mut Self::Target {
697        // SAFETY: There can only ever be one `Borrow` to the same
698        // data, so we're sure there are no other references.
699        unsafe { self.heap.data_mut() }
700    }
701}
702
703impl<'ptr, T: ?Sized + fmt::Debug> fmt::Debug for Borrow<'ptr, T> {
704    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
705        f.debug_tuple("Borrow").field(&self.deref()).finish()
706    }
707}
708
709///////////////////////////////////////////////////////////////////////////////
710// Errors
711///////////////////////////////////////////////////////////////////////////////
712
713/// An error that may occur during borrowing of [`RefBox`] or [`Weak`].
714#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
715pub enum BorrowError {
716    Borrowed,
717    Dropped,
718}
719
720impl fmt::Display for BorrowError {
721    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722        match self {
723            BorrowError::Borrowed => write!(f, "already borrowed"),
724            BorrowError::Dropped => write!(f, "owner dropped"),
725        }
726    }
727}
728
729impl error::Error for BorrowError {}
730
731///////////////////////////////////////////////////////////////////////////////
732// Tests
733///////////////////////////////////////////////////////////////////////////////
734
735#[cfg(test)]
736mod tests {
737    use std::cell::Cell;
738    use std::panic;
739    use std::rc::Rc;
740
741    use crate::RefBox;
742    use crate::internals::{RefBoxHeap, Status};
743
744    #[test]
745    fn ref_box_new() {
746        let ref_box = RefBox::new(123456);
747        assert_eq!(unsafe { *ref_box.get_unchecked() }, 123456);
748        drop(ref_box);
749    }
750
751    /// The weak count after creation should be 0.
752    #[test]
753    fn ref_box_new_weak_count() {
754        let ref_box = RefBox::new(123456);
755        assert_eq!(ref_box.weak_count(), 0);
756        drop(ref_box);
757    }
758
759    #[test]
760    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
761    fn ref_box_new_cyclic() {
762        let ref_box = RefBox::new_cyclic(|_weak| 13579);
763        assert_eq!(unsafe { *ref_box.get_unchecked() }, 13579);
764        drop(ref_box);
765    }
766
767    /// The weak count in the closure should be 1, and the weak count after creation should be 0.
768    #[test]
769    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
770    fn ref_box_new_cyclic_weak_count() {
771        let ref_box = RefBox::new_cyclic(|weak| {
772            assert_eq!(weak.weak_count(), 1);
773        });
774        assert_eq!(ref_box.weak_count(), 0);
775        drop(ref_box);
776    }
777
778    /// The Weak in the closure should point to the same instance as the returned RefBox.
779    #[test]
780    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
781    fn ref_box_new_cyclic_ptr_eq() {
782        let mut out_weak = None;
783        let ref_box = RefBox::new_cyclic(|weak| out_weak = Some(weak.clone()));
784        assert_eq!(ref_box.ptr.as_ptr(), out_weak.unwrap().ptr.as_ptr());
785        drop(ref_box);
786    }
787
788    /// MIRI: A panic in the closure of [`RefBox::new_cyclic`] should not leak memory.
789    #[test]
790    #[should_panic]
791    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
792    fn ref_box_new_cyclic_does_not_leak() {
793        let ref_box = RefBox::new_cyclic(|_weak| {
794            panic!("panic in closure!");
795        });
796        drop(ref_box);
797    }
798
799    /// A weak pointer returned from [`RefBox::downgrade`] should point to the same
800    /// instance as the RefBox.
801    #[test]
802    fn downgrade_ptr_eq() {
803        let val = 123456;
804        let ref_box = RefBox::new(val);
805        let weak = RefBox::downgrade(&ref_box);
806        assert_eq!(ref_box.ptr.as_ptr(), weak.ptr.as_ptr());
807    }
808
809    /// ['RefBox::downgrade'] should increase the weak reference count.
810    #[test]
811    fn downgrade_increases_refcount() {
812        let val = 123456;
813        let ref_box = RefBox::new(val);
814        assert_eq!(ref_box.weak_count(), 0);
815        let weak = RefBox::downgrade(&ref_box);
816        assert_eq!(ref_box.weak_count(), 1);
817        assert_eq!(weak.weak_count(), 1);
818    }
819
820    /// ['RefBox::downgrade'] should panic if the weak count overflows u32::MAX.
821    #[test]
822    fn downgrade_panics_on_max() {
823        let val = 123456;
824        let ref_box = RefBox::new(val);
825        ref_box.heap().set_weak_count(u32::MAX);
826
827        // Use catch unwind and reset weak count, otherwise MIRI will report memory leak.
828        let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
829            let weak = RefBox::downgrade(&ref_box);
830            drop(weak);
831        }));
832        assert!(result.is_err());
833
834        ref_box.heap().set_weak_count(0);
835        drop(ref_box);
836    }
837
838    /// ['RefBox::try_downgrade'] should return None if the weak count overflows
839    /// u32::MAX.
840    #[test]
841    fn try_downgrade_returns_none_on_max() {
842        let val = 123456;
843        let ref_box = RefBox::new(val);
844        ref_box.heap().set_weak_count(u32::MAX);
845        let weak = RefBox::try_downgrade(&ref_box);
846        assert!(weak.is_none());
847        drop(weak);
848        ref_box.heap().set_weak_count(0);
849        drop(ref_box);
850    }
851
852    /// ['Weak::clone'] should increase the weak reference count.
853    #[test]
854    fn cloning_weak_increases_weak_count() {
855        let val = 123456;
856        let ref_box = RefBox::new(val);
857        assert_eq!(ref_box.weak_count(), 0);
858        let weak = RefBox::downgrade(&ref_box);
859        assert_eq!(ref_box.weak_count(), 1);
860        let weak2 = weak.clone();
861        assert_eq!(ref_box.weak_count(), 2);
862        drop(weak2);
863        drop(weak);
864    }
865
866    /// ['Weak::clone'] should panic if the weak count overflows u32::MAX.
867    #[test]
868    fn cloning_weak_panics_on_max() {
869        let ref_box = RefBox::new(123456);
870        let weak = RefBox::downgrade(&ref_box);
871        weak.heap().set_weak_count(u32::MAX);
872
873        // Use catch unwind and reset refcount, otherwise MIRI will report memory leak.
874        let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
875            let weak2 = weak.clone();
876            drop(weak2);
877        }));
878        assert!(result.is_err());
879
880        drop(weak);
881        ref_box.heap().set_weak_count(0);
882        drop(ref_box);
883    }
884
885    #[test]
886    fn dropping_weak_decreases_weak_count() {
887        let val = 123456;
888        let ref_box = RefBox::new(val);
889        let weak = RefBox::downgrade(&ref_box);
890        assert_eq!(ref_box.weak_count(), 1);
891        drop(weak);
892        assert_eq!(ref_box.weak_count(), 0);
893    }
894
895    #[test]
896    fn owner_is_alive() {
897        let val = 123456;
898        let ref_box = RefBox::new(val);
899        let weak = RefBox::downgrade(&ref_box);
900        assert_eq!(weak.is_alive(), true);
901        drop(ref_box);
902    }
903
904    #[test]
905    fn owner_is_not_alive_after_dropped() {
906        let val = 123456;
907        let ref_box = RefBox::new(val);
908        let weak = RefBox::downgrade(&ref_box);
909        assert_eq!(weak.is_alive(), true);
910        drop(ref_box);
911        assert_eq!(weak.is_alive(), false);
912    }
913
914    #[test]
915    fn dropping_ref_box_drops_data() {
916        struct DropThing(Rc<Cell<bool>>);
917
918        impl Drop for DropThing {
919            fn drop(&mut self) {
920                self.0.set(true);
921            }
922        }
923
924        let drop_checker = Rc::new(Cell::new(false));
925        let ref_box = RefBox::new(DropThing(drop_checker.clone()));
926        assert_eq!(drop_checker.get(), false);
927        drop(ref_box);
928        assert_eq!(drop_checker.get(), true);
929    }
930
931    #[test]
932    fn dropping_rc_with_weak_refs_drops_data() {
933        struct DropThing(Rc<Cell<bool>>);
934
935        impl Drop for DropThing {
936            fn drop(&mut self) {
937                self.0.set(true);
938            }
939        }
940
941        let drop_checker = Rc::new(Cell::new(false));
942        let ref_box = RefBox::new(DropThing(drop_checker.clone()));
943        let weak = RefBox::downgrade(&ref_box);
944        assert_eq!(drop_checker.get(), false);
945        drop(ref_box);
946        assert_eq!(drop_checker.get(), true);
947        drop(weak);
948    }
949
950    #[test]
951    fn dropping_weak_does_not_drop_data() {
952        struct DropThing(Rc<Cell<bool>>);
953
954        impl Drop for DropThing {
955            fn drop(&mut self) {
956                self.0.set(true);
957            }
958        }
959
960        let drop_checker = Rc::new(Cell::new(false));
961        let ref_box = RefBox::new(DropThing(drop_checker.clone()));
962        let weak = RefBox::downgrade(&ref_box);
963        assert_eq!(drop_checker.get(), false);
964        drop(weak);
965        assert_eq!(drop_checker.get(), false);
966        drop(ref_box);
967        assert_eq!(drop_checker.get(), true);
968    }
969
970    #[test]
971    fn owner_is_borrowable() {
972        let ref_box = RefBox::new(123456);
973        let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
974        assert!(borrow.is_ok());
975        drop(borrow);
976        drop(ref_box);
977    }
978
979    #[test]
980    fn owner_is_not_borrowable_twice() {
981        let ref_box = RefBox::new(123456);
982        let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
983        assert!(borrow.is_ok());
984        let borrow2 = ref_box.try_borrow_mut_or_else(|| "was borrowed");
985        assert!(matches!(borrow2, Err("was borrowed")));
986        drop(borrow);
987        drop(borrow2);
988        drop(ref_box);
989    }
990
991    #[test]
992    fn weak_is_borrowable() {
993        let ref_box = RefBox::new(123456);
994        let weak = RefBox::downgrade(&ref_box);
995        let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
996        assert!(matches!(borrow, Ok(_)));
997        drop(borrow);
998        drop(weak);
999        drop(ref_box);
1000    }
1001
1002    #[test]
1003    fn weak_is_not_borrowable_twice() {
1004        let ref_box = RefBox::new(123456);
1005        let weak = RefBox::downgrade(&ref_box);
1006        let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1007        assert!(matches!(borrow, Ok(_)));
1008        let borrow2 = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1009        assert!(matches!(borrow2, Err("was borrowed")));
1010        drop(borrow);
1011        drop(borrow2);
1012        drop(weak);
1013        drop(ref_box);
1014    }
1015
1016    #[test]
1017    fn weak_is_not_borrowable_if_owner_borrowed() {
1018        let ref_box = RefBox::new(123456);
1019        let weak = RefBox::downgrade(&ref_box);
1020        let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
1021        assert!(matches!(borrow, Ok(_)));
1022        let borrow2 = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1023        assert!(matches!(borrow2, Err("was borrowed")));
1024        drop(borrow);
1025        drop(borrow2);
1026        drop(weak);
1027        drop(ref_box);
1028    }
1029
1030    #[test]
1031    fn weak_is_not_borrowable_if_owner_dropped() {
1032        let ref_box = RefBox::new(123456);
1033        let weak = RefBox::downgrade(&ref_box);
1034        drop(ref_box);
1035        let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1036        assert!(matches!(borrow, Err("was dropped")));
1037        drop(borrow);
1038        drop(weak);
1039    }
1040
1041    #[test]
1042    fn dropping_owner_while_borrowed_delays_drops() {
1043        let ref_box = RefBox::new(123456);
1044        let weak = RefBox::downgrade(&ref_box);
1045        let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1046        assert_eq!(weak.status(), Status::Borrowed);
1047        drop(ref_box);
1048        assert_eq!(weak.status(), Status::DroppedWhileBorrowed);
1049        drop(borrow);
1050        assert_eq!(weak.status(), Status::Dropped);
1051        drop(weak);
1052    }
1053
1054    #[test]
1055    fn borrowing_changes_status() {
1056        let ref_box = RefBox::new(123456);
1057        assert_eq!(ref_box.status(), Status::Available);
1058        let borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed");
1059        assert_eq!(ref_box.status(), Status::Borrowed);
1060        drop(borrow);
1061        assert_eq!(ref_box.status(), Status::Available);
1062        drop(ref_box);
1063    }
1064
1065    #[test]
1066    fn dropping_owner_changes_status() {
1067        let ref_box = RefBox::new(123456);
1068        let weak = RefBox::downgrade(&ref_box);
1069        assert_eq!(weak.status(), Status::Available);
1070        drop(ref_box);
1071        assert_eq!(weak.status(), Status::Dropped);
1072        drop(weak);
1073    }
1074
1075    #[test]
1076    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
1077    fn borrowing_in_cyclic_fails() {
1078        let ref_box = RefBox::new_cyclic(|weak| {
1079            let borrow = weak.try_borrow_mut_or_else(|| "was borrowed", || "was dropped");
1080            assert!(borrow.is_err());
1081        });
1082        drop(ref_box);
1083    }
1084
1085    #[test]
1086    #[cfg(any(feature = "cyclic", feature = "cyclic_stable"))]
1087    fn cloning_weak_in_cyclic_increases_refcount() {
1088        let ref_box = RefBox::new_cyclic(|weak| {
1089            let weak2 = weak.clone();
1090            assert_eq!(weak.weak_count(), 2);
1091            drop(weak2);
1092        });
1093        drop(ref_box);
1094    }
1095
1096    #[test]
1097    fn calling_getters_while_having_mutable_ref() {
1098        let ref_box = RefBox::new(123456);
1099        let mut borrow = ref_box.try_borrow_mut_or_else(|| "was borrowed").unwrap();
1100        let mut_ref = &mut *borrow;
1101        assert_eq!(ref_box.weak_count(), 0);
1102        *mut_ref = 654321;
1103        let weak = RefBox::downgrade(&ref_box);
1104        assert_eq!(ref_box.weak_count(), 1);
1105        *mut_ref = 13579;
1106        drop(borrow);
1107        drop(weak);
1108        drop(ref_box);
1109    }
1110
1111    #[test]
1112    fn single_ref_boxes_are_distinct() {
1113        let ref_box_1 = RefBox::new(123456);
1114        let ref_box_2 = RefBox::new(654321);
1115
1116        let borrow1 = ref_box_1.try_borrow_mut().unwrap();
1117        let borrow2 = ref_box_2.try_borrow_mut().unwrap();
1118
1119        assert_ne!(*borrow1, *borrow2);
1120        assert_eq!(*borrow1, 123456);
1121        assert_eq!(*borrow2, 654321);
1122
1123        drop(borrow1);
1124        drop(borrow2);
1125        drop(ref_box_1);
1126        drop(ref_box_2);
1127    }
1128
1129    /// Test if [`RefBox::as_ptr`] returns the right pointer. Run with MIRI.
1130    #[test]
1131    fn ref_box_as_ptr() {
1132        let ref_box = RefBox::new(123456);
1133        let ptr = ref_box.as_ptr();
1134
1135        let heap = unsafe { ref_box.ptr.as_ref() };
1136        let real_ptr = heap.data.get();
1137
1138        assert_eq!(ptr, real_ptr);
1139        drop(ref_box);
1140    }
1141
1142    /// Test if [`Weak::as_ptr`] returns the right pointer. Run with MIRI.
1143    #[test]
1144    fn weak_as_ptr() {
1145        let ref_box = RefBox::new(123456);
1146        let weak = RefBox::downgrade(&ref_box);
1147        let ptr = weak.as_ptr();
1148
1149        let heap = unsafe { weak.ptr.as_ref() };
1150        let real_ptr = heap.data.get();
1151
1152        assert_eq!(ptr, real_ptr);
1153        drop(weak);
1154        drop(ref_box);
1155    }
1156
1157    /// Test if the overhead of the heap part is 8 bytes when 'cyclic_stable' feature is not enabled.
1158    #[test]
1159    #[cfg(not(feature = "cyclic_stable"))]
1160    fn heap_overhead() {
1161        let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1162        assert_eq!(layout.size(), 8);
1163    }
1164
1165    /// Test if the overhead of the heap part is 12 bytes when 'cyclic_stable' feature is enabled
1166    /// and the pointer size is 16 bits.
1167    #[test]
1168    #[cfg(feature = "cyclic_stable")]
1169    #[cfg(any(target_pointer_width = "16"))]
1170    fn heap_overhead_cyclic_stable_16bit() {
1171        let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1172        assert_eq!(layout.size(), 12);
1173    }
1174
1175    /// Test if the overhead of the heap part is 16 bytes when 'cyclic_stable' feature is enabled
1176    /// and the pointer size is 32 bits.
1177    #[test]
1178    #[cfg(feature = "cyclic_stable")]
1179    #[cfg(any(target_pointer_width = "32"))]
1180    fn heap_overhead_cyclic_stable_32bit() {
1181        let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1182        assert_eq!(layout.size(), 16);
1183    }
1184
1185    /// Test if the overhead of the heap part is 24 bytes when 'cyclic_stable' feature is enabled
1186    /// and the pointer size is 64 bits.
1187    #[test]
1188    #[cfg(feature = "cyclic_stable")]
1189    #[cfg(any(target_pointer_width = "64"))]
1190    fn heap_overhead_cyclic_stable_64bit() {
1191        let layout = std::alloc::Layout::new::<RefBoxHeap<()>>();
1192        assert_eq!(layout.size(), 24);
1193    }
1194}