Rollup merge of #91589 - derekdreery:arc_unwrap_or_clone, r=m-ou-se
impl `Arc::unwrap_or_clone` The function gets the inner value, cloning only if necessary. The conversation started on [`irlo`](https://internals.rust-lang.org/t/arc-into-inner/15707). If the reviewer think the PR has potential to be merged, and does not need an RFC, then I will create the corresponding tracking issues and update the PR. ## Alternative names - `into_inner` - `make_owned` - `make_unique` - `take_*` (`take_inner`?)
This commit is contained in:
commit
6f03bd09ff
2 changed files with 70 additions and 0 deletions
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -1477,6 +1477,41 @@ impl<T: Clone> Arc<T> {
|
|||
// either unique to begin with, or became one upon cloning the contents.
|
||||
unsafe { Self::get_mut_unchecked(this) }
|
||||
}
|
||||
|
||||
/// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the
|
||||
/// clone.
|
||||
///
|
||||
/// Assuming `arc_t` is of type `Arc<T>`, this function is functionally equivalent to
|
||||
/// `(*arc_t).clone()`, but will avoid cloning the inner value where possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(arc_unwrap_or_clone)]
|
||||
/// # use std::{ptr, sync::Arc};
|
||||
/// let inner = String::from("test");
|
||||
/// let ptr = inner.as_ptr();
|
||||
///
|
||||
/// let arc = Arc::new(inner);
|
||||
/// let inner = Arc::unwrap_or_clone(arc);
|
||||
/// // The inner value was not cloned
|
||||
/// assert!(ptr::eq(ptr, inner.as_ptr()));
|
||||
///
|
||||
/// let arc = Arc::new(inner);
|
||||
/// let arc2 = arc.clone();
|
||||
/// let inner = Arc::unwrap_or_clone(arc);
|
||||
/// // Because there were 2 references, we had to clone the inner value.
|
||||
/// assert!(!ptr::eq(ptr, inner.as_ptr()));
|
||||
/// // `arc2` is the last reference, so when we unwrap it we get back
|
||||
/// // the original `String`.
|
||||
/// let inner = Arc::unwrap_or_clone(arc2);
|
||||
/// assert!(ptr::eq(ptr, inner.as_ptr()));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[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())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue