Description
In #2334, inspired by #1866 (comment), we moved the validity invariant of Ptr
s into the type position. This move was inspired by the observation that the "set of possible valid referents" has a name in type theory — i.e., a type. However, technical limitations prevented us from wholly integrating validity as "real" type. In particular:
MaybeUninit<T>
requiresT: Sized
AsInitialized<T>
is possibly not expressible because initialized bytes which are written to initialized-but-invalid positions inMaybeUninit<T>
are not necessarily preserved through a typed copy (Do typed copies of unions preserve "invalid" bytes? rust-lang/unsafe-code-guidelines#555)Initialized<T>
is not expressible, because initialized bytes written to padding locations inMaybeUninit<T>
are almost certainly not preserved through typed copy.- We could perhaps work around this by requiring
KnownLayout
andrepr(C)
recursively on all fields, but this requirement seems onerous. We probably need language support for this case.
- We could perhaps work around this by requiring
#2334 works around this by introducing 'virtual' wrapper types — Uninit<T>
, Initialized<T>
, AsInitialized<T>
, and Valid<T>
— that occupy the type position of Ptr
but which are not, themselves, real, instantiated types. This trick lets us revise Ptr
's API in such a way that makes it less likely for us to independently and invalidly update T
and the validity (see #1866).
Now, as we begin to extend Ptr
to support owned Box
, Arc
and the ilk (#1183), we have discovered a modeling challenge between the aliasing mode and alignment. We are considering modeling Box
, Arc
, etc., as distinct aliasing modes, but it is unsound for such pointers to be unaligned or to change alignment. This leads to some modeling challenges:
- For example, while going from a
Ptr<_, [u8; 2], (Aligned, Exclusive)>
toPtr<_, u16, (Unaligned, Exclusive)>
is sound, going from aPtr<_, [u8; 2], (Aligned, Box)>
toPtr<_, u16, (Unaligned, Box)>
is not, or at least unusable — it is unsound to even drop the resultingPtr
. - For example, while going from a
Ptr<_, u16, (Aligned, Exclusive)>
toPtr<_, [u8; 2], (Aligned, Exclusive)>
to&mut [u8; 2]
is sound, going from aPtr<_, u16, (Aligned, Box)>
toPtr<_, [u8; 2], (Aligned, Box)>
toBox<[u8; 2]>
is not — again, it would be unsound to drop the resultingBox
.
Once again, we must tread carefully before transitioning between the referent type and an invariant (in this case, alignment). Whereas it was impossible to really move the validity into the type position in #2334, that is not the case for alignment: #1828 provides a prototype implementation of UnalignUnsized
. Taking this approach would require us to require KnownLayout
on Ptr
's referent, but that might have minimal impact on our public API — only affecting APIs which operate on unsized types that do not already have a KnownLayout
bound. This is a small list, encompassing FromZeros::zero
and possibly nothing else.