On an unrelated train of thought about what the difference between Pin<Rc<T>> and Rc<T> is, I learned about the try_unwrap(this: Rc<T>) -> Result<T, Rc<T>> function on Rc and similarly on Arc (which could arguably be named try_into_inner, but that ship has sailed).
When you want to have linear types (in the sense of types that cannot be explicitly or implicitly dropped) in Rust, for example because proper dropping needs extra arguments, can fail, or is async, etc., a function like try_unwrap is super useful to get something back out of an Rc without dropping that thing. When you have a “linear” type today, that e.g. uses a drop bomb, you can do
fn get_rid_of(x: Rc<MyLinearType>) {
match Rc::try_unwrap(x) {
Ok(inner) => inner.safely_discard_with("extra argument"),
Err(x) => drop(x) // won't call destructor of `MyLinearType`
// because there’s another `Rc` left
}
This approach does however not work anymore when you have an Arc, since an interleaved execution of two get_rid_of functions, implemented analogously for Arc, could both first determine there's more than one copy of the Arc left, and then both drop their Arc. I feel like we’re missing some API here like
fn unwrap_or_drop<T>(this: Arc<T>) -> Option<T> { /* ... */ }
whose implementation is essentially an atomic version of
{
Arc::try_unwrap(this).ok()
}
For convenience one might also want to have a
fn drop_with<T>(this: Arc<T>, f: impl FnOnce(T)) { /* ... */ }
or, for supporting unsized types that only panic on drop in certain states but can be mutated back into a safe state
fn drop_with_mut<T: ?Sized>(this: Arc<T>, f: impl FnOnce(&mut T)) { /* ... */ }
As an alternative for these drop_with* functions, one could of course also just use an Arc<Wrapper<T>> where Wrapper makes the extra function call on drop. Of course drop_with_mut has the advantage of accepting closures with shorter life-time.
But I digress. My main question here is just:
- Do you think,
unwrap_or_dropis a reasonable extension of theArcAPI?- Is there any way I’ve overlooked how the same can be archieved with the existing API or any technical reason I’ve overlooked why an atomic
unwrap_or_dropdoesn’t work?
- Is there any way I’ve overlooked how the same can be archieved with the existing API or any technical reason I’ve overlooked why an atomic
- Should it be added to
Rc, too, for consistency? - If we want this, how is the process on such API additions? Can a PR with a non-stabilized implementation be created and merged directly or would this need an RFC first?
- And if you care thinking about those as-well, what do you think of the
drop_with*functions?- (I’m open for suggestions for different names, too.)
