summaryrefslogtreecommitdiffstats
path: root/library/alloc/src/rc.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /library/alloc/src/rc.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/alloc/src/rc.rs')
-rw-r--r--library/alloc/src/rc.rs168
1 files changed, 151 insertions, 17 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 38a711ac7..b3305b8ca 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -258,19 +258,19 @@ use core::iter;
use core::marker::{PhantomData, Unsize};
#[cfg(not(no_global_oom_handling))]
use core::mem::size_of_val;
-use core::mem::{self, align_of_val_raw, forget};
-use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
+use core::mem::{self, align_of_val_raw, forget, ManuallyDrop};
+use core::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
use core::panic::{RefUnwindSafe, UnwindSafe};
#[cfg(not(no_global_oom_handling))]
use core::pin::Pin;
-use core::ptr::{self, NonNull};
+use core::ptr::{self, drop_in_place, NonNull};
#[cfg(not(no_global_oom_handling))]
use core::slice::from_raw_parts_mut;
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
#[cfg(not(no_global_oom_handling))]
-use crate::alloc::{box_free, WriteCloneIntoRaw};
+use crate::alloc::WriteCloneIntoRaw;
use crate::alloc::{AllocError, Allocator, Global, Layout};
use crate::borrow::{Cow, ToOwned};
#[cfg(not(no_global_oom_handling))]
@@ -1169,7 +1169,7 @@ impl<T: ?Sized> Rc<T> {
#[inline]
#[stable(feature = "ptr_eq", since = "1.17.0")]
/// Returns `true` if the two `Rc`s point to the same allocation in a vein similar to
- /// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
+ /// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers.
///
/// # Examples
///
@@ -1184,7 +1184,7 @@ impl<T: ?Sized> Rc<T> {
/// assert!(!Rc::ptr_eq(&five, &other_five));
/// ```
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
- this.ptr.as_ptr() == other.ptr.as_ptr()
+ this.ptr.as_ptr() as *const () == other.ptr.as_ptr() as *const ()
}
}
@@ -1442,23 +1442,21 @@ impl<T: ?Sized> Rc<T> {
}
#[cfg(not(no_global_oom_handling))]
- fn from_box(v: Box<T>) -> Rc<T> {
+ fn from_box(src: Box<T>) -> Rc<T> {
unsafe {
- let (box_unique, alloc) = Box::into_unique(v);
- let bptr = box_unique.as_ptr();
-
- let value_size = size_of_val(&*bptr);
- let ptr = Self::allocate_for_ptr(bptr);
+ let value_size = size_of_val(&*src);
+ let ptr = Self::allocate_for_ptr(&*src);
// Copy value as bytes
ptr::copy_nonoverlapping(
- bptr as *const T as *const u8,
+ &*src as *const T as *const u8,
&mut (*ptr).value as *mut _ as *mut u8,
value_size,
);
// Free the allocation without dropping its contents
- box_free(box_unique, alloc);
+ let src = Box::from_raw(Box::into_raw(src) as *mut mem::ManuallyDrop<T>);
+ drop(src);
Self::from_ptr(ptr)
}
@@ -2468,8 +2466,8 @@ impl<T: ?Sized> Weak<T> {
}
/// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if
- /// both don't point to any allocation (because they were created with `Weak::new()`). See [that
- /// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
+ /// both don't point to any allocation (because they were created with `Weak::new()`). However,
+ /// this function ignores the metadata of `dyn Trait` pointers.
///
/// # Notes
///
@@ -2510,7 +2508,7 @@ impl<T: ?Sized> Weak<T> {
#[must_use]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
- self.ptr.as_ptr() == other.ptr.as_ptr()
+ ptr::eq(self.ptr.as_ptr() as *const (), other.ptr.as_ptr() as *const ())
}
}
@@ -2746,3 +2744,139 @@ fn data_offset_align(align: usize) -> usize {
let layout = Layout::new::<RcBox<()>>();
layout.size() + layout.padding_needed_for(align)
}
+
+/// A uniquely owned `Rc`
+///
+/// This represents an `Rc` that is known to be uniquely owned -- that is, have exactly one strong
+/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
+/// references will fail unless the `UniqueRc` they point to has been converted into a regular `Rc`.
+///
+/// Because they are uniquely owned, the contents of a `UniqueRc` can be freely mutated. A common
+/// use case is to have an object be mutable during its initialization phase but then have it become
+/// immutable and converted to a normal `Rc`.
+///
+/// This can be used as a flexible way to create cyclic data structures, as in the example below.
+///
+/// ```
+/// #![feature(unique_rc_arc)]
+/// use std::rc::{Rc, Weak, UniqueRc};
+///
+/// struct Gadget {
+/// #[allow(dead_code)]
+/// me: Weak<Gadget>,
+/// }
+///
+/// fn create_gadget() -> Option<Rc<Gadget>> {
+/// let mut rc = UniqueRc::new(Gadget {
+/// me: Weak::new(),
+/// });
+/// rc.me = UniqueRc::downgrade(&rc);
+/// Some(UniqueRc::into_rc(rc))
+/// }
+///
+/// create_gadget().unwrap();
+/// ```
+///
+/// An advantage of using `UniqueRc` over [`Rc::new_cyclic`] to build cyclic data structures is that
+/// [`Rc::new_cyclic`]'s `data_fn` parameter cannot be async or return a [`Result`]. As shown in the
+/// previous example, `UniqueRc` allows for more flexibility in the construction of cyclic data,
+/// including fallible or async constructors.
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+#[derive(Debug)]
+pub struct UniqueRc<T> {
+ ptr: NonNull<RcBox<T>>,
+ phantom: PhantomData<RcBox<T>>,
+}
+
+impl<T> UniqueRc<T> {
+ /// Creates a new `UniqueRc`
+ ///
+ /// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
+ /// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
+ /// After converting the `UniqueRc` into an [`Rc`], any weak references created beforehand will
+ /// point to the new [`Rc`].
+ #[cfg(not(no_global_oom_handling))]
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ pub fn new(value: T) -> Self {
+ Self {
+ ptr: Box::leak(Box::new(RcBox {
+ strong: Cell::new(0),
+ // keep one weak reference so if all the weak pointers that are created are dropped
+ // the UniqueRc still stays valid.
+ weak: Cell::new(1),
+ value,
+ }))
+ .into(),
+ phantom: PhantomData,
+ }
+ }
+
+ /// Creates a new weak reference to the `UniqueRc`
+ ///
+ /// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
+ /// to a [`Rc`] using [`UniqueRc::into_rc`].
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ pub fn downgrade(this: &Self) -> Weak<T> {
+ // SAFETY: This pointer was allocated at creation time and we guarantee that we only have
+ // one strong reference before converting to a regular Rc.
+ unsafe {
+ this.ptr.as_ref().inc_weak();
+ }
+ Weak { ptr: this.ptr }
+ }
+
+ /// Converts the `UniqueRc` into a regular [`Rc`]
+ ///
+ /// This consumes the `UniqueRc` and returns a regular [`Rc`] that contains the `value` that
+ /// is passed to `into_rc`.
+ ///
+ /// Any weak references created before this method is called can now be upgraded to strong
+ /// references.
+ #[unstable(feature = "unique_rc_arc", issue = "112566")]
+ pub fn into_rc(this: Self) -> Rc<T> {
+ let mut this = ManuallyDrop::new(this);
+ // SAFETY: This pointer was allocated at creation time so we know it is valid.
+ unsafe {
+ // Convert our weak reference into a strong reference
+ this.ptr.as_mut().strong.set(1);
+ Rc::from_inner(this.ptr)
+ }
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T> Deref for UniqueRc<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ // SAFETY: This pointer was allocated at creation time so we know it is valid.
+ unsafe { &self.ptr.as_ref().value }
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+impl<T> DerefMut for UniqueRc<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ // SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
+ // have unique ownership and therefore it's safe to make a mutable reference because
+ // `UniqueRc` owns the only strong reference to itself.
+ unsafe { &mut (*self.ptr.as_ptr()).value }
+ }
+}
+
+#[unstable(feature = "unique_rc_arc", issue = "112566")]
+unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
+ fn drop(&mut self) {
+ unsafe {
+ // destroy the contained object
+ drop_in_place(DerefMut::deref_mut(self));
+
+ // remove the implicit "strong weak" pointer now that we've destroyed the contents.
+ self.ptr.as_ref().dec_weak();
+
+ if self.ptr.as_ref().weak() == 0 {
+ Global.deallocate(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()));
+ }
+ }
+ }
+}