From a2341fbbc2f9b35292473f139d17316a55d9e3d0 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 11 Mar 2023 11:19:25 -0800 Subject: [PATCH 1/2] Introduce `Rc::into_inner`, as a parallel to `Arc::into_inner` Unlike `Arc`, `Rc` doesn't have the same race condition to avoid, but maintaining an equivalent API still makes it easier to work with both `Rc` and `Arc`. --- library/alloc/src/rc.rs | 18 ++++++++++++++++++ library/alloc/src/rc/tests.rs | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c9aa23fc4af1f..0e0cf145a992f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -681,6 +681,24 @@ impl Rc { Err(this) } } + + /// Returns the inner value, if the `Rc` has exactly one strong reference. + /// + /// Otherwise, [`None`] is returned and the `Rc` is dropped. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// If `Rc::into_inner` is called on every clone of this `Rc`, + /// it is guaranteed that exactly one of the calls returns the inner value. + /// This means in particular that the inner value is not dropped. + /// + /// This is equivalent to `Rc::try_unwrap(...).ok()`. (Note that these are not equivalent for + /// `Arc`, due to race conditions that do not apply to `Rc`.) + #[inline] + #[unstable(feature = "rc_into_inner", issue = "106894")] + pub fn into_inner(this: Self) -> Option { + Rc::try_unwrap(this).ok() + } } impl Rc<[T]> { diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 32433cfbdcff6..342dc686fa3cb 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -151,6 +151,22 @@ fn try_unwrap() { assert_eq!(Rc::try_unwrap(x), Ok(5)); } +#[test] +fn into_inner() { + let x = Rc::new(3); + assert_eq!(Rc::into_inner(x), Some(3)); + + let x = Rc::new(4); + let y = Rc::clone(&x); + assert_eq!(Rc::into_inner(x), None); + assert_eq!(Rc::into_inner(y), Some(4)); + + let x = Rc::new(5); + let _w = Rc::downgrade(&x); + assert_eq!(Rc::into_inner(x), Some(5)); +} + + #[test] fn into_from_raw() { let x = Rc::new(Box::new("hello")); From 992957efa9a4f12641ffb229e3b57c7088d140eb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 12 Mar 2023 11:21:40 -0700 Subject: [PATCH 2/2] Fix formatting of new Rc::into_inner test --- library/alloc/src/rc/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 342dc686fa3cb..2784108e0e635 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -166,7 +166,6 @@ fn into_inner() { assert_eq!(Rc::into_inner(x), Some(5)); } - #[test] fn into_from_raw() { let x = Rc::new(Box::new("hello"));