Because Pin is fundamental, we can just bypass PinCoerceUnsized by doing impl CoerceUnsized for Pin<MySmartPtr>.
Here is an example that uses this to do an unsound Clone (playground):
#![forbid(unsafe_code)]
#![feature(unsize, coerce_unsized)]
use std::{
any::{Any, type_name_of_val},
marker::{PhantomPinned, Unsize},
ops::{CoerceUnsized, Deref},
pin::Pin,
sync::Arc,
};
struct A<T: ?Sized>(Arc<T>);
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<A<U>> for A<T> {}
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<A<U>>> for Pin<A<T>> {}
impl<T: ?Sized> Deref for A<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
trait Producer<T>: Any {
fn get_clone(&self) -> A<dyn Producer<T>> {
panic!("never called")
}
fn observe_pin(self: Pin<&Self>) {
println!("Pinned {} at {self:p}", std::any::type_name::<Self>());
}
}
impl<T: Any> Producer<T> for T {}
struct ValProducer<T> {
ptr: Arc<T>,
}
impl<T> Unpin for ValProducer<T> {}
impl<T: 'static> Producer<T> for ValProducer<T> {
fn get_clone(&self) -> A<dyn Producer<T>> {
A(self.ptr.clone())
}
}
impl<T: Any> Clone for A<dyn Producer<T>> {
fn clone(&self) -> Self {
(**self).get_clone()
}
}
fn break_drop_guarantee<T: Any>(ptr: Arc<T>) {
let unpin: Pin<A<ValProducer<T>>> = Pin::new(A(Arc::new(ValProducer { ptr: ptr.clone() })));
let unpin: Pin<A<dyn Producer<T>>> = unpin;
let pinned: Pin<A<dyn Producer<T>>> = unpin.clone();
pinned.as_ref().observe_pin();
drop((unpin, pinned));
println!("Observing unpinned {} at {ptr:p}", type_name_of_val(&ptr));
let Ok(_unwrapped) = Arc::try_unwrap(ptr) else {
unreachable!()
};
}
fn main() {
struct Victim {
_data: [u8; 32],
_p: PhantomPinned,
}
break_drop_guarantee(Arc::new(Victim {
_data: [0; _],
_p: PhantomPinned,
}));
impl Drop for Victim {
fn drop(&mut self) {
println!("Dropping at {self:p}");
}
}
}
This should also affect #156935.
@rustbot label A-pin F-coerce_unsized requires-nightly I-unsound
Because
Pinis fundamental, we can just bypassPinCoerceUnsizedby doingimpl CoerceUnsized for Pin<MySmartPtr>.Here is an example that uses this to do an unsound
Clone(playground):This should also affect #156935.
@rustbot label A-pin F-coerce_unsized requires-nightly I-unsound