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"));