Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ptr] Store invariants in the referent type #2354

Open
jswrenn opened this issue Feb 18, 2025 · 0 comments
Open

[ptr] Store invariants in the referent type #2354

jswrenn opened this issue Feb 18, 2025 · 0 comments

Comments

@jswrenn
Copy link
Collaborator

jswrenn commented Feb 18, 2025

In #2334, inspired by #1866 (comment), we moved the validity invariant of Ptrs 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> requires T: Sized
  • AsInitialized<T> is possibly not expressible because initialized bytes which are written to initialized-but-invalid positions in MaybeUninit<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 in MaybeUninit<T> are almost certainly not preserved through typed copy.
    • We could perhaps work around this by requiring KnownLayout and repr(C) recursively on all fields, but this requirement seems onerous. We probably need language support for this case.

#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)> to Ptr<_, u16, (Unaligned, Exclusive)> is sound, going from a Ptr<_, [u8; 2], (Aligned, Box)> to Ptr<_, u16, (Unaligned, Box)> is not, or at least unusable — it is unsound to even drop the resulting Ptr.
  • For example, while going from a Ptr<_, u16, (Aligned, Exclusive)> to Ptr<_, [u8; 2], (Aligned, Exclusive)> to &mut [u8; 2] is sound, going from a Ptr<_, u16, (Aligned, Box)> to Ptr<_, [u8; 2], (Aligned, Box)> to Box<[u8; 2]> is not — again, it would be unsound to drop the resulting Box.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant