diff options
| -rw-r--r-- | library/alloc/src/rc.rs | 44 | ||||
| -rw-r--r-- | library/alloc/src/sync.rs | 49 |
2 files changed, 66 insertions, 27 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index bf5fcfdcbf5..78bf28c843c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -374,33 +374,51 @@ impl<T> Rc<T> { } } - /// Constructs a new `Rc<T>` using a weak reference to itself. Attempting - /// to upgrade the weak reference before this function returns will result - /// in a `None` value. However, the weak reference may be cloned freely and - /// stored for use at a later time. + /// Constructs a new `Rc<T>` using a closure `data_fn` that has access to a + /// weak reference to the constructing `Rc<T>`. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to prevent a memory leak. + /// In `data_fn`, initialization of `T` can make use of the weak reference + /// by cloning and storing it inside `T` for use at a later time. + /// + /// Since the new `Rc<T>` is not fully-constructed until `Rc<T>::new_cyclic` + /// returns, calling [`upgrade`] on the weak reference inside `data_fn` will + /// fail and result in a `None` value. + /// + /// # Panics + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak<T>`] is dropped normally. /// /// # Examples /// /// ``` - /// #![feature(arc_new_cyclic)] /// #![allow(dead_code)] /// use std::rc::{Rc, Weak}; /// /// struct Gadget { - /// self_weak: Weak<Self>, - /// // ... more fields + /// me: Weak<Gadget>, /// } + /// /// impl Gadget { - /// pub fn new() -> Rc<Self> { - /// Rc::new_cyclic(|self_weak| { - /// Gadget { self_weak: self_weak.clone(), /* ... */ } - /// }) + /// /// Construct a reference counted Gadget. + /// fn new() -> Rc<Self> { + /// Rc::new_cyclic(|me| Gadget { me: me.clone() }) + /// } + /// + /// /// Return a reference counted pointer to Self. + /// fn me(&self) -> Rc<Self> { + /// self.me.upgrade().unwrap() /// } /// } /// ``` + /// [`upgrade`]: Weak::upgrade #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "arc_new_cyclic", issue = "75861")] - pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> { + #[stable(feature = "arc_new_cyclic", since = "1.60.0")] + pub fn new_cyclic<F>(data_fn: F) -> Rc<T> + where + F: FnOnce(&Weak<T>) -> T, + { // Construct the inner in the "uninitialized" state with a single // weak reference. let uninit_ptr: NonNull<_> = Box::leak(box RcBox { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index ab8a44b2147..64f21d087da 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -351,30 +351,51 @@ impl<T> Arc<T> { unsafe { Self::from_inner(Box::leak(x).into()) } } - /// Constructs a new `Arc<T>` using a weak reference to itself. Attempting - /// to upgrade the weak reference before this function returns will result - /// in a `None` value. However, the weak reference may be cloned freely and - /// stored for use at a later time. + /// Constructs a new `Arc<T>` using a closure `data_fn` that has access to + /// a weak reference to the constructing `Arc<T>`. /// - /// # Examples + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to prevent a memory leak. + /// In `data_fn`, initialization of `T` can make use of the weak reference + /// by cloning and storing it inside `T` for use at a later time. + /// + /// Since the new `Arc<T>` is not fully-constructed until + /// `Arc<T>::new_cyclic` returns, calling [`upgrade`] on the weak + /// reference inside `data_fn` will fail and result in a `None` value. + /// + /// # Panics + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak<T>`] is dropped normally. + /// + /// # Example /// ``` - /// #![feature(arc_new_cyclic)] /// #![allow(dead_code)] - /// /// use std::sync::{Arc, Weak}; /// - /// struct Foo { - /// me: Weak<Foo>, + /// struct Gadget { + /// me: Weak<Gadget>, /// } /// - /// let foo = Arc::new_cyclic(|me| Foo { - /// me: me.clone(), - /// }); + /// impl Gadget { + /// /// Construct a reference counted Gadget. + /// fn new() -> Arc<Self> { + /// Arc::new_cyclic(|me| Gadget { me: me.clone() }) + /// } + /// + /// /// Return a reference counted pointer to Self. + /// fn me(&self) -> Arc<Self> { + /// self.me.upgrade().unwrap() + /// } + /// } /// ``` + /// [`upgrade`]: Weak::upgrade #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "arc_new_cyclic", issue = "75861")] - pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Arc<T> { + #[stable(feature = "arc_new_cyclic", since = "1.60.0")] + pub fn new_cyclic<F>(data_fn: F) -> Arc<T> + where + F: FnOnce(&Weak<T>) -> T, + { // Construct the inner in the "uninitialized" state with a single // weak reference. let uninit_ptr: NonNull<_> = Box::leak(box ArcInner { |
