Add function Arc/Rc::as_weak(…) to convert &Arc/Rc<T> to &Weak<T> #1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I would like to propose the addition of a new
as_weak
associated function onArc
andRc
, taking a shared reference to a strongArc
/Rc
and transmuting it into a shared reference to the correspondingWeak
type.Currently, if you have a strong
Arc
/Rc
and you're calling a function that expects a&Weak
, you'll need to.downgrade()
to create a temporaryWeak
, incurring two additional writes to the backing allocation. This could be avoided if it were possible to convert an&Arc
/&Rc
to a&Weak
directly, with a function like this:In memory,
Arc
/Rc
andsync::Weak
/rc::Weak
are both represented by aNotNull
pointer to the backingArcInner
/RcBox
where the reference counts and inner value are actually stored. Whether a reference is strong or weak exists only at the type level, and the static guarantees provided byWeak
(that the pointed-to allocation will exist, unless the pointer has the special non-alignedWeak::new
value) are strictly weaker than those provided byArc
/Rc
(that the pointed-to allocation will exist full-stop, and that the value inside that allocation will still be valid/will not have been dropped yet). TheArc
/Rc
do have aPhantomData<T>
that theWeak
s do not, but it's zero-size and shouldn't affect layout, only drop behaviour (which isn't relevant since the proposed function is for borrowed values).This requires the addition of the
#[repr(transparent)]
attribute toArc
/Rc
, andWeak
in order to guarantee their memory layouts are identical. (#[repr(C)]
might also work for that purpose, but I'm not sure if that would break theNonZero
niche optimization.) According to the discussions at rust-lang#72841 (review), adding the#[repr]
does not constitute a public interface change/commitment because the internal fields are still private (and with rust-lang#90435 such#[repr]
s may be hidden from the docs in the future). So even if the#[repr(transparent)]
were added, this function still couldn't be implemented in an external crate as the crate wouldn't be able to soundly rely on the layout remaining the same; this function can only be implemented in the standard library.This implementation is gated behind a new
#![feature(rc_as_weak)]
.previous discussion: Rust Internals thread #17171, Stack Overflow question #73314967