(Weak::as_ptr
is stable on beta.)
On the impl and stabilization for Weak::as_ptr
I brought up the need for it to support T: ?Sized
as well. The fact that it doesn't is "just" an implementation limitation, and is planned to be loosened in the future.
In fact, I think it might be possible to loosen it now (bit not when it was stabilized) because of the added align_of_val_raw
.
TL;DR: the way that Weak::as_ptr
goes from *mut RcBox<T>
to *mut T
requires getting the alignment of T
. This is possible statically for sized T
via mem::align_of::<T>()
. For unsized T
, this used to require creating a reference an calling mem::align_of_val(&T)
, which requires an actual T
behind the reference. This isn't guaranteed for Weak
because of Weak::new
(and weak handles to dropped T
s, but std potentially is privileged enough to get away with a reference to a dropped type; you aren't). We now have (unstable) mem::align_of_raw(*const T)
, which allows getting the required alignment of a pointer without asserting its validity, which makes Weak::as_raw
implementable for unsized T
.
If you followed that, feel free to submit a PR! I'll potentially get around to submitting a PR if nobody else has later this week, since this is one of my pet peeves with the stabilized API.
Technically this would stabilize that "something like" mem::align_of_val(*const T)
is possible, so it would be fair to block relaxing the bound to ?Sized
on that, but I don't think that's necessary.
The current Rc
implementation prevents this, as the inner RcBox
allocation is only freed after all of the Weak
s are dropped.
Plus, I think the exposed API prevents dropping the inner allocation sooner. Rc
is required to be able to roundtrip successfully through from_raw(into_raw(_))
, which rules out a split allocation like is done by C++ std::shared_ptr
. I suppose Weak
s could use an internal Cell
to change to a dangling Weak
on a failed upgrade
, as weak_count
always returns 0 if there are no strong references left.
(This is... problematic for Weak::from_raw
. The weak count is (exposed as) 0, so Weak::from_raw(Weak::into_raw(weak))
is "documented UB" (but not (yet) implemented UB) for a weak reference outliving strong references. This is, at best, a problematic footgun, and at worst, makes Weak::from_raw
unusable. Issue tracker: #73840)