What I meant for backwards compatibility was that extern
types are already in the wild, whereas immovable types aren't. Subordinating immovable types to the design considerations of extern
types forces compromises into the design of immovable types which don't need to exist.
Viewing Pin<T>
as a wrapper for &mut T
for weird T
begs the question somewhat, since you're arguing for it to be equivalent to &mut T where T: !DynSized
. Also, to the extent that this describes the implementation, you're violating the abstraction barrier. Pin<'a, T>
can be viewed in its own right as a unique reference type with lifetime 'a
which, for T: !Unpin
, can only exist where &mut
/ move access has been permanently disabled for the referent.
You can’t reborrow it for a shorter lifetime;
https://doc.rust-lang.org/nightly/std/mem/struct.Pin.html#method.borrow
For one thing, safe FFI wrappers ought to be, well, safe, and at least potentially (depending on the design of the foreign library) no less hacky than any other Rust API. If DynSized-related issues are unacceptable for normal Rust code (whether compile-time breakage or runtime panics), they’re also unacceptable for FFI wrappers, and we should just get rid of extern type before it’s stabilized.
In principle, yes, but extern
types are a bit of a necessary evil unless/until the soundness issues can be fully addressed. The opportunity exists to have immovable types enter the world entirely absent these issues.
Box
-to-Rc
comes to mind. I'm pretty sure you'd end up with an uninitialized T
at the end of it. I'm not convinced by the argument that immovable types will always be sufficiently abstract that you can't put them in a Box
. Maybe you can come up with a scheme that works for generators, but that's far short of a generalized feature, and doesn't address what external library code might (validly?) do.
If DynSized
is accepted, and if it moves sufficiently close to closing the soundness holes (for some meaning of "sufficiently close"), then yes, I can see this approach being valid. I don't think an unmitigated zero-size hack should make it into stable/production code.
If the idea is for this proposal to be fully backward-compatible with the existing Pin
design, then this doesn't work. Being !DynSized
is inseparable from the type, whereas the T
in a Pin<T>
can have had a fulfilling life as a movable value before getting pinned. Also, unless you want a transition period in which !Unpin
types are warned to implement !DynSized
with ultimate breakage, Pin<T>
needs to be able to maintain its invariants without any changes needed to T
. For these reasons, Pin<T>
would probably have to be equivalent to something like &mut Pinned<T> where Pinned<T>: !DynSized
. (Edit: And this doesn’t address any potential method conflicts, Deref
impl conflicts, ...).
The current design of Pin
currently has that for the &T
case. But yeah, having it just work for &mut T where T: ?Sized
is nice, though I'm not sure how common that is compared to &T where T: ?Sized
. I'm not entirely convinced about the need for distinguishing whether the referent is movable vs immovable for &T
.