... as documented.
The problem: this line from the documentation:
It is allowed for the strong count to be 0 at the time of calling this, but the weak count must be non-zero or the pointer must have originated from a dangling Weak<T> (one created by new).
The weak count as reported by Weak::weak_count is 0 when the strong count is 0, even if there are still outstanding weak references:
pub fn weak_count(&self) -> usize
Gets the number of Weak pointers pointing to this allocation.
If no strong pointers remain, this will return zero.
The combination of these two means that getting a pointer from Weak::into_raw is not enough to guarantee that it's safe to use in Weak::from_raw. Instead, you have to know that (if it originated from a strong reference) you still have an outstanding strong reference to the allocation, because otherwise the (exposed) weak count is 0, and thus calling from_raw is "documented UB".
To properly document when this is intuitively allowed (i.e. it's allowed because I got the pointer from into_raw and have called into_raw more than from_raw, so there are still "unowned" raw weak references to claim) (which lines up with what the implementation allows), we need to expose (probably docs only) the fact that there is still being a weak reference count behind the hood being tracked until all of the Weaks have been dropped.
This will probably also require guaranteeing that Weak doesn't drop its weak reference and become dangling "early" (e.g. note that upgrade failed, decrement the (real) weak count (potentially deallocating the place), and become a dangling weak via internal mutability) and that Weak::clone on a "zombie" Weak increments the (real) weak count and creates a new "zombie" Weak, not a dangling Weak.
... as documented.
The problem: this line from the documentation:
The weak count as reported by
Weak::weak_countis 0 when the strong count is 0, even if there are still outstanding weak references:The combination of these two means that getting a pointer from
Weak::into_rawis not enough to guarantee that it's safe to use inWeak::from_raw. Instead, you have to know that (if it originated from a strong reference) you still have an outstanding strong reference to the allocation, because otherwise the (exposed) weak count is 0, and thus callingfrom_rawis "documented UB".To properly document when this is intuitively allowed (i.e. it's allowed because I got the pointer from
into_rawand have calledinto_rawmore thanfrom_raw, so there are still "unowned" raw weak references to claim) (which lines up with what the implementation allows), we need to expose (probably docs only) the fact that there is still being a weak reference count behind the hood being tracked until all of theWeaks have been dropped.This will probably also require guaranteeing that
Weakdoesn't drop its weak reference and become dangling "early" (e.g. note thatupgradefailed, decrement the (real) weak count (potentially deallocating the place), and become a dangling weak via internal mutability) and thatWeak::cloneon a "zombie"Weakincrements the (real) weak count and creates a new "zombie"Weak, not a danglingWeak.