Open nikomatsakis opened 4 years ago
Lowering the priority of this to medium, adding as a blocker to #27732 (coerce unsized stabilization).
@nikomatsakis Seems like you forgot to add the P-medium
tag for this issue?
Update: It is possible to abuse existing CoerceUnsized
implementations on stable
. See #85099 (although I created that issue before reading any of this issue and its IRLO thread, so don’t expect any syntactic similarity to the unsoundness examples of this issue).
The type Pin<&LocalType>
implements Deref<Target = LocalType>
but it doesn’t implement DerefMut
. The types Pin
and &
are #[fundamental]
so that an impl DerefMut for Pin<&LocalType>>
is possible. You can use LocalType == SomeLocalStruct
or LocalType == dyn LocalTrait
and you can coerce Pin<Pin<&SomeLocalStruct>>
into Pin<Pin<&dyn LocalTrait>>
. (Indeed, two layers of Pin
!!) This allows creating a pair of “smart pointers that implement CoerceUnsized
but have strange behavior” on stable (Pin<&SomeLocalStruct>
and Pin<&dyn LocalTrait>
become the smart pointers with “strange behavior” and they already implement CoerceUnsized
).
More concretely: Since Pin<&dyn LocalTrait>: Deref<dyn LocalTrait>
, a “strange behavior” DerefMut
implementation of Pin<&dyn LocalTrait>
can be used to dereference an underlying Pin<&SomeLocalStruct>
into, effectively, a target type (wrapped in the trait object) that’s different from SomeLocalStruct
. The struct SomeLocalStruct
might always be Unpin
while the different type behind the &mut dyn LocalTrait
returned by DerefMut
can be !Unpin
. Having SomeLocalStruct: Unpin
allows for easy creation of the Pin<Pin<&SomeLocalStruct>>
which coerces into Pin<Pin<&dyn LocalTrait>>
even though Pin<&dyn LocalTrait>::Target: !Unpin
(and even the actual Target
type inside of the trait object being returned by the DerefMut
can be !Unpin
).
Methods on LocalTrait
can be used both to make the DerefMut
implementation possible and to convert the Pin<&mut dyn LocalTrait>
_(from a Pin::as_mut
call on &mut Pin<Pin<&dyn LocalTrait>>
) back into a pinned mutable referene to the concrete “type behind the &mut dyn LocalTrait
returned by DerefMut
”_.
Split out from #66544. It is possible to exploit
Pin
on nightly Rust (but not stable) by creating smart pointers that implementCoerceUnsized
but have strange behavior. See the dedicated internals thread for more details -- also, please keep conversation on the thread, and not on the Github issue. ❤️