about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRichard Dodd <richard.o.dodd@gmail.com>2022-02-03 09:35:21 +0000
committerRichard Dodd <richard.o.dodd@gmail.com>2022-02-03 10:40:31 +0000
commitf5e6d16d000e0aa73833de909de44e8dcc8589ed (patch)
tree49da5f40d4668a8ddbac62f1d2a2e3c7a2074bd0
parent0602fb0c6e445f75c598f79ee2f77fe8e2019dd0 (diff)
downloadrust-f5e6d16d000e0aa73833de909de44e8dcc8589ed.tar.gz
rust-f5e6d16d000e0aa73833de909de44e8dcc8589ed.zip
Add tracking issue and impl for `Rc`.
-rw-r--r--library/alloc/src/rc.rs35
-rw-r--r--library/alloc/src/sync.rs2
2 files changed, 36 insertions, 1 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 78bf28c843c..3065169e5e2 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -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> {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 3d132484b2f..7e7670aad64 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -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())
     }