Skip to content

Commit 59d9ad9

Browse files
authored
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
2 parents bfe1564 + 00e191c commit 59d9ad9

File tree

2 files changed

+66
-27
lines changed

2 files changed

+66
-27
lines changed

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

+31-13
Original file line numberDiff line numberDiff line change
@@ -374,33 +374,51 @@ impl<T> Rc<T> {
374374
}
375375
}
376376

377-
/// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
378-
/// to upgrade the weak reference before this function returns will result
379-
/// in a `None` value. However, the weak reference may be cloned freely and
380-
/// stored for use at a later time.
377+
/// Constructs a new `Rc<T>` using a closure `data_fn` that has access to a
378+
/// weak reference to the constructing `Rc<T>`.
379+
///
380+
/// Generally, a structure circularly referencing itself, either directly or
381+
/// indirectly, should not hold a strong reference to prevent a memory leak.
382+
/// In `data_fn`, initialization of `T` can make use of the weak reference
383+
/// by cloning and storing it inside `T` for use at a later time.
384+
///
385+
/// Since the new `Rc<T>` is not fully-constructed until `Rc<T>::new_cyclic`
386+
/// returns, calling [`upgrade`] on the weak reference inside `data_fn` will
387+
/// fail and result in a `None` value.
388+
///
389+
/// # Panics
390+
/// If `data_fn` panics, the panic is propagated to the caller, and the
391+
/// temporary [`Weak<T>`] is dropped normally.
381392
///
382393
/// # Examples
383394
///
384395
/// ```
385-
/// #![feature(arc_new_cyclic)]
386396
/// #![allow(dead_code)]
387397
/// use std::rc::{Rc, Weak};
388398
///
389399
/// struct Gadget {
390-
/// self_weak: Weak<Self>,
391-
/// // ... more fields
400+
/// me: Weak<Gadget>,
392401
/// }
402+
///
393403
/// impl Gadget {
394-
/// pub fn new() -> Rc<Self> {
395-
/// Rc::new_cyclic(|self_weak| {
396-
/// Gadget { self_weak: self_weak.clone(), /* ... */ }
397-
/// })
404+
/// /// Construct a reference counted Gadget.
405+
/// fn new() -> Rc<Self> {
406+
/// Rc::new_cyclic(|me| Gadget { me: me.clone() })
407+
/// }
408+
///
409+
/// /// Return a reference counted pointer to Self.
410+
/// fn me(&self) -> Rc<Self> {
411+
/// self.me.upgrade().unwrap()
398412
/// }
399413
/// }
400414
/// ```
415+
/// [`upgrade`]: Weak::upgrade
401416
#[cfg(not(no_global_oom_handling))]
402-
#[unstable(feature = "arc_new_cyclic", issue = "75861")]
403-
pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
417+
#[stable(feature = "arc_new_cyclic", since = "1.60.0")]
418+
pub fn new_cyclic<F>(data_fn: F) -> Rc<T>
419+
where
420+
F: FnOnce(&Weak<T>) -> T,
421+
{
404422
// Construct the inner in the "uninitialized" state with a single
405423
// weak reference.
406424
let uninit_ptr: NonNull<_> = Box::leak(box RcBox {

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

+35-14
Original file line numberDiff line numberDiff line change
@@ -351,30 +351,51 @@ impl<T> Arc<T> {
351351
unsafe { Self::from_inner(Box::leak(x).into()) }
352352
}
353353

354-
/// Constructs a new `Arc<T>` using a weak reference to itself. Attempting
355-
/// to upgrade the weak reference before this function returns will result
356-
/// in a `None` value. However, the weak reference may be cloned freely and
357-
/// stored for use at a later time.
354+
/// Constructs a new `Arc<T>` using a closure `data_fn` that has access to
355+
/// a weak reference to the constructing `Arc<T>`.
358356
///
359-
/// # Examples
357+
/// Generally, a structure circularly referencing itself, either directly or
358+
/// indirectly, should not hold a strong reference to prevent a memory leak.
359+
/// In `data_fn`, initialization of `T` can make use of the weak reference
360+
/// by cloning and storing it inside `T` for use at a later time.
361+
///
362+
/// Since the new `Arc<T>` is not fully-constructed until
363+
/// `Arc<T>::new_cyclic` returns, calling [`upgrade`] on the weak
364+
/// reference inside `data_fn` will fail and result in a `None` value.
365+
///
366+
/// # Panics
367+
/// If `data_fn` panics, the panic is propagated to the caller, and the
368+
/// temporary [`Weak<T>`] is dropped normally.
369+
///
370+
/// # Example
360371
/// ```
361-
/// #![feature(arc_new_cyclic)]
362372
/// #![allow(dead_code)]
363-
///
364373
/// use std::sync::{Arc, Weak};
365374
///
366-
/// struct Foo {
367-
/// me: Weak<Foo>,
375+
/// struct Gadget {
376+
/// me: Weak<Gadget>,
368377
/// }
369378
///
370-
/// let foo = Arc::new_cyclic(|me| Foo {
371-
/// me: me.clone(),
372-
/// });
379+
/// impl Gadget {
380+
/// /// Construct a reference counted Gadget.
381+
/// fn new() -> Arc<Self> {
382+
/// Arc::new_cyclic(|me| Gadget { me: me.clone() })
383+
/// }
384+
///
385+
/// /// Return a reference counted pointer to Self.
386+
/// fn me(&self) -> Arc<Self> {
387+
/// self.me.upgrade().unwrap()
388+
/// }
389+
/// }
373390
/// ```
391+
/// [`upgrade`]: Weak::upgrade
374392
#[cfg(not(no_global_oom_handling))]
375393
#[inline]
376-
#[unstable(feature = "arc_new_cyclic", issue = "75861")]
377-
pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Arc<T> {
394+
#[stable(feature = "arc_new_cyclic", since = "1.60.0")]
395+
pub fn new_cyclic<F>(data_fn: F) -> Arc<T>
396+
where
397+
F: FnOnce(&Weak<T>) -> T,
398+
{
378399
// Construct the inner in the "uninitialized" state with a single
379400
// weak reference.
380401
let uninit_ptr: NonNull<_> = Box::leak(box ArcInner {

0 commit comments

Comments
 (0)