Skip to content

Commit b28775c

Browse files
authored
Rollup merge of #109026 - joshtriplett:rc-into-inner, r=dtolnay
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`.
2 parents afe2575 + 992957e commit b28775c

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

Diff for: library/alloc/src/rc.rs

+18
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,24 @@ impl<T> Rc<T> {
681681
Err(this)
682682
}
683683
}
684+
685+
/// Returns the inner value, if the `Rc` has exactly one strong reference.
686+
///
687+
/// Otherwise, [`None`] is returned and the `Rc` is dropped.
688+
///
689+
/// This will succeed even if there are outstanding weak references.
690+
///
691+
/// If `Rc::into_inner` is called on every clone of this `Rc`,
692+
/// it is guaranteed that exactly one of the calls returns the inner value.
693+
/// This means in particular that the inner value is not dropped.
694+
///
695+
/// This is equivalent to `Rc::try_unwrap(...).ok()`. (Note that these are not equivalent for
696+
/// `Arc`, due to race conditions that do not apply to `Rc`.)
697+
#[inline]
698+
#[unstable(feature = "rc_into_inner", issue = "106894")]
699+
pub fn into_inner(this: Self) -> Option<T> {
700+
Rc::try_unwrap(this).ok()
701+
}
684702
}
685703

686704
impl<T> Rc<[T]> {

Diff for: library/alloc/src/rc/tests.rs

+15
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@ fn try_unwrap() {
151151
assert_eq!(Rc::try_unwrap(x), Ok(5));
152152
}
153153

154+
#[test]
155+
fn into_inner() {
156+
let x = Rc::new(3);
157+
assert_eq!(Rc::into_inner(x), Some(3));
158+
159+
let x = Rc::new(4);
160+
let y = Rc::clone(&x);
161+
assert_eq!(Rc::into_inner(x), None);
162+
assert_eq!(Rc::into_inner(y), Some(4));
163+
164+
let x = Rc::new(5);
165+
let _w = Rc::downgrade(&x);
166+
assert_eq!(Rc::into_inner(x), Some(5));
167+
}
168+
154169
#[test]
155170
fn into_from_raw() {
156171
let x = Rc::new(Box::new("hello"));

0 commit comments

Comments
 (0)