The implicated functions are Pin::as_mut
(method 1) and Pin::clone
(method 2), not Pin::as_ref
.
The original PoC uses as_ref()
(method 1) and as_mut()
(method 2) to upcast to a trait object; you've shown that that's unnecessary, and you can rely on implicit coercion instead. But that's not the interesting part. dyn MyTrait
does not impl Unpin
, but you don't get any extra abilities from the type not being Unpin
. It simply means that the type system no longer guarantees that is safe to unpin – but at that point the concrete type is still Wrapper
, which actually is safe.
The dangerous part happens when it calls as_mut()
for method 1 – a different call from the one you removed – or clone()
for method 2. That's when the Wrapper
is swapped out for the future.
Don't believe me? Well...
Here is a version that does the coercion before pinning. It goes from Box<Wrapper>
to Box<dyn Dubious>
to Pin<Box<dyn Dubious>>
to Pin<&mut dyn Dubious>
, so there's no coercion happening within the pin.
I'd like to make a version that doesn't use trait objects at all, but the lifetimes don't work out; having a type contain a mutable reference to itself makes the borrow checker act rather weird. I may have been wrong when I said trait objects weren't the only possibility.