diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-01-23 01:09:40 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-23 01:09:40 +0100 |
| commit | 59d9ad98b66afdfa2d9e636743dfd323321e5f49 (patch) | |
| tree | efc4952cc9c026198e5dd37d38c181637c78e182 /library/alloc/src | |
| parent | bfe15646761a75f0259e204cab071565eed2b1e5 (diff) | |
| parent | 00e191c72d16135e74014bc621629524570bbf77 (diff) | |
| download | rust-59d9ad98b66afdfa2d9e636743dfd323321e5f49.tar.gz rust-59d9ad98b66afdfa2d9e636743dfd323321e5f49.zip | |
Rollup merge of #90666 - bdbai:arc_new_cyclic, r=m-ou-se
Stabilize arc_new_cyclic This stabilizes feature `arc_new_cyclic` as the implementation has been merged for one year and there is no unresolved questions. The FCP is not started yet. Closes #75861 . ``@rustbot`` label +T-libs-api
Diffstat (limited to 'library/alloc/src')
| -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 { |
