Add a method onto Rc and Arc to unwrap their inner content in a Box

Let's say we have an unsized type (in my case a "dyn std::error::Error") inside of an "Arc". I need to be able to do "try_unwrap" on this type to get the inner type; however, this isn't possible, since the type is unsized. It would be nice to have a "try_unwrap_boxed" method that did what "try_unwrap" does, but puts it into a Box<T>.

I would be willing to implement this. In fact, I have implemented a version of it here: GitHub - notgull/try-unwrap-boxed: Attempt to turn an Rc<T> or an Arc<T> into a Box<T>.

I don't know whether this has to be an RFC or if I could just make a PR in the Rust repository,

6 Likes

It's not possible to store it in a local binding. But have you tried unwrapping directly into a Box::new() call? I haven't tried it (I'm on mobile atm) but it seems like that should work.

It doesn't seems possible.

No, because Rc::try_unwrap and Box::new exist only for T: Sized, even with the unsized_locals feature.

The Box API docs suggest differently, with a T: ?Sized bound on the struct definition, and no other bounds on the impl block or the Box::new() method.

Box::new has a Sized bound. It's easy to miss because it's implicit.

So where does that bound come from? And why hasn't it been added explicitly? It seems to fly in the face of Rust's philosophy of "explicit over implicit".

The Sized bound is implicit on all generics and associate types, unless you explicitly opt-out with ?Sized.

2 Likes

I'd forgotten that even existed.

Sorry if it feels like I'm beating a dead horse, but why does that supercede the very explicit bound on the struct definition?

Because impl bounds doesn't inherit any bounds from the struct defenition ever (iirc)

Except lifetime bounds. Moreover, I’d argue that ?Sized is not a bound, but rather removing an otherwise implicit bound. So even if bounds were inherited from the type definition (for example within the setup defined by the implied bounds RFC), it’s not even sure we’d want to inherit ?Sized.

I would like (sort of) this feature as well: if you work with Pin<Arc<T>>, then it is necessary to return the not-internal equivalent of Pin<ArcInner<T>> from an hypothetical Arc::try_pin_unwrap.

The obvious reason behind the impossibility of using Box is because ArcInner<T> contains more than just T, and if you have a Pinned Arc, you cannot move ArcInner anywhere. On the other hand, ArcInner is an implementation detail, therefore an opaque, non Cloneable newtype is needed to implement Arc::try_pin_unwrap. It is also necessary to make this type work like a Weak with a strong value equal to 0, in order to avoid other living Weak to build an Arc and, at the same time, to avoid that one of them could free ArcInner. But that's another story.

I will probably try to make an RFC for this, but I want to create an issue and a PR to introduce a couple of pin methods for Arc and Rc. Only at that point I will take my time for this feature. If someone else wants to tackle it down before me, I will be happy :grin: