diff options
| author | Josh Triplett <josh@joshtriplett.org> | 2023-03-11 11:19:25 -0800 |
|---|---|---|
| committer | Josh Triplett <josh@joshtriplett.org> | 2023-03-11 12:47:12 -0800 |
| commit | a2341fbbc2f9b35292473f139d17316a55d9e3d0 (patch) | |
| tree | c8fc198c21ce3cb8849763dff862f5318b5675ab | |
| parent | d7948c843de94245c794e8c63dd4301a78bb5ba3 (diff) | |
| download | rust-a2341fbbc2f9b35292473f139d17316a55d9e3d0.tar.gz rust-a2341fbbc2f9b35292473f139d17316a55d9e3d0.zip | |
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`.
| -rw-r--r-- | library/alloc/src/rc.rs | 18 | ||||
| -rw-r--r-- | library/alloc/src/rc/tests.rs | 16 |
2 files changed, 34 insertions, 0 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c9aa23fc4af..0e0cf145a99 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -681,6 +681,24 @@ impl<T> Rc<T> { 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<T> { + Rc::try_unwrap(this).ok() + } } impl<T> Rc<[T]> { diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 32433cfbdcf..342dc686fa3 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -152,6 +152,22 @@ fn try_unwrap() { } #[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")); let y = x.clone(); |
