zerocopy/pointer/
ptr.rs

1// Copyright 2023 The Fuchsia Authors
2//
3// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6// This file may not be copied, modified, or distributed except according to
7// those terms.
8
9use core::{marker::PhantomData, ptr::NonNull};
10
11use super::{inner::PtrInner, invariant::*};
12use crate::{CastType, KnownLayout};
13
14/// Module used to gate access to [`Ptr`]'s fields.
15mod def {
16    use super::*;
17
18    #[cfg(doc)]
19    use super::super::invariant;
20
21    /// A raw pointer with more restrictions.
22    ///
23    /// `Ptr<T>` is similar to [`NonNull<T>`], but it is more restrictive in the
24    /// following ways (note that these requirements only hold of non-zero-sized
25    /// referents):
26    /// - It must derive from a valid allocation.
27    /// - It must reference a byte range which is contained inside the
28    ///   allocation from which it derives.
29    ///   - As a consequence, the byte range it references must have a size
30    ///     which does not overflow `isize`.
31    ///
32    /// Depending on how `Ptr` is parameterized, it may have additional
33    /// invariants:
34    /// - `ptr` conforms to the aliasing invariant of
35    ///   [`I::Aliasing`](invariant::Aliasing).
36    /// - `ptr` conforms to the alignment invariant of
37    ///   [`I::Alignment`](invariant::Alignment).
38    /// - `ptr` conforms to the validity invariant of
39    ///   [`I::Validity`](invariant::Validity).
40    ///
41    /// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`.
42    ///
43    /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
44    pub struct Ptr<'a, T, I>
45    where
46        T: ?Sized,
47        I: Invariants,
48    {
49        /// # Invariants
50        ///
51        /// 0. `ptr` conforms to the aliasing invariant of
52        ///    [`I::Aliasing`](invariant::Aliasing).
53        /// 1. `ptr` conforms to the alignment invariant of
54        ///    [`I::Alignment`](invariant::Alignment).
55        /// 2. `ptr` conforms to the validity invariant of
56        ///    [`I::Validity`](invariant::Validity).
57        // SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`.
58        ptr: PtrInner<'a, T>,
59        _invariants: PhantomData<I>,
60    }
61
62    impl<'a, T, I> Ptr<'a, T, I>
63    where
64        T: 'a + ?Sized,
65        I: Invariants,
66    {
67        /// Constructs a `Ptr` from a [`NonNull`].
68        ///
69        /// # Safety
70        ///
71        /// The caller promises that:
72        ///
73        /// 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from
74        ///    some valid Rust allocation, `A`.
75        /// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
76        ///    provenance for `A`.
77        /// 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a
78        ///    byte range which is entirely contained in `A`.
79        /// 3. `ptr` addresses a byte range whose length fits in an `isize`.
80        /// 4. `ptr` addresses a byte range which does not wrap around the
81        ///    address space.
82        /// 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to
83        ///    live for at least `'a`.
84        /// 6. `ptr` conforms to the aliasing invariant of
85        ///    [`I::Aliasing`](invariant::Aliasing).
86        /// 7. `ptr` conforms to the alignment invariant of
87        ///    [`I::Alignment`](invariant::Alignment).
88        /// 8. `ptr` conforms to the validity invariant of
89        ///    [`I::Validity`](invariant::Validity).
90        pub(super) unsafe fn new(ptr: NonNull<T>) -> Ptr<'a, T, I> {
91            // SAFETY: The caller has promised (in 0 - 5) to satisfy all safety
92            // invariants of `PtrInner::new`.
93            let ptr = unsafe { PtrInner::new(ptr) };
94            // SAFETY: The caller has promised (in 6 - 8) to satisfy all safety
95            // invariants of `Ptr`.
96            Self { ptr, _invariants: PhantomData }
97        }
98
99        /// Constructs a new `Ptr` from a [`PtrInner`].
100        ///
101        /// # Safety
102        ///
103        /// The caller promises that:
104        ///
105        /// 0. `ptr` conforms to the aliasing invariant of
106        ///    [`I::Aliasing`](invariant::Aliasing).
107        /// 1. `ptr` conforms to the alignment invariant of
108        ///    [`I::Alignment`](invariant::Alignment).
109        /// 2. `ptr` conforms to the validity invariant of
110        ///    [`I::Validity`](invariant::Validity).
111        pub(super) unsafe fn from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I> {
112            // SAFETY: The caller has promised to satisfy all safety invariants
113            // of `Ptr`.
114            Self { ptr, _invariants: PhantomData }
115        }
116
117        /// Converts this `Ptr<T>` to a [`PtrInner<T>`].
118        ///
119        /// Note that this method does not consume `self`. The caller should
120        /// watch out for `unsafe` code which uses the returned value in a way
121        /// that violates the safety invariants of `self`.
122        pub(crate) fn as_inner(&self) -> PtrInner<'a, T> {
123            self.ptr
124        }
125    }
126}
127
128#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.
129pub use def::Ptr;
130
131/// External trait implementations on [`Ptr`].
132mod _external {
133    use super::*;
134    use core::fmt::{Debug, Formatter};
135
136    /// SAFETY: Shared pointers are safely `Copy`. `Ptr`'s other invariants
137    /// (besides aliasing) are unaffected by the number of references that exist
138    /// to `Ptr`'s referent.
139    impl<'a, T, I> Copy for Ptr<'a, T, I>
140    where
141        T: 'a + ?Sized,
142        I: Invariants<Aliasing = Shared>,
143    {
144    }
145
146    /// SAFETY: Shared pointers are safely `Clone`. `Ptr`'s other invariants
147    /// (besides aliasing) are unaffected by the number of references that exist
148    /// to `Ptr`'s referent.
149    impl<'a, T, I> Clone for Ptr<'a, T, I>
150    where
151        T: 'a + ?Sized,
152        I: Invariants<Aliasing = Shared>,
153    {
154        #[inline]
155        fn clone(&self) -> Self {
156            *self
157        }
158    }
159
160    impl<'a, T, I> Debug for Ptr<'a, T, I>
161    where
162        T: 'a + ?Sized,
163        I: Invariants,
164    {
165        #[inline]
166        fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
167            self.as_inner().as_non_null().fmt(f)
168        }
169    }
170}
171
172/// Methods for converting to and from `Ptr` and Rust's safe reference types.
173mod _conversions {
174    use super::*;
175    use crate::util::{AlignmentVariance, Covariant, TransparentWrapper, ValidityVariance};
176
177    /// `&'a T` → `Ptr<'a, T>`
178    impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)>
179    where
180        T: 'a + ?Sized,
181    {
182        /// Constructs a `Ptr` from a shared reference.
183        #[doc(hidden)]
184        #[inline]
185        pub fn from_ref(ptr: &'a T) -> Self {
186            let inner = PtrInner::from_ref(ptr);
187            // SAFETY:
188            // 0. `ptr`, by invariant on `&'a T`, conforms to the aliasing
189            //    invariant of `Shared`.
190            // 1. `ptr`, by invariant on `&'a T`, conforms to the alignment
191            //    invariant of `Aligned`.
192            // 2. `ptr`, by invariant on `&'a T`, conforms to the validity
193            //    invariant of `Valid`.
194            unsafe { Self::from_inner(inner) }
195        }
196    }
197
198    /// `&'a mut T` → `Ptr<'a, T>`
199    impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)>
200    where
201        T: 'a + ?Sized,
202    {
203        /// Constructs a `Ptr` from an exclusive reference.
204        #[inline]
205        pub(crate) fn from_mut(ptr: &'a mut T) -> Self {
206            let inner = PtrInner::from_mut(ptr);
207            // SAFETY:
208            // 0. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing
209            //    invariant of `Exclusive`.
210            // 1. `ptr`, by invariant on `&'a mut T`, conforms to the alignment
211            //    invariant of `Aligned`.
212            // 2. `ptr`, by invariant on `&'a mut T`, conforms to the validity
213            //    invariant of `Valid`.
214            unsafe { Self::from_inner(inner) }
215        }
216    }
217
218    /// `Ptr<'a, T>` → `&'a T`
219    impl<'a, T, I> Ptr<'a, T, I>
220    where
221        T: 'a + ?Sized,
222        I: Invariants<Alignment = Aligned, Validity = Valid>,
223        I::Aliasing: Reference,
224    {
225        /// Converts `self` to a shared reference.
226        // This consumes `self`, not `&self`, because `self` is, logically, a
227        // pointer. For `I::Aliasing = invariant::Shared`, `Self: Copy`, and so
228        // this doesn't prevent the caller from still using the pointer after
229        // calling `as_ref`.
230        #[allow(clippy::wrong_self_convention)]
231        pub(crate) fn as_ref(self) -> &'a T {
232            let raw = self.as_inner().as_non_null();
233            // SAFETY: This invocation of `NonNull::as_ref` satisfies its
234            // documented safety preconditions:
235            //
236            // 1. The pointer is properly aligned. This is ensured by-contract
237            //    on `Ptr`, because the `I::Alignment` is `Aligned`.
238            //
239            // 2. If the pointer's referent is not zero-sized, then the pointer
240            //    must be “dereferenceable” in the sense defined in the module
241            //    documentation; i.e.:
242            //
243            //    > The memory range of the given size starting at the pointer
244            //    > must all be within the bounds of a single allocated object.
245            //    > [2]
246            //
247            //   This is ensured by contract on all `PtrInner`s.
248            //
249            // 3. The pointer must point to an initialized instance of `T`. This
250            //    is ensured by-contract on `Ptr`, because the `I::Validity` is
251            //    `Valid`.
252            //
253            // 4. You must enforce Rust’s aliasing rules. This is ensured by
254            //    contract on `Ptr`, because `I::Aliasing: Reference`. Either it
255            //    is `Shared` or `Exclusive`. If it is `Shared`, other
256            //    references may not mutate the referent outside of
257            //    `UnsafeCell`s.
258            //
259            // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ref
260            // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety
261            unsafe { raw.as_ref() }
262        }
263    }
264
265    impl<'a, T, I> Ptr<'a, T, I>
266    where
267        T: 'a + ?Sized,
268        I: Invariants,
269        I::Aliasing: Reference,
270    {
271        /// Reborrows `self`, producing another `Ptr`.
272        ///
273        /// Since `self` is borrowed immutably, this prevents any mutable
274        /// methods from being called on `self` as long as the returned `Ptr`
275        /// exists.
276        #[doc(hidden)]
277        #[inline]
278        #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below.
279        pub fn reborrow<'b>(&'b mut self) -> Ptr<'b, T, I>
280        where
281            'a: 'b,
282        {
283            // SAFETY: The following all hold by invariant on `self`, and thus
284            // hold of `ptr = self.as_inner()`:
285            // 0. SEE BELOW.
286            // 1. `ptr` conforms to the alignment invariant of
287            //   [`I::Alignment`](invariant::Alignment).
288            // 2. `ptr` conforms to the validity invariant of
289            //   [`I::Validity`](invariant::Validity).
290            //
291            // For aliasing (6 above), since `I::Aliasing: Reference`,
292            // there are two cases for `I::Aliasing`:
293            // - For `invariant::Shared`: `'a` outlives `'b`, and so the
294            //   returned `Ptr` does not permit accessing the referent any
295            //   longer than is possible via `self`. For shared aliasing, it is
296            //   sound for multiple `Ptr`s to exist simultaneously which
297            //   reference the same memory, so creating a new one is not
298            //   problematic.
299            // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we
300            //   return a `Ptr` with lifetime `'b`, `self` is inaccessible to
301            //   the caller for the lifetime `'b` - in other words, `self` is
302            //   inaccessible to the caller as long as the returned `Ptr`
303            //   exists. Since `self` is an exclusive `Ptr`, no other live
304            //   references or `Ptr`s may exist which refer to the same memory
305            //   while `self` is live. Thus, as long as the returned `Ptr`
306            //   exists, no other references or `Ptr`s which refer to the same
307            //   memory may be live.
308            unsafe { Ptr::from_inner(self.as_inner()) }
309        }
310    }
311
312    /// `Ptr<'a, T>` → `&'a mut T`
313    impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)>
314    where
315        T: 'a + ?Sized,
316    {
317        /// Converts `self` to a mutable reference.
318        #[allow(clippy::wrong_self_convention)]
319        pub(crate) fn as_mut(self) -> &'a mut T {
320            let mut raw = self.as_inner().as_non_null();
321            // SAFETY: This invocation of `NonNull::as_mut` satisfies its
322            // documented safety preconditions:
323            //
324            // 1. The pointer is properly aligned. This is ensured by-contract
325            //    on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`.
326            //
327            // 2. If the pointer's referent is not zero-sized, then the pointer
328            //    must be “dereferenceable” in the sense defined in the module
329            //    documentation; i.e.:
330            //
331            //    > The memory range of the given size starting at the pointer
332            //    > must all be within the bounds of a single allocated object.
333            //    > [2]
334            //
335            //   This is ensured by contract on all `PtrInner`s.
336            //
337            // 3. The pointer must point to an initialized instance of `T`. This
338            //    is ensured by-contract on `Ptr`, because the validity
339            //    invariant is `Valid`.
340            //
341            // 4. You must enforce Rust’s aliasing rules. This is ensured by
342            //    contract on `Ptr`, because the `ALIASING_INVARIANT` is
343            //    `Exclusive`.
344            //
345            // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut
346            // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety
347            unsafe { raw.as_mut() }
348        }
349    }
350
351    /// `Ptr<'a, T = Wrapper<U>>` → `Ptr<'a, U>`
352    impl<'a, T, I> Ptr<'a, T, I>
353    where
354        T: 'a + TransparentWrapper<I, UnsafeCellVariance = Covariant> + ?Sized,
355        I: Invariants,
356    {
357        /// Converts `self` to a transparent wrapper type into a `Ptr` to the
358        /// wrapped inner type.
359        pub(crate) fn transparent_wrapper_into_inner(
360            self,
361        ) -> Ptr<
362            'a,
363            T::Inner,
364            (
365                I::Aliasing,
366                <T::AlignmentVariance as AlignmentVariance<I::Alignment>>::Applied,
367                <T::ValidityVariance as ValidityVariance<I::Validity>>::Applied,
368            ),
369        > {
370            // SAFETY:
371            // - By invariant on `TransparentWrapper::cast_into_inner`:
372            //   - This cast preserves address and referent size, and thus the
373            //     returned pointer addresses the same bytes as `p`
374            //   - This cast preserves provenance
375            // - By invariant on `TransparentWrapper<UnsafeCellVariance =
376            //   Covariant>`, `T` and `T::Inner` have `UnsafeCell`s at the same
377            //   byte ranges. Since `p` and the returned pointer address the
378            //   same byte range, they refer to `UnsafeCell`s at the same byte
379            //   ranges.
380            // - By invariant on `TransparentWrapper`, since `self` satisfies
381            //   the validity invariant `I::Validity`, the returned pointer (of
382            //   type `T::Inner`) satisfies the given "applied" validity
383            //   invariant.
384            let ptr = unsafe { self.transmute_unchecked(|p| T::cast_into_inner(p)) };
385            // SAFETY: By invariant on `TransparentWrapper`, since `self`
386            // satisfies the alignment invariant `I::Alignment`, the returned
387            // pointer (of type `T::Inner`) satisfies the given "applied"
388            // alignment invariant.
389            unsafe { ptr.assume_alignment() }
390        }
391    }
392
393    /// `Ptr<'a, T>` → `Ptr<'a, U>`
394    impl<'a, T: ?Sized, I> Ptr<'a, T, I>
395    where
396        I: Invariants,
397    {
398        /// Casts to a different (unsized) target type without checking interior
399        /// mutability.
400        ///
401        /// Callers should prefer [`cast_unsized`] where possible.
402        ///
403        /// [`cast_unsized`]: Ptr::cast_unsized
404        ///
405        /// # Safety
406        ///
407        /// The caller promises that `u = cast(p)` is a pointer cast with the
408        /// following properties:
409        /// - `u` addresses a subset of the bytes addressed by `p`
410        /// - `u` has the same provenance as `p`
411        /// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist
412        ///   at ranges identical to those at which `UnsafeCell`s exist in `*p`
413        /// - It is sound to transmute a pointer of type `T` with aliasing
414        ///   `I::Aliasing` and validity `I::Validity` to a pointer of type `U`
415        ///   with aliasing `I::Aliasing` and validity `V`. This is a subtle
416        ///   soundness requirement that is a function of `T`, `U`,
417        ///   `I::Aliasing`, `I::Validity`, and `V`, and may depend upon the
418        ///   presence, absence, or specific location of `UnsafeCell`s in `T`
419        ///   and/or `U`.
420        #[doc(hidden)]
421        #[inline]
422        pub unsafe fn transmute_unchecked<U: ?Sized, V, F>(
423            self,
424            cast: F,
425        ) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)>
426        where
427            V: Validity,
428            F: FnOnce(*mut T) -> *mut U,
429        {
430            let ptr = cast(self.as_inner().as_non_null().as_ptr());
431
432            // SAFETY: Caller promises that `cast` returns a pointer whose
433            // address is in the range of `self.as_inner().as_non_null()`'s referent. By
434            // invariant, none of these addresses are null.
435            let ptr = unsafe { NonNull::new_unchecked(ptr) };
436
437            // SAFETY:
438            //
439            // Lemma 1: `ptr` has the same provenance as `self`. The caller
440            // promises that `cast` preserves provenance, and we call it with
441            // `self.as_inner().as_non_null()`.
442            //
443            // 0. By invariant,  if `self`'s referent is not zero sized, then
444            //    `self` is derived from some valid Rust allocation, `A`. By
445            //    Lemma 1, `ptr` has the same provenance as `self`. Thus, `ptr`
446            //    is derived from `A`.
447            // 1. By invariant, if `self`'s referent is not zero sized, then
448            //    `self` has valid provenance for `A`. By Lemma 1, so does
449            //    `ptr`.
450            // 2. By invariant on `self` and caller precondition, if `ptr`'s
451            //    referent is not zero sized, then `ptr` addresses a byte range
452            //    which is entirely contained in `A`.
453            // 3. By invariant on `self` and caller precondition, `ptr`
454            //    addresses a byte range whose length fits in an `isize`.
455            // 4. By invariant on `self` and caller precondition, `ptr`
456            //    addresses a byte range which does not wrap around the address
457            //    space.
458            // 5. By invariant on `self`, if `self`'s referent is not zero
459            //    sized, then `A` is guaranteed to live for at least `'a`.
460            // 6. `ptr` conforms to the aliasing invariant of `I::Aliasing`:
461            //    - `Exclusive`: `self` is the only `Ptr` or reference which is
462            //      permitted to read or modify the referent for the lifetime
463            //      `'a`. Since we consume `self` by value, the returned pointer
464            //      remains the only `Ptr` or reference which is permitted to
465            //      read or modify the referent for the lifetime `'a`.
466            //    - `Shared`: Since `self` has aliasing `Shared`, we know that
467            //      no other code may mutate the referent during the lifetime
468            //      `'a`, except via `UnsafeCell`s. The caller promises that
469            //      `UnsafeCell`s cover the same byte ranges in `*self` and
470            //      `*ptr`. For each byte in the referent, there are two cases:
471            //      - If the byte is not covered by an `UnsafeCell` in `*ptr`,
472            //        then it is not covered in `*self`. By invariant on `self`,
473            //        it will not be mutated during `'a`, as required by the
474            //        constructed pointer. Similarly, the returned pointer will
475            //        not permit any mutations to these locations, as required
476            //        by the invariant on `self`.
477            //      - If the byte is covered by an `UnsafeCell` in `*ptr`, then
478            //        the returned pointer's invariants do not assume that the
479            //        byte will not be mutated during `'a`. While the returned
480            //        pointer will permit mutation of this byte during `'a`, by
481            //        invariant on `self`, no other code assumes that this will
482            //        not happen.
483            //    - `Inaccessible`: There are no restrictions we need to uphold.
484            // 7. `ptr` trivially satisfies the alignment invariant `Unaligned`.
485            // 8. The caller promises that `ptr` conforms to the validity
486            //    invariant `V` with respect to its referent type, `U`.
487            unsafe { Ptr::new(ptr) }
488        }
489    }
490
491    /// `Ptr<'a, T, (_, _, _)>` → `Ptr<'a, Unalign<T>, (_, Aligned, _)>`
492    impl<'a, T, I> Ptr<'a, T, I>
493    where
494        I: Invariants,
495    {
496        /// Converts a `Ptr` an unaligned `T` into a `Ptr` to an aligned
497        /// `Unalign<T>`.
498        pub(crate) fn into_unalign(
499            self,
500        ) -> Ptr<'a, crate::Unalign<T>, (I::Aliasing, Aligned, I::Validity)> {
501            // SAFETY:
502            // - This cast preserves provenance.
503            // - This cast preserves address. `Unalign<T>` promises to have the
504            //   same size as `T`, and so the cast returns a pointer addressing
505            //   the same byte range as `p`.
506            // - By the same argument, the returned pointer refers to
507            //   `UnsafeCell`s at the same locations as `p`.
508            // - `Unalign<T>` promises to have the same bit validity as `T`
509            let ptr = unsafe {
510                #[allow(clippy::as_conversions)]
511                self.transmute_unchecked(|p: *mut T| p as *mut crate::Unalign<T>)
512            };
513            ptr.bikeshed_recall_aligned()
514        }
515    }
516}
517
518/// State transitions between invariants.
519mod _transitions {
520    use super::*;
521    use crate::{AlignmentError, TryFromBytes, ValidityError};
522
523    impl<'a, T, I> Ptr<'a, T, I>
524    where
525        T: 'a + ?Sized,
526        I: Invariants,
527    {
528        /// Returns a `Ptr` with [`Exclusive`] aliasing if `self` already has
529        /// `Exclusive` aliasing.
530        ///
531        /// This allows code which is generic over aliasing to down-cast to a
532        /// concrete aliasing.
533        ///
534        /// [`Exclusive`]: crate::pointer::invariant::Exclusive
535        #[inline]
536        pub(crate) fn into_exclusive_or_post_monomorphization_error(
537            self,
538        ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> {
539            // NOTE(https://github.com/rust-lang/rust/issues/131625): We do this
540            // rather than just having `Aliasing::IS_EXCLUSIVE` have the panic
541            // behavior because doing it that way causes rustdoc to fail while
542            // attempting to document hidden items (since it evaluates the
543            // constant - and thus panics).
544            trait AliasingExt: Aliasing {
545                const IS_EXCL: bool;
546            }
547
548            impl<A: Aliasing> AliasingExt for A {
549                const IS_EXCL: bool = {
550                    const_assert!(Self::IS_EXCLUSIVE);
551                    true
552                };
553            }
554
555            assert!(I::Aliasing::IS_EXCL);
556
557            // SAFETY: We've confirmed that `self` already has the aliasing
558            // `Exclusive`. If it didn't, either the preceding assert would fail
559            // or evaluating `I::Aliasing::IS_EXCL` would fail. We're *pretty*
560            // sure that it's guaranteed to fail const eval, but the `assert!`
561            // provides a backstop in case that doesn't work.
562            unsafe { self.assume_exclusive() }
563        }
564
565        /// Assumes that `self` satisfies the invariants `H`.
566        ///
567        /// # Safety
568        ///
569        /// The caller promises that `self` satisfies the invariants `H`.
570        unsafe fn assume_invariants<H: Invariants>(self) -> Ptr<'a, T, H> {
571            // SAFETY: The caller has promised to satisfy all parameterized
572            // invariants of `Ptr`. `Ptr`'s other invariants are satisfied
573            // by-contract by the source `Ptr`.
574            unsafe { Ptr::from_inner(self.as_inner()) }
575        }
576
577        /// Helps the type system unify two distinct invariant types which are
578        /// actually the same.
579        pub(crate) fn unify_invariants<
580            H: Invariants<Aliasing = I::Aliasing, Alignment = I::Alignment, Validity = I::Validity>,
581        >(
582            self,
583        ) -> Ptr<'a, T, H> {
584            // SAFETY: The associated type bounds on `H` ensure that the
585            // invariants are unchanged.
586            unsafe { self.assume_invariants::<H>() }
587        }
588
589        /// Assumes that `self` satisfies the aliasing requirement of `A`.
590        ///
591        /// # Safety
592        ///
593        /// The caller promises that `self` satisfies the aliasing requirement
594        /// of `A`.
595        #[inline]
596        pub(crate) unsafe fn assume_aliasing<A: Aliasing>(
597            self,
598        ) -> Ptr<'a, T, (A, I::Alignment, I::Validity)> {
599            // SAFETY: The caller promises that `self` satisfies the aliasing
600            // requirements of `A`.
601            unsafe { self.assume_invariants() }
602        }
603
604        /// Assumes `self` satisfies the aliasing requirement of [`Exclusive`].
605        ///
606        /// # Safety
607        ///
608        /// The caller promises that `self` satisfies the aliasing requirement
609        /// of `Exclusive`.
610        ///
611        /// [`Exclusive`]: crate::pointer::invariant::Exclusive
612        #[inline]
613        pub(crate) unsafe fn assume_exclusive(
614            self,
615        ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> {
616            // SAFETY: The caller promises that `self` satisfies the aliasing
617            // requirements of `Exclusive`.
618            unsafe { self.assume_aliasing::<Exclusive>() }
619        }
620
621        /// Assumes that `self`'s referent is validly-aligned for `T` if
622        /// required by `A`.
623        ///
624        /// # Safety
625        ///
626        /// The caller promises that `self`'s referent conforms to the alignment
627        /// invariant of `T` if required by `A`.
628        #[inline]
629        pub(crate) unsafe fn assume_alignment<A: Alignment>(
630            self,
631        ) -> Ptr<'a, T, (I::Aliasing, A, I::Validity)> {
632            // SAFETY: The caller promises that `self`'s referent is
633            // well-aligned for `T` if required by `A` .
634            unsafe { self.assume_invariants() }
635        }
636
637        /// Checks the `self`'s alignment at runtime, returning an aligned `Ptr`
638        /// on success.
639        pub(crate) fn bikeshed_try_into_aligned(
640            self,
641        ) -> Result<Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>, AlignmentError<Self, T>>
642        where
643            T: Sized,
644        {
645            if let Err(err) =
646                crate::util::validate_aligned_to::<_, T>(self.as_inner().as_non_null())
647            {
648                return Err(err.with_src(self));
649            }
650
651            // SAFETY: We just checked the alignment.
652            Ok(unsafe { self.assume_alignment::<Aligned>() })
653        }
654
655        /// Recalls that `self`'s referent is validly-aligned for `T`.
656        #[inline]
657        // TODO(#859): Reconsider the name of this method before making it
658        // public.
659        pub(crate) fn bikeshed_recall_aligned(
660            self,
661        ) -> Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>
662        where
663            T: crate::Unaligned,
664        {
665            // SAFETY: The bound `T: Unaligned` ensures that `T` has no
666            // non-trivial alignment requirement.
667            unsafe { self.assume_alignment::<Aligned>() }
668        }
669
670        /// Assumes that `self`'s referent conforms to the validity requirement
671        /// of `V`.
672        ///
673        /// # Safety
674        ///
675        /// The caller promises that `self`'s referent conforms to the validity
676        /// requirement of `V`.
677        #[doc(hidden)]
678        #[must_use]
679        #[inline]
680        pub unsafe fn assume_validity<V: Validity>(
681            self,
682        ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> {
683            // SAFETY: The caller promises that `self`'s referent conforms to
684            // the validity requirement of `V`.
685            unsafe { self.assume_invariants() }
686        }
687
688        /// A shorthand for `self.assume_validity<invariant::Initialized>()`.
689        ///
690        /// # Safety
691        ///
692        /// The caller promises to uphold the safety preconditions of
693        /// `self.assume_validity<invariant::Initialized>()`.
694        #[doc(hidden)]
695        #[must_use]
696        #[inline]
697        pub unsafe fn assume_initialized(
698            self,
699        ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> {
700            // SAFETY: The caller has promised to uphold the safety
701            // preconditions.
702            unsafe { self.assume_validity::<Initialized>() }
703        }
704
705        /// A shorthand for `self.assume_validity<Valid>()`.
706        ///
707        /// # Safety
708        ///
709        /// The caller promises to uphold the safety preconditions of
710        /// `self.assume_validity<Valid>()`.
711        #[doc(hidden)]
712        #[must_use]
713        #[inline]
714        pub unsafe fn assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> {
715            // SAFETY: The caller has promised to uphold the safety
716            // preconditions.
717            unsafe { self.assume_validity::<Valid>() }
718        }
719
720        /// Recalls that `self`'s referent is initialized.
721        #[doc(hidden)]
722        #[must_use]
723        #[inline]
724        // TODO(#859): Reconsider the name of this method before making it
725        // public.
726        pub fn bikeshed_recall_initialized_from_bytes(
727            self,
728        ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)>
729        where
730            T: crate::IntoBytes + crate::FromBytes,
731            I: Invariants<Validity = Valid>,
732        {
733            // SAFETY: The `T: IntoBytes` bound ensures that any bit-valid `T`
734            // is entirely initialized. `I: Invariants<Validity = Valid>`
735            // ensures that `self`'s referent is a bit-valid `T`. Producing an
736            // `Initialized` `Ptr` may permit the caller to write arbitrary
737            // initialized bytes to the referent (depending on aliasing mode and
738            // presence of `UnsafeCell`s). `T: FromBytes` ensures that any byte
739            // sequence written will remain a bit-valid `T`.
740            unsafe { self.assume_initialized() }
741        }
742
743        /// Recalls that `self`'s referent is initialized.
744        #[doc(hidden)]
745        #[must_use]
746        #[inline]
747        // TODO(#859): Reconsider the name of this method before making it
748        // public.
749        pub fn bikeshed_recall_initialized_immutable(
750            self,
751        ) -> Ptr<'a, T, (Shared, I::Alignment, Initialized)>
752        where
753            T: crate::IntoBytes + crate::Immutable,
754            I: Invariants<Aliasing = Shared, Validity = Valid>,
755        {
756            // SAFETY: The `T: IntoBytes` bound ensures that any bit-valid `T`
757            // is entirely initialized. `I: Invariants<Validity = Valid>`
758            // ensures that `self`'s referent is a bit-valid `T`. Since `T:
759            // Immutable` and the aliasing is `Shared`, the resulting `Ptr`
760            // cannot be used to modify the referent, and so it's acceptable
761            // that going from `Valid` to `Initialized` may increase the set of
762            // values allowed in the referent.
763            unsafe { self.assume_initialized() }
764        }
765
766        /// Recalls that `self`'s referent is bit-valid for `T`.
767        #[doc(hidden)]
768        #[must_use]
769        #[inline]
770        // TODO(#859): Reconsider the name of this method before making it
771        // public.
772        pub fn bikeshed_recall_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>
773        where
774            T: crate::FromBytes,
775            I: Invariants<Validity = Initialized>,
776        {
777            // SAFETY: The bound `T: FromBytes` ensures that any initialized
778            // sequence of bytes is bit-valid for `T`. `I: Invariants<Validity =
779            // invariant::Initialized>` ensures that all of the referent bytes
780            // are initialized.
781            unsafe { self.assume_valid() }
782        }
783
784        /// Checks that `self`'s referent is validly initialized for `T`,
785        /// returning a `Ptr` with `Valid` on success.
786        ///
787        /// # Panics
788        ///
789        /// This method will panic if
790        /// [`T::is_bit_valid`][TryFromBytes::is_bit_valid] panics.
791        ///
792        /// # Safety
793        ///
794        /// On error, unsafe code may rely on this method's returned
795        /// `ValidityError` containing `self`.
796        #[inline]
797        pub(crate) fn try_into_valid<R>(
798            mut self,
799        ) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>, ValidityError<Self, T>>
800        where
801            T: TryFromBytes + Read<I::Aliasing, R>,
802            I::Aliasing: Reference,
803            I: Invariants<Validity = Initialized>,
804            R: crate::pointer::ReadReason,
805        {
806            // This call may panic. If that happens, it doesn't cause any soundness
807            // issues, as we have not generated any invalid state which we need to
808            // fix before returning.
809            if T::is_bit_valid(self.reborrow().forget_aligned()) {
810                // SAFETY: If `T::is_bit_valid`, code may assume that `self`
811                // contains a bit-valid instance of `Self`.
812                Ok(unsafe { self.assume_valid() })
813            } else {
814                Err(ValidityError::new(self))
815            }
816        }
817
818        /// Forgets that `self`'s referent is validly-aligned for `T`.
819        #[doc(hidden)]
820        #[must_use]
821        #[inline]
822        pub fn forget_aligned(self) -> Ptr<'a, T, (I::Aliasing, Unaligned, I::Validity)> {
823            // SAFETY: `Unaligned` is less restrictive than `Aligned`.
824            unsafe { self.assume_invariants() }
825        }
826    }
827}
828
829/// Casts of the referent type.
830mod _casts {
831    use super::*;
832    use crate::{CastError, SizeError};
833
834    impl<'a, T, I> Ptr<'a, T, I>
835    where
836        T: 'a + ?Sized,
837        I: Invariants,
838    {
839        /// Casts to a different (unsized) target type without checking interior
840        /// mutability.
841        ///
842        /// Callers should prefer [`cast_unsized`] where possible.
843        ///
844        /// [`cast_unsized`]: Ptr::cast_unsized
845        ///
846        /// # Safety
847        ///
848        /// The caller promises that `u = cast(p)` is a pointer cast with the
849        /// following properties:
850        /// - `u` addresses a subset of the bytes addressed by `p`
851        /// - `u` has the same provenance as `p`
852        /// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist
853        ///   at ranges identical to those at which `UnsafeCell`s exist in `*p`
854        #[doc(hidden)]
855        #[inline]
856        pub unsafe fn cast_unsized_unchecked<U, F: FnOnce(*mut T) -> *mut U>(
857            self,
858            cast: F,
859        ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)>
860        where
861            U: 'a + CastableFrom<T, I::Validity, I::Validity> + ?Sized,
862        {
863            // SAFETY:
864            // - The caller promises that `u = cast(p)` is a pointer which
865            //   satisfies:
866            //   - `u` addresses a subset of the bytes addressed by `p`
867            //   - `u` has the same provenance as `p`
868            //   - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must
869            //     exist at ranges identical to those at which `UnsafeCell`s
870            //     exist in `*p`
871            // - By `U: CastableFrom<T, I::Validity, I::Validity>`,
872            //   `I::Validity` is either `Uninit` or `Initialized`. In both
873            //   cases, the bit validity `I::Validity` has the same semantics
874            //   regardless of referent type. In other words, the set of allowed
875            //   referent values for `Ptr<T, (_, _, I::Validity)>` and `Ptr<U,
876            //   (_, _, I::Validity)>` are identical.
877            unsafe { self.transmute_unchecked(cast) }
878        }
879
880        /// Casts to a different (unsized) target type.
881        ///
882        /// # Safety
883        ///
884        /// The caller promises that `u = cast(p)` is a pointer cast with the
885        /// following properties:
886        /// - `u` addresses a subset of the bytes addressed by `p`
887        /// - `u` has the same provenance as `p`
888        #[doc(hidden)]
889        #[inline]
890        pub unsafe fn cast_unsized<U, F, R, S>(
891            self,
892            cast: F,
893        ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)>
894        where
895            T: Read<I::Aliasing, R>,
896            U: 'a + ?Sized + Read<I::Aliasing, S> + CastableFrom<T, I::Validity, I::Validity>,
897            R: ReadReason,
898            S: ReadReason,
899            F: FnOnce(*mut T) -> *mut U,
900        {
901            // SAFETY: Because `T` and `U` both implement `Read<I::Aliasing, _>`,
902            // either:
903            // - `I::Aliasing` is `Exclusive`
904            // - `T` and `U` are both `Immutable`, in which case they trivially
905            //   contain `UnsafeCell`s at identical locations
906            //
907            // The caller promises all other safety preconditions.
908            unsafe { self.cast_unsized_unchecked(cast) }
909        }
910    }
911
912    impl<'a, T, I> Ptr<'a, T, I>
913    where
914        T: 'a + KnownLayout + ?Sized,
915        I: Invariants<Validity = Initialized>,
916    {
917        /// Casts this pointer-to-initialized into a pointer-to-bytes.
918        #[allow(clippy::wrong_self_convention)]
919        pub(crate) fn as_bytes<R>(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Valid)>
920        where
921            R: ReadReason,
922            T: Read<I::Aliasing, R>,
923            I::Aliasing: Reference,
924        {
925            let bytes = match T::size_of_val_raw(self.as_inner().as_non_null()) {
926                Some(bytes) => bytes,
927                // SAFETY: `KnownLayout::size_of_val_raw` promises to always
928                // return `Some` so long as the resulting size fits in a
929                // `usize`. By invariant on `Ptr`, `self` refers to a range of
930                // bytes whose size fits in an `isize`, which implies that it
931                // also fits in a `usize`.
932                None => unsafe { core::hint::unreachable_unchecked() },
933            };
934
935            // SAFETY:
936            // - `slice_from_raw_parts_mut` and `.cast` both preserve the
937            //   pointer's address, and `bytes` is the length of `p`, so the
938            //   returned pointer addresses the same bytes as `p`
939            // - `slice_from_raw_parts_mut` and `.cast` both preserve provenance
940            let ptr: Ptr<'a, [u8], _> = unsafe {
941                self.cast_unsized(|p: *mut T| {
942                    #[allow(clippy::as_conversions)]
943                    core::ptr::slice_from_raw_parts_mut(p.cast::<u8>(), bytes)
944                })
945            };
946
947            let ptr = ptr.bikeshed_recall_aligned();
948
949            // SAFETY: `ptr`'s referent begins as `Initialized`, denoting that
950            // all bytes of the referent are initialized bytes. The referent
951            // type is then casted to `[u8]`, whose only validity invariant is
952            // that its bytes are initialized. This validity invariant is
953            // satisfied by the `Initialized` invariant on the starting `ptr`.
954            unsafe { ptr.assume_validity::<Valid>() }
955        }
956    }
957
958    impl<'a, T, I, const N: usize> Ptr<'a, [T; N], I>
959    where
960        T: 'a,
961        I: Invariants,
962    {
963        /// Casts this pointer-to-array into a slice.
964        #[allow(clippy::wrong_self_convention)]
965        pub(crate) fn as_slice(self) -> Ptr<'a, [T], I> {
966            let slice = self.as_inner().as_slice();
967            // SAFETY: Note that, by post-condition on `PtrInner::as_slice`,
968            // `slice` refers to the same byte range as `self.as_inner()`.
969            //
970            // 6. Thus, `slice` conforms to the aliasing invariant of
971            //    `I::Aliasing` because `self` does.
972            // 7. By the above lemma, `slice` conforms to the alignment
973            //    invariant of `I::Alignment` because `self` does.
974            // 8. By the above lemma, `slice` conforms to the validity invariant
975            //    of `I::Validity` because `self` does.
976            unsafe { Ptr::from_inner(slice) }
977        }
978    }
979
980    /// For caller convenience, these methods are generic over alignment
981    /// invariant. In practice, the referent is always well-aligned, because the
982    /// alignment of `[u8]` is 1.
983    impl<'a, I> Ptr<'a, [u8], I>
984    where
985        I: Invariants<Validity = Valid>,
986    {
987        /// Attempts to cast `self` to a `U` using the given cast type.
988        ///
989        /// If `U` is a slice DST and pointer metadata (`meta`) is provided,
990        /// then the cast will only succeed if it would produce an object with
991        /// the given metadata.
992        ///
993        /// Returns `None` if the resulting `U` would be invalidly-aligned, if
994        /// no `U` can fit in `self`, or if the provided pointer metadata
995        /// describes an invalid instance of `U`. On success, returns a pointer
996        /// to the largest-possible `U` which fits in `self`.
997        ///
998        /// # Safety
999        ///
1000        /// The caller may assume that this implementation is correct, and may
1001        /// rely on that assumption for the soundness of their code. In
1002        /// particular, the caller may assume that, if `try_cast_into` returns
1003        /// `Some((ptr, remainder))`, then `ptr` and `remainder` refer to
1004        /// non-overlapping byte ranges within `self`, and that `ptr` and
1005        /// `remainder` entirely cover `self`. Finally:
1006        /// - If this is a prefix cast, `ptr` has the same address as `self`.
1007        /// - If this is a suffix cast, `remainder` has the same address as
1008        ///   `self`.
1009        #[inline(always)]
1010        pub(crate) fn try_cast_into<U, R>(
1011            self,
1012            cast_type: CastType,
1013            meta: Option<U::PointerMetadata>,
1014        ) -> Result<
1015            (Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, Ptr<'a, [u8], I>),
1016            CastError<Self, U>,
1017        >
1018        where
1019            R: ReadReason,
1020            I::Aliasing: Reference,
1021            U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>,
1022        {
1023            let (inner, remainder) =
1024                self.as_inner().try_cast_into(cast_type, meta).map_err(|err| {
1025                    err.map_src(|inner|
1026                    // SAFETY: `PtrInner::try_cast_into` promises to return its
1027                    // original argument on error, which was originally produced
1028                    // by `self.as_inner()`, which is guaranteed to satisfy
1029                    // `Ptr`'s invariants.
1030                    unsafe { Ptr::from_inner(inner) })
1031                })?;
1032
1033            // SAFETY:
1034            // 0. Since `U: Read<I::Aliasing, _>`, either:
1035            //    - `I::Aliasing` is `Exclusive`, in which case both `src` and
1036            //      `ptr` conform to `Exclusive`
1037            //    - `I::Aliasing` is `Shared` and `U` is `Immutable` (we already
1038            //      know that `[u8]: Immutable`). In this case, neither `U` nor
1039            //      `[u8]` permit mutation, and so `Shared` aliasing is
1040            //      satisfied.
1041            // 1. `ptr` conforms to the alignment invariant of `Aligned` because
1042            //    it is derived from `try_cast_into`, which promises that the
1043            //    object described by `target` is validly aligned for `U`.
1044            // 2. By trait bound, `self` - and thus `target` - is a bit-valid
1045            //    `[u8]`. All bit-valid `[u8]`s have all of their bytes
1046            //    initialized, so `ptr` conforms to the validity invariant of
1047            //    `Initialized`.
1048            let res = unsafe { Ptr::from_inner(inner) };
1049
1050            // SAFETY:
1051            // 0. `self` and `remainder` both have the type `[u8]`. Thus, they
1052            //    have `UnsafeCell`s at the same locations. Type casting does
1053            //    not affect aliasing.
1054            // 1. `[u8]` has no alignment requirement.
1055            // 2. `self` has validity `Valid` and has type `[u8]`. Since
1056            //    `remainder` references a subset of `self`'s referent, it is
1057            //    also bit-valid.
1058            let remainder = unsafe { Ptr::from_inner(remainder) };
1059
1060            Ok((res, remainder))
1061        }
1062
1063        /// Attempts to cast `self` into a `U`, failing if all of the bytes of
1064        /// `self` cannot be treated as a `U`.
1065        ///
1066        /// In particular, this method fails if `self` is not validly-aligned
1067        /// for `U` or if `self`'s size is not a valid size for `U`.
1068        ///
1069        /// # Safety
1070        ///
1071        /// On success, the caller may assume that the returned pointer
1072        /// references the same byte range as `self`.
1073        #[allow(unused)]
1074        #[inline(always)]
1075        pub(crate) fn try_cast_into_no_leftover<U, R>(
1076            self,
1077            meta: Option<U::PointerMetadata>,
1078        ) -> Result<Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, CastError<Self, U>>
1079        where
1080            I::Aliasing: Reference,
1081            U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>,
1082            R: ReadReason,
1083        {
1084            // TODO(#67): Remove this allow. See NonNulSlicelExt for more
1085            // details.
1086            #[allow(unstable_name_collisions)]
1087            match self.try_cast_into(CastType::Prefix, meta) {
1088                Ok((slf, remainder)) => {
1089                    if remainder.len() == 0 {
1090                        Ok(slf)
1091                    } else {
1092                        // Undo the cast so we can return the original bytes.
1093                        let slf = slf.as_bytes();
1094                        // Restore the initial alignment invariant of `self`.
1095                        //
1096                        // SAFETY: The referent type of `slf` is now equal to
1097                        // that of `self`, but the alignment invariants
1098                        // nominally differ. Since `slf` and `self` refer to the
1099                        // same memory and no actions have been taken that would
1100                        // violate the original invariants on `self`, it is
1101                        // sound to apply the alignment invariant of `self` onto
1102                        // `slf`.
1103                        let slf = unsafe { slf.assume_alignment::<I::Alignment>() };
1104                        let slf = slf.unify_invariants();
1105                        Err(CastError::Size(SizeError::<_, U>::new(slf)))
1106                    }
1107                }
1108                Err(err) => Err(err),
1109            }
1110        }
1111    }
1112
1113    impl<'a, T, I> Ptr<'a, core::cell::UnsafeCell<T>, I>
1114    where
1115        T: 'a + ?Sized,
1116        I: Invariants<Aliasing = Exclusive>,
1117    {
1118        /// Converts this `Ptr` into a pointer to the underlying data.
1119        ///
1120        /// This call borrows the `UnsafeCell` mutably (at compile-time) which
1121        /// guarantees that we possess the only reference.
1122        ///
1123        /// This is like [`UnsafeCell::get_mut`], but for `Ptr`.
1124        ///
1125        /// [`UnsafeCell::get_mut`]: core::cell::UnsafeCell::get_mut
1126        #[must_use]
1127        #[inline(always)]
1128        pub fn get_mut(self) -> Ptr<'a, T, I> {
1129            // SAFETY:
1130            // - The closure uses an `as` cast, which preserves address
1131            //   range and provenance.
1132            // - Aliasing is `Exclusive`, and so we are not required to promise
1133            //   anything about the locations of `UnsafeCell`s.
1134            // - `UnsafeCell<T>` has the same bit validity as `T` [1], and so if
1135            //   `self` has a particular validity invariant, then the same holds
1136            //   of the returned `Ptr`. Technically the term "representation"
1137            //   doesn't guarantee this, but the subsequent sentence in the
1138            //   documentation makes it clear that this is the intention.
1139            //
1140            // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
1141            //
1142            //   `UnsafeCell<T>` has the same in-memory representation as its
1143            //   inner type `T`. A consequence of this guarantee is that it is
1144            //   possible to convert between `T` and `UnsafeCell<T>`.
1145            #[allow(clippy::as_conversions)]
1146            let ptr = unsafe { self.transmute_unchecked(|p| p as *mut T) };
1147
1148            // SAFETY: `UnsafeCell<T>` has the same alignment as `T` [1],
1149            // and so if `self` is guaranteed to be aligned, then so is the
1150            // returned `Ptr`.
1151            //
1152            // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
1153            //
1154            //   `UnsafeCell<T>` has the same in-memory representation as
1155            //   its inner type `T`. A consequence of this guarantee is that
1156            //   it is possible to convert between `T` and `UnsafeCell<T>`.
1157            let ptr = unsafe { ptr.assume_alignment::<I::Alignment>() };
1158            ptr.unify_invariants()
1159        }
1160    }
1161}
1162
1163/// Projections through the referent.
1164mod _project {
1165    use super::*;
1166
1167    impl<'a, T, I> Ptr<'a, T, I>
1168    where
1169        T: 'a + ?Sized,
1170        I: Invariants<Validity = Initialized>,
1171    {
1172        /// Projects a field from `self`.
1173        ///
1174        /// # Safety
1175        ///
1176        /// `project` has the same safety preconditions as
1177        /// `cast_unsized_unchecked`.
1178        #[doc(hidden)]
1179        #[inline]
1180        pub unsafe fn project<U: 'a + ?Sized>(
1181            self,
1182            projector: impl FnOnce(*mut T) -> *mut U,
1183        ) -> Ptr<'a, U, (I::Aliasing, Unaligned, Initialized)> {
1184            // TODO(#1122): If `cast_unsized` were able to reason that, when
1185            // casting from an `Initialized` pointer, the result is another
1186            // `Initialized` pointer, we could remove this method entirely.
1187
1188            // SAFETY: This method has the same safety preconditions as
1189            // `cast_unsized_unchecked`.
1190            let ptr = unsafe { self.cast_unsized_unchecked(projector) };
1191
1192            // SAFETY: If all of the bytes of `self` are initialized (as
1193            // promised by `I: Invariants<Validity = Initialized>`), then any
1194            // subset of those bytes are also all initialized.
1195            unsafe { ptr.assume_validity::<Initialized>() }
1196        }
1197    }
1198
1199    impl<'a, T, I> Ptr<'a, [T], I>
1200    where
1201        T: 'a,
1202        I: Invariants,
1203    {
1204        /// The number of slice elements in the object referenced by `self`.
1205        ///
1206        /// # Safety
1207        ///
1208        /// Unsafe code my rely on `len` satisfying the above contract.
1209        pub(crate) fn len(&self) -> usize {
1210            self.as_inner().len()
1211        }
1212    }
1213
1214    impl<'a, T, I> Ptr<'a, [T], I>
1215    where
1216        T: 'a,
1217        I: Invariants,
1218        I::Aliasing: Reference,
1219    {
1220        /// Iteratively projects the elements `Ptr<T>` from `Ptr<[T]>`.
1221        pub(crate) fn iter(&self) -> impl Iterator<Item = Ptr<'a, T, I>> {
1222            // SAFETY:
1223            // 0. `elem` conforms to the aliasing invariant of `I::Aliasing`
1224            //    because projection does not impact the aliasing invariant.
1225            // 1. `elem`, conditionally, conforms to the validity invariant of
1226            //    `I::Alignment`. If `elem` is projected from data well-aligned
1227            //    for `[T]`, `elem` will be valid for `T`.
1228            // 2. `elem`, conditionally, conforms to the validity invariant of
1229            //    `I::Validity`. If `elem` is projected from data valid for
1230            //    `[T]`, `elem` will be valid for `T`.
1231            self.as_inner().iter().map(|elem| unsafe { Ptr::from_inner(elem) })
1232        }
1233    }
1234}
1235
1236#[cfg(test)]
1237mod tests {
1238    use core::mem::{self, MaybeUninit};
1239
1240    use super::*;
1241    #[allow(unused)] // Needed on our MSRV, but considered unused on later toolchains.
1242    use crate::util::AsAddress;
1243    use crate::{pointer::BecauseImmutable, util::testutil::AU64, FromBytes, Immutable};
1244
1245    mod test_ptr_try_cast_into_soundness {
1246        use super::*;
1247
1248        // This test is designed so that if `Ptr::try_cast_into_xxx` are
1249        // buggy, it will manifest as unsoundness that Miri can detect.
1250
1251        // - If `size_of::<T>() == 0`, `N == 4`
1252        // - Else, `N == 4 * size_of::<T>()`
1253        //
1254        // Each test will be run for each metadata in `metas`.
1255        fn test<T, I, const N: usize>(metas: I)
1256        where
1257            T: ?Sized + KnownLayout + Immutable + FromBytes,
1258            I: IntoIterator<Item = Option<T::PointerMetadata>> + Clone,
1259        {
1260            let mut bytes = [MaybeUninit::<u8>::uninit(); N];
1261            let initialized = [MaybeUninit::new(0u8); N];
1262            for start in 0..=bytes.len() {
1263                for end in start..=bytes.len() {
1264                    // Set all bytes to uninitialized other than those in
1265                    // the range we're going to pass to `try_cast_from`.
1266                    // This allows Miri to detect out-of-bounds reads
1267                    // because they read uninitialized memory. Without this,
1268                    // some out-of-bounds reads would still be in-bounds of
1269                    // `bytes`, and so might spuriously be accepted.
1270                    bytes = [MaybeUninit::<u8>::uninit(); N];
1271                    let bytes = &mut bytes[start..end];
1272                    // Initialize only the byte range we're going to pass to
1273                    // `try_cast_from`.
1274                    bytes.copy_from_slice(&initialized[start..end]);
1275
1276                    let bytes = {
1277                        let bytes: *const [MaybeUninit<u8>] = bytes;
1278                        #[allow(clippy::as_conversions)]
1279                        let bytes = bytes as *const [u8];
1280                        // SAFETY: We just initialized these bytes to valid
1281                        // `u8`s.
1282                        unsafe { &*bytes }
1283                    };
1284
1285                    // SAFETY: The bytes in `slf` must be initialized.
1286                    unsafe fn validate_and_get_len<T: ?Sized + KnownLayout + FromBytes>(
1287                        slf: Ptr<'_, T, (Shared, Aligned, Initialized)>,
1288                    ) -> usize {
1289                        let t = slf.bikeshed_recall_valid().as_ref();
1290
1291                        let bytes = {
1292                            let len = mem::size_of_val(t);
1293                            let t: *const T = t;
1294                            // SAFETY:
1295                            // - We know `t`'s bytes are all initialized
1296                            //   because we just read it from `slf`, which
1297                            //   points to an initialized range of bytes. If
1298                            //   there's a bug and this doesn't hold, then
1299                            //   that's exactly what we're hoping Miri will
1300                            //   catch!
1301                            // - Since `T: FromBytes`, `T` doesn't contain
1302                            //   any `UnsafeCell`s, so it's okay for `t: T`
1303                            //   and a `&[u8]` to the same memory to be
1304                            //   alive concurrently.
1305                            unsafe { core::slice::from_raw_parts(t.cast::<u8>(), len) }
1306                        };
1307
1308                        // This assertion ensures that `t`'s bytes are read
1309                        // and compared to another value, which in turn
1310                        // ensures that Miri gets a chance to notice if any
1311                        // of `t`'s bytes are uninitialized, which they
1312                        // shouldn't be (see the comment above).
1313                        assert_eq!(bytes, vec![0u8; bytes.len()]);
1314
1315                        mem::size_of_val(t)
1316                    }
1317
1318                    for meta in metas.clone().into_iter() {
1319                        for cast_type in [CastType::Prefix, CastType::Suffix] {
1320                            if let Ok((slf, remaining)) = Ptr::from_ref(bytes)
1321                                .try_cast_into::<T, BecauseImmutable>(cast_type, meta)
1322                            {
1323                                // SAFETY: All bytes in `bytes` have been
1324                                // initialized.
1325                                let len = unsafe { validate_and_get_len(slf) };
1326                                assert_eq!(remaining.len(), bytes.len() - len);
1327                                #[allow(unstable_name_collisions)]
1328                                let bytes_addr = bytes.as_ptr().addr();
1329                                #[allow(unstable_name_collisions)]
1330                                let remaining_addr =
1331                                    remaining.as_inner().as_non_null().as_ptr().addr();
1332                                match cast_type {
1333                                    CastType::Prefix => {
1334                                        assert_eq!(remaining_addr, bytes_addr + len)
1335                                    }
1336                                    CastType::Suffix => assert_eq!(remaining_addr, bytes_addr),
1337                                }
1338
1339                                if let Some(want) = meta {
1340                                    let got = KnownLayout::pointer_to_metadata(
1341                                        slf.as_inner().as_non_null().as_ptr(),
1342                                    );
1343                                    assert_eq!(got, want);
1344                                }
1345                            }
1346                        }
1347
1348                        if let Ok(slf) = Ptr::from_ref(bytes)
1349                            .try_cast_into_no_leftover::<T, BecauseImmutable>(meta)
1350                        {
1351                            // SAFETY: All bytes in `bytes` have been
1352                            // initialized.
1353                            let len = unsafe { validate_and_get_len(slf) };
1354                            assert_eq!(len, bytes.len());
1355
1356                            if let Some(want) = meta {
1357                                let got = KnownLayout::pointer_to_metadata(
1358                                    slf.as_inner().as_non_null().as_ptr(),
1359                                );
1360                                assert_eq!(got, want);
1361                            }
1362                        }
1363                    }
1364                }
1365            }
1366        }
1367
1368        #[derive(FromBytes, KnownLayout, Immutable)]
1369        #[repr(C)]
1370        struct SliceDst<T> {
1371            a: u8,
1372            trailing: [T],
1373        }
1374
1375        // Each test case becomes its own `#[test]` function. We do this because
1376        // this test in particular takes far, far longer to execute under Miri
1377        // than all of our other tests combined. Previously, we had these
1378        // execute sequentially in a single test function. We run Miri tests in
1379        // parallel in CI, but this test being sequential meant that most of
1380        // that parallelism was wasted, as all other tests would finish in a
1381        // fraction of the total execution time, leaving this test to execute on
1382        // a single thread for the remainder of the test. By putting each test
1383        // case in its own function, we permit better use of available
1384        // parallelism.
1385        macro_rules! test {
1386            ($test_name:ident: $ty:ty) => {
1387                #[test]
1388                #[allow(non_snake_case)]
1389                fn $test_name() {
1390                    const S: usize = core::mem::size_of::<$ty>();
1391                    const N: usize = if S == 0 { 4 } else { S * 4 };
1392                    test::<$ty, _, N>([None]);
1393
1394                    // If `$ty` is a ZST, then we can't pass `None` as the
1395                    // pointer metadata, or else computing the correct trailing
1396                    // slice length will panic.
1397                    if S == 0 {
1398                        test::<[$ty], _, N>([Some(0), Some(1), Some(2), Some(3)]);
1399                        test::<SliceDst<$ty>, _, N>([Some(0), Some(1), Some(2), Some(3)]);
1400                    } else {
1401                        test::<[$ty], _, N>([None, Some(0), Some(1), Some(2), Some(3)]);
1402                        test::<SliceDst<$ty>, _, N>([None, Some(0), Some(1), Some(2), Some(3)]);
1403                    }
1404                }
1405            };
1406            ($ty:ident) => {
1407                test!($ty: $ty);
1408            };
1409            ($($ty:ident),*) => { $(test!($ty);)* }
1410        }
1411
1412        test!(empty_tuple: ());
1413        test!(u8, u16, u32, u64, u128, usize, AU64);
1414        test!(i8, i16, i32, i64, i128, isize);
1415        test!(f32, f64);
1416    }
1417
1418    #[test]
1419    fn test_try_cast_into_explicit_count() {
1420        macro_rules! test {
1421            ($ty:ty, $bytes:expr, $elems:expr, $expect:expr) => {{
1422                let bytes = [0u8; $bytes];
1423                let ptr = Ptr::from_ref(&bytes[..]);
1424                let res =
1425                    ptr.try_cast_into::<$ty, BecauseImmutable>(CastType::Prefix, Some($elems));
1426                if let Some(expect) = $expect {
1427                    let (ptr, _) = res.unwrap();
1428                    assert_eq!(
1429                        KnownLayout::pointer_to_metadata(ptr.as_inner().as_non_null().as_ptr()),
1430                        expect
1431                    );
1432                } else {
1433                    let _ = res.unwrap_err();
1434                }
1435            }};
1436        }
1437
1438        #[derive(KnownLayout, Immutable)]
1439        #[repr(C)]
1440        struct ZstDst {
1441            u: [u8; 8],
1442            slc: [()],
1443        }
1444
1445        test!(ZstDst, 8, 0, Some(0));
1446        test!(ZstDst, 7, 0, None);
1447
1448        test!(ZstDst, 8, usize::MAX, Some(usize::MAX));
1449        test!(ZstDst, 7, usize::MAX, None);
1450
1451        #[derive(KnownLayout, Immutable)]
1452        #[repr(C)]
1453        struct Dst {
1454            u: [u8; 8],
1455            slc: [u8],
1456        }
1457
1458        test!(Dst, 8, 0, Some(0));
1459        test!(Dst, 7, 0, None);
1460
1461        test!(Dst, 9, 1, Some(1));
1462        test!(Dst, 8, 1, None);
1463
1464        // If we didn't properly check for overflow, this would cause the
1465        // metadata to overflow to 0, and thus the cast would spuriously
1466        // succeed.
1467        test!(Dst, 8, usize::MAX - 8 + 1, None);
1468    }
1469}