Skip to content

Commit

Permalink
Add tracking issue and impl for Rc.
Browse files Browse the repository at this point in the history
  • Loading branch information
derekdreery committed Feb 3, 2022
1 parent 0602fb0 commit f5e6d16
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
35 changes: 35 additions & 0 deletions library/alloc/src/rc.rs
Expand Up @@ -1203,6 +1203,41 @@ impl<T: Clone> Rc<T> {
// reference to the allocation.
unsafe { &mut this.ptr.as_mut().value }
}

/// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the
/// clone.
///
/// Assuming `rc_t` is of type `Rc<T>`, this function is functionally equivalent to
/// `(*rc_t).clone()`, but will avoid cloning the inner value where possible.
///
/// # Examples
///
/// ```
/// #![feature(arc_unwrap_or_clone)]
/// # use std::{ptr, rc::Rc};
/// let inner = String::from("test");
/// let ptr = inner.as_ptr();
///
/// let rc = Rc::new(inner);
/// let inner = Rc::unwrap_or_clone(rc);
/// // The inner value was not cloned
/// assert!(ptr::eq(ptr, inner.as_ptr()));
///
/// let rc = Rc::new(inner);
/// let rc2 = rc.clone();
/// let inner = Rc::unwrap_or_clone(rc);
/// // Because there were 2 references, we had to clone the inner value.
/// assert!(!ptr::eq(ptr, inner.as_ptr()));
/// // `rc2` is the last reference, so when we unwrap it we get back
/// // the original `String`.
/// let inner = Rc::unwrap_or_clone(rc2);
/// assert!(ptr::eq(ptr, inner.as_ptr()));
/// ```
#[inline]
#[unstable(feature = "arc_unwrap_or_clone", issue = "93610")]
pub fn unwrap_or_clone(this: Self) -> T {
Rc::try_unwrap(this).unwrap_or_else(|rc| (*rc).clone())
}
}

impl Rc<dyn Any> {
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/sync.rs
Expand Up @@ -1508,7 +1508,7 @@ impl<T: Clone> Arc<T> {
/// assert!(ptr::eq(ptr, inner.as_ptr()));
/// ```
#[inline]
#[unstable(feature = "arc_unwrap_or_clone", issue = "none")]
#[unstable(feature = "arc_unwrap_or_clone", issue = "93610")]
pub fn unwrap_or_clone(this: Self) -> T {
Arc::try_unwrap(this).unwrap_or_else(|arc| (*arc).clone())
}
Expand Down

0 comments on commit f5e6d16

Please sign in to comment.