-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
The PinCoerceUnsized type allows unsize-coercing through Pin.
I found that PinCoerceUnsized has the following impls in the standard library, which are on types that don't even implement Deref, and therefore are useless within a Pin.
unsafe impl<T: ?Sized> PinCoerceUnsized for *const T {}
unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
unsafe impl<T: PointeeSized> PinCoerceUnsized for NonNull<T> {}
unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
unsafe impl<T: ?Sized> PinCoerceUnsized for SyncUnsafeCell<T> {}
unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for alloc::rc::Weak<T, A> {}
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for alloc::sync::Weak<T, A> {}I don't see any point on why these would be allowed. These impls allows some really strange code to compile in stable rust. For example, the following code compiles:
use std::cell::UnsafeCell;
use std::pin::Pin;
fn foo(x: Pin<UnsafeCell<&i32>>) -> Pin<UnsafeCell<&dyn Sync>> {
x
}
fn bar(x: Pin<&i32>) -> Pin<*const dyn Send> {
x
}Notably, despite bar compiling, it is not allowed to coerce a Pin<&i32> to a Pin<*const i32>.
I'm not sure if these strange behaviors have any soundness implications. (Although the impl on the cell types worryingly lack a T: PinCoerceUnsized bound). But since they serve no purpose, can they be deleted?
@rustbot labels +A-pin +A-coercions
Meta
The code snippets are tested on the playground with version 1.91.0-nightly (2025-08-07 2fd855fbfc8239285aa2)