Rollup merge of #95843 - GuillaumeGomez:improve-new-cyclic-doc, r=m-ou-se

Improve Rc::new_cyclic and Arc::new_cyclic documentation

Fixes https://github.com/rust-lang/rust/issues/95672.

cc `@CAD97` (since I used your explanations)
This commit is contained in:
Matthias Krüger 2022-05-05 15:43:02 +02:00 committed by GitHub
commit 3f07303efe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 16 deletions

View File

@ -374,19 +374,26 @@ impl<T> Rc<T> {
} }
} }
/// Constructs a new `Rc<T>` using a closure `data_fn` that has access to a /// Constructs a new `Rc<T>` while giving you a `Weak<T>` to the allocation,
/// weak reference to the constructing `Rc<T>`. /// to allow you to construct a `T` which holds a weak pointer to itself.
/// ///
/// Generally, a structure circularly referencing itself, either directly or /// Generally, a structure circularly referencing itself, either directly or
/// indirectly, should not hold a strong reference to prevent a memory leak. /// indirectly, should not hold a strong reference to itself to prevent a memory leak.
/// In `data_fn`, initialization of `T` can make use of the weak reference /// Using this function, you get access to the weak pointer during the
/// by cloning and storing it inside `T` for use at a later time. /// initialization of `T`, before the `Rc<T>` is created, such that you can
/// clone and store it inside the `T`.
///
/// `new_cyclic` first allocates the managed allocation for the `Rc<T>`,
/// then calls your closure, giving it a `Weak<T>` to this allocation,
/// and only afterwards completes the construction of the `Rc<T>` by placing
/// the `T` returned from your closure into the allocation.
/// ///
/// Since the new `Rc<T>` is not fully-constructed until `Rc<T>::new_cyclic` /// 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 /// returns, calling [`upgrade`] on the weak reference inside your closure will
/// fail and result in a `None` value. /// fail and result in a `None` value.
/// ///
/// # Panics /// # Panics
///
/// If `data_fn` panics, the panic is propagated to the caller, and the /// If `data_fn` panics, the panic is propagated to the caller, and the
/// temporary [`Weak<T>`] is dropped normally. /// temporary [`Weak<T>`] is dropped normally.
/// ///
@ -403,7 +410,12 @@ impl<T> Rc<T> {
/// impl Gadget { /// impl Gadget {
/// /// Construct a reference counted Gadget. /// /// Construct a reference counted Gadget.
/// fn new() -> Rc<Self> { /// fn new() -> Rc<Self> {
/// Rc::new_cyclic(|me| Gadget { me: me.clone() }) /// // `me` is a `Weak<Gadget>` pointing at the new allocation of the
/// // `Rc` we're constructing.
/// Rc::new_cyclic(|me| {
/// // Create the actual struct here.
/// Gadget { me: me.clone() }
/// })
/// } /// }
/// ///
/// /// Return a reference counted pointer to Self. /// /// Return a reference counted pointer to Self.

View File

@ -351,23 +351,31 @@ impl<T> Arc<T> {
unsafe { Self::from_inner(Box::leak(x).into()) } unsafe { Self::from_inner(Box::leak(x).into()) }
} }
/// Constructs a new `Arc<T>` using a closure `data_fn` that has access to /// Constructs a new `Arc<T>` while giving you a `Weak<T>` to the allocation,
/// a weak reference to the constructing `Arc<T>`. /// to allow you to construct a `T` which holds a weak pointer to itself.
/// ///
/// Generally, a structure circularly referencing itself, either directly or /// Generally, a structure circularly referencing itself, either directly or
/// indirectly, should not hold a strong reference to prevent a memory leak. /// indirectly, should not hold a strong reference to itself to prevent a memory leak.
/// In `data_fn`, initialization of `T` can make use of the weak reference /// Using this function, you get access to the weak pointer during the
/// by cloning and storing it inside `T` for use at a later time. /// initialization of `T`, before the `Arc<T>` is created, such that you can
/// clone and store it inside the `T`.
/// ///
/// Since the new `Arc<T>` is not fully-constructed until /// `new_cyclic` first allocates the managed allocation for the `Arc<T>`,
/// `Arc<T>::new_cyclic` returns, calling [`upgrade`] on the weak /// then calls your closure, giving it a `Weak<T>` to this allocation,
/// reference inside `data_fn` will fail and result in a `None` value. /// and only afterwards completes the construction of the `Arc<T>` by placing
/// the `T` returned from your closure into the allocation.
///
/// Since the new `Arc<T>` is not fully-constructed until `Arc<T>::new_cyclic`
/// returns, calling [`upgrade`] on the weak reference inside your closure will
/// fail and result in a `None` value.
/// ///
/// # Panics /// # Panics
///
/// If `data_fn` panics, the panic is propagated to the caller, and the /// If `data_fn` panics, the panic is propagated to the caller, and the
/// temporary [`Weak<T>`] is dropped normally. /// temporary [`Weak<T>`] is dropped normally.
/// ///
/// # Example /// # Example
///
/// ``` /// ```
/// # #![allow(dead_code)] /// # #![allow(dead_code)]
/// use std::sync::{Arc, Weak}; /// use std::sync::{Arc, Weak};
@ -379,7 +387,12 @@ impl<T> Arc<T> {
/// impl Gadget { /// impl Gadget {
/// /// Construct a reference counted Gadget. /// /// Construct a reference counted Gadget.
/// fn new() -> Arc<Self> { /// fn new() -> Arc<Self> {
/// Arc::new_cyclic(|me| Gadget { me: me.clone() }) /// // `me` is a `Weak<Gadget>` pointing at the new allocation of the
/// // `Arc` we're constructing.
/// Arc::new_cyclic(|me| {
/// // Create the actual struct here.
/// Gadget { me: me.clone() }
/// })
/// } /// }
/// ///
/// /// Return a reference counted pointer to Self. /// /// Return a reference counted pointer to Self.