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_drop
is a reasonable extension of theArc
API?- 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_drop
doesn’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.)