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::ptr::NonNull;
10
11use crate::{util::AsAddress, CastType, KnownLayout};
12
13/// Module used to gate access to [`Ptr`]'s fields.
14mod def {
15 #[cfg(doc)]
16 use super::invariant;
17 use super::Invariants;
18 use core::{marker::PhantomData, ptr::NonNull};
19
20 /// A raw pointer with more restrictions.
21 ///
22 /// `Ptr<T>` is similar to [`NonNull<T>`], but it is more restrictive in the
23 /// following ways (note that these requirements only hold of non-zero-sized
24 /// referents):
25 /// - It must derive from a valid allocation.
26 /// - It must reference a byte range which is contained inside the
27 /// allocation from which it derives.
28 /// - As a consequence, the byte range it references must have a size
29 /// which does not overflow `isize`.
30 ///
31 /// Depending on how `Ptr` is parameterized, it may have additional
32 /// invariants:
33 /// - `ptr` conforms to the aliasing invariant of
34 /// [`I::Aliasing`](invariant::Aliasing).
35 /// - `ptr` conforms to the alignment invariant of
36 /// [`I::Alignment`](invariant::Alignment).
37 /// - `ptr` conforms to the validity invariant of
38 /// [`I::Validity`](invariant::Validity).
39 ///
40 /// `Ptr<'a, T>` is [covariant] in `'a` and `T`.
41 ///
42 /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
43 pub struct Ptr<'a, T, I>
44 where
45 T: 'a + ?Sized,
46 I: Invariants,
47 {
48 /// # Invariants
49 ///
50 /// 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from
51 /// some valid Rust allocation, `A`.
52 /// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
53 /// provenance for `A`.
54 /// 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a
55 /// byte range which is entirely contained in `A`.
56 /// 3. `ptr` addresses a byte range whose length fits in an `isize`.
57 /// 4. `ptr` addresses a byte range which does not wrap around the
58 /// address space.
59 /// 5. If `ptr`'s referent is not zero sized,`A` is guaranteed to live
60 /// for at least `'a`.
61 /// 6. `T: 'a`.
62 /// 7. `ptr` conforms to the aliasing invariant of
63 /// [`I::Aliasing`](invariant::Aliasing).
64 /// 8. `ptr` conforms to the alignment invariant of
65 /// [`I::Alignment`](invariant::Alignment).
66 /// 9. `ptr` conforms to the validity invariant of
67 /// [`I::Validity`](invariant::Validity).
68 // SAFETY: `NonNull<T>` is covariant over `T` [1].
69 //
70 // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html
71 ptr: NonNull<T>,
72 // SAFETY: `&'a ()` is covariant over `'a` [1].
73 //
74 // [1]: https://doc.rust-lang.org/reference/subtyping.html#variance
75 _invariants: PhantomData<&'a I>,
76 }
77
78 impl<'a, T, I> Ptr<'a, T, I>
79 where
80 T: 'a + ?Sized,
81 I: Invariants,
82 {
83 /// Constructs a `Ptr` from a [`NonNull`].
84 ///
85 /// # Safety
86 ///
87 /// The caller promises that:
88 ///
89 /// 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from
90 /// some valid Rust allocation, `A`.
91 /// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
92 /// provenance for `A`.
93 /// 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a
94 /// byte range which is entirely contained in `A`.
95 /// 3. `ptr` addresses a byte range whose length fits in an `isize`.
96 /// 4. `ptr` addresses a byte range which does not wrap around the
97 /// address space.
98 /// 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to
99 /// live for at least `'a`.
100 /// 6. `ptr` conforms to the aliasing invariant of
101 /// [`I::Aliasing`](invariant::Aliasing).
102 /// 7. `ptr` conforms to the alignment invariant of
103 /// [`I::Alignment`](invariant::Alignment).
104 /// 8. `ptr` conforms to the validity invariant of
105 /// [`I::Validity`](invariant::Validity).
106 pub(super) unsafe fn new(ptr: NonNull<T>) -> Ptr<'a, T, I> {
107 // SAFETY: The caller has promised to satisfy all safety invariants
108 // of `Ptr`.
109 Self { ptr, _invariants: PhantomData }
110 }
111
112 /// Converts this `Ptr<T>` to a [`NonNull<T>`].
113 ///
114 /// Note that this method does not consume `self`. The caller should
115 /// watch out for `unsafe` code which uses the returned `NonNull` in a
116 /// way that violates the safety invariants of `self`.
117 pub(crate) fn as_non_null(&self) -> NonNull<T> {
118 self.ptr
119 }
120 }
121}
122
123#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.
124pub use def::Ptr;
125
126/// Used to define the system of [invariants][invariant] of `Ptr`.
127macro_rules! define_system {
128 ($(#[$system_attr:meta])* $system:ident {
129 $($(#[$set_attr:meta])* $set:ident {
130 $( $(#[$elem_attr:meta])* $elem:ident $(< $($stronger_elem:ident)|*)?,)*
131 })*
132 }) => {
133 /// No requirement - any invariant is allowed.
134 #[allow(missing_copy_implementations, missing_debug_implementations)]
135 pub enum Any {}
136
137 /// `Self` imposes a requirement at least as strict as `I`.
138 pub trait AtLeast<I> {}
139
140 mod sealed {
141 pub trait Sealed {}
142
143 impl<$($set,)*> Sealed for ($($set,)*)
144 where
145 $($set: super::$set,)*
146 {}
147
148 impl Sealed for super::Any {}
149
150 $($(
151 impl Sealed for super::$elem {}
152 )*)*
153 }
154
155 $(#[$system_attr])*
156 ///
157 #[doc = concat!(
158 stringify!($system),
159 " are encoded as tuples of (",
160 )]
161 $(#[doc = concat!(
162 "[`",
163 stringify!($set),
164 "`],"
165 )])*
166 #[doc = concat!(
167 ").",
168 )]
169 /// This trait is implemented for such tuples, and can be used to
170 /// project out the components of these tuples via its associated types.
171 pub trait $system: sealed::Sealed {
172 $(
173 $(#[$set_attr])*
174 type $set: $set;
175 )*
176 }
177
178 impl<$($set,)*> $system for ($($set,)*)
179 where
180 $($set: self::$set,)*
181 {
182 $(type $set = $set;)*
183 }
184
185 $(
186 $(#[$set_attr])*
187 pub trait $set: 'static + sealed::Sealed {
188 // This only exists for use in
189 // `into_exclusive_or_post_monomorphization_error`.
190 #[doc(hidden)]
191 const NAME: &'static str;
192 }
193
194 impl $set for Any {
195 const NAME: &'static str = stringify!(Any);
196 }
197
198 $(
199 $(#[$elem_attr])*
200 #[allow(missing_copy_implementations, missing_debug_implementations)]
201 pub enum $elem {}
202
203 $(#[$elem_attr])*
204 impl $set for $elem {
205 const NAME: &'static str = stringify!($elem);
206 }
207 )*
208 )*
209
210 $($(
211 impl AtLeast<Any> for $elem {}
212 impl AtLeast<$elem> for $elem {}
213
214 $($(impl AtLeast<$elem> for $stronger_elem {})*)?
215 )*)*
216 };
217}
218
219/// The parameterized invariants of a [`Ptr`].
220///
221/// Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`])
222/// triples implementing the [`Invariants`] trait.
223#[doc(hidden)]
224pub mod invariant {
225 define_system! {
226 /// The invariants of a [`Ptr`][super::Ptr].
227 Invariants {
228 /// The aliasing invariant of a [`Ptr`][super::Ptr].
229 Aliasing {
230 /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`.
231 ///
232 /// The referent of a shared-aliased `Ptr` may be concurrently
233 /// referenced by any number of shared-aliased `Ptr` or `&T`
234 /// references, and may not be concurrently referenced by any
235 /// exclusively-aliased `Ptr`s or `&mut T` references. The
236 /// referent must not be mutated, except via [`UnsafeCell`]s.
237 ///
238 /// [`UnsafeCell`]: core::cell::UnsafeCell
239 Shared < Exclusive,
240
241 /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut
242 /// T`.
243 ///
244 /// The referent of an exclusively-aliased `Ptr` may not be
245 /// concurrently referenced by any other `Ptr`s or references,
246 /// and may not be accessed (read or written) other than via
247 /// this `Ptr`.
248 Exclusive,
249 }
250
251 /// The alignment invariant of a [`Ptr`][super::Ptr].
252 Alignment {
253 /// The referent is aligned: for `Ptr<T>`, the referent's
254 /// address is a multiple of the `T`'s alignment.
255 Aligned,
256 }
257
258 /// The validity invariant of a [`Ptr`][super::Ptr].
259 Validity {
260 /// The byte ranges initialized in `T` are also initialized in
261 /// the referent.
262 ///
263 /// Formally: uninitialized bytes may only be present in
264 /// `Ptr<T>`'s referent where they are guaranteed to be present
265 /// in `T`. This is a dynamic property: if, at a particular byte
266 /// offset, a valid enum discriminant is set, the subsequent
267 /// bytes may only have uninitialized bytes as specificed by the
268 /// corresponding enum.
269 ///
270 /// Formally, given `len = size_of_val_raw(ptr)`, at every byte
271 /// offset, `b`, in the range `[0, len)`:
272 /// - If, in any instance `t: T` of length `len`, the byte at
273 /// offset `b` in `t` is initialized, then the byte at offset
274 /// `b` within `*ptr` must be initialized.
275 /// - Let `c` be the contents of the byte range `[0, b)` in
276 /// `*ptr`. Let `S` be the subset of valid instances of `T` of
277 /// length `len` which contain `c` in the offset range `[0,
278 /// b)`. If, in any instance of `t: T` in `S`, the byte at
279 /// offset `b` in `t` is initialized, then the byte at offset
280 /// `b` in `*ptr` must be initialized.
281 ///
282 /// Pragmatically, this means that if `*ptr` is guaranteed to
283 /// contain an enum type at a particular offset, and the enum
284 /// discriminant stored in `*ptr` corresponds to a valid
285 /// variant of that enum type, then it is guaranteed that the
286 /// appropriate bytes of `*ptr` are initialized as defined by
287 /// that variant's bit validity (although note that the
288 /// variant may contain another enum type, in which case the
289 /// same rules apply depending on the state of its
290 /// discriminant, and so on recursively).
291 AsInitialized < Initialized | Valid,
292
293 /// The byte ranges in the referent are fully initialized. In
294 /// other words, if the referent is `N` bytes long, then it
295 /// contains a bit-valid `[u8; N]`.
296 Initialized,
297
298 /// The referent is bit-valid for `T`.
299 Valid,
300 }
301 }
302 }
303}
304
305pub(crate) use invariant::*;
306
307/// External trait implementations on [`Ptr`].
308mod _external {
309 use super::*;
310 use core::fmt::{Debug, Formatter};
311
312 /// SAFETY: Shared pointers are safely `Copy`. We do not implement `Copy`
313 /// for exclusive pointers, since at most one may exist at a time. `Ptr`'s
314 /// other invariants are unaffected by the number of references that exist
315 /// to `Ptr`'s referent.
316 impl<'a, T, I> Copy for Ptr<'a, T, I>
317 where
318 T: 'a + ?Sized,
319 I: Invariants,
320 Shared: AtLeast<I::Aliasing>,
321 {
322 }
323
324 /// SAFETY: Shared pointers are safely `Clone`. We do not implement `Clone`
325 /// for exclusive pointers, since at most one may exist at a time. `Ptr`'s
326 /// other invariants are unaffected by the number of references that exist
327 /// to `Ptr`'s referent.
328 impl<'a, T, I> Clone for Ptr<'a, T, I>
329 where
330 T: 'a + ?Sized,
331 I: Invariants,
332 Shared: AtLeast<I::Aliasing>,
333 {
334 #[inline]
335 fn clone(&self) -> Self {
336 *self
337 }
338 }
339
340 impl<'a, T, I> Debug for Ptr<'a, T, I>
341 where
342 T: 'a + ?Sized,
343 I: Invariants,
344 {
345 #[inline]
346 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
347 self.as_non_null().fmt(f)
348 }
349 }
350}
351
352/// Methods for converting to and from `Ptr` and Rust's safe reference types.
353mod _conversions {
354 use super::*;
355 use crate::util::{AlignmentVariance, Covariant, TransparentWrapper, ValidityVariance};
356
357 /// `&'a T` → `Ptr<'a, T>`
358 impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)>
359 where
360 T: 'a + ?Sized,
361 {
362 /// Constructs a `Ptr` from a shared reference.
363 #[doc(hidden)]
364 #[inline]
365 pub fn from_ref(ptr: &'a T) -> Self {
366 let ptr = NonNull::from(ptr);
367 // SAFETY:
368 // 0. If `ptr`'s referent is not zero sized, then `ptr`, by
369 // invariant on `&'a T`, is derived from some valid Rust
370 // allocation, `A`.
371 // 1. If `ptr`'s referent is not zero sized, then `ptr`, by
372 // invariant on `&'a T`, has valid provenance for `A`.
373 // 2. If `ptr`'s referent is not zero sized, then `ptr`, by
374 // invariant on `&'a T`, addresses a byte range which is entirely
375 // contained in `A`.
376 // 3. `ptr`, by invariant on `&'a T`, addresses a byte range whose
377 // length fits in an `isize`.
378 // 4. `ptr`, by invariant on `&'a T`, addresses a byte range which
379 // does not wrap around the address space.
380 // 5. If `ptr`'s referent is not zero sized, then `A`, by invariant
381 // on `&'a T`, is guaranteed to live for at least `'a`.
382 // 6. `T: 'a`.
383 // 7. `ptr`, by invariant on `&'a T`, conforms to the aliasing
384 // invariant of `Shared`.
385 // 8. `ptr`, by invariant on `&'a T`, conforms to the alignment
386 // invariant of `Aligned`.
387 // 9. `ptr`, by invariant on `&'a T`, conforms to the validity
388 // invariant of `Valid`.
389 unsafe { Self::new(ptr) }
390 }
391 }
392
393 /// `&'a mut T` → `Ptr<'a, T>`
394 impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)>
395 where
396 T: 'a + ?Sized,
397 {
398 /// Constructs a `Ptr` from an exclusive reference.
399 #[inline]
400 pub(crate) fn from_mut(ptr: &'a mut T) -> Self {
401 let ptr = NonNull::from(ptr);
402 // SAFETY:
403 // 0. If `ptr`'s referent is not zero sized, then `ptr`, by
404 // invariant on `&'a mut T`, is derived from some valid Rust
405 // allocation, `A`.
406 // 1. If `ptr`'s referent is not zero sized, then `ptr`, by
407 // invariant on `&'a mut T`, has valid provenance for `A`.
408 // 2. If `ptr`'s referent is not zero sized, then `ptr`, by
409 // invariant on `&'a mut T`, addresses a byte range which is
410 // entirely contained in `A`.
411 // 3. `ptr`, by invariant on `&'a mut T`, addresses a byte range
412 // whose length fits in an `isize`.
413 // 4. `ptr`, by invariant on `&'a mut T`, addresses a byte range
414 // which does not wrap around the address space.
415 // 5. If `ptr`'s referent is not zero sized, then `A`, by invariant
416 // on `&'a mut T`, is guaranteed to live for at least `'a`.
417 // 6. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing
418 // invariant of `Exclusive`.
419 // 7. `ptr`, by invariant on `&'a mut T`, conforms to the alignment
420 // invariant of `Aligned`.
421 // 8. `ptr`, by invariant on `&'a mut T`, conforms to the validity
422 // invariant of `Valid`.
423 unsafe { Self::new(ptr) }
424 }
425 }
426
427 /// `Ptr<'a, T>` → `&'a T`
428 impl<'a, T, I> Ptr<'a, T, I>
429 where
430 T: 'a + ?Sized,
431 I: Invariants<Alignment = Aligned, Validity = Valid>,
432 I::Aliasing: AtLeast<Shared>,
433 {
434 /// Converts `self` to a shared reference.
435 // This consumes `self`, not `&self`, because `self` is, logically, a
436 // pointer. For `I::Aliasing = invariant::Shared`, `Self: Copy`, and so
437 // this doesn't prevent the caller from still using the pointer after
438 // calling `as_ref`.
439 #[allow(clippy::wrong_self_convention)]
440 pub(crate) fn as_ref(self) -> &'a T {
441 let raw = self.as_non_null();
442 // SAFETY: This invocation of `NonNull::as_ref` satisfies its
443 // documented safety preconditions:
444 //
445 // 1. The pointer is properly aligned. This is ensured by-contract
446 // on `Ptr`, because the `I::Alignment` is `Aligned`.
447 //
448 // 2. If the pointer's referent is not zero-sized, then the pointer
449 // must be “dereferenceable” in the sense defined in the module
450 // documentation; i.e.:
451 //
452 // > The memory range of the given size starting at the pointer
453 // > must all be within the bounds of a single allocated object.
454 // > [2]
455 //
456 // This is ensured by contract on all `Ptr`s.
457 //
458 // 3. The pointer must point to an initialized instance of `T`. This
459 // is ensured by-contract on `Ptr`, because the `I::Validity` is
460 // `Valid`.
461 //
462 // 4. You must enforce Rust’s aliasing rules. This is ensured by
463 // contract on `Ptr`, because the `I::Aliasing` is
464 // `AtLeast<Shared>`. Either it is `Shared` or `Exclusive`. If it
465 // is `Shared`, other references may not mutate the referent
466 // outside of `UnsafeCell`s.
467 //
468 // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ref
469 // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety
470 unsafe { raw.as_ref() }
471 }
472 }
473
474 impl<'a, T, I> Ptr<'a, T, I>
475 where
476 T: 'a + ?Sized,
477 I: Invariants,
478 I::Aliasing: AtLeast<Shared>,
479 {
480 /// Reborrows `self`, producing another `Ptr`.
481 ///
482 /// Since `self` is borrowed immutably, this prevents any mutable
483 /// methods from being called on `self` as long as the returned `Ptr`
484 /// exists.
485 #[doc(hidden)]
486 #[inline]
487 #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below.
488 pub fn reborrow<'b>(&'b mut self) -> Ptr<'b, T, I>
489 where
490 'a: 'b,
491 {
492 // SAFETY: The following all hold by invariant on `self`, and thus
493 // hold of `ptr = self.as_non_null()`:
494 // 0. If `ptr`'s referent is not zero sized, then `ptr` is derived
495 // from some valid Rust allocation, `A`.
496 // 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
497 // provenance for `A`.
498 // 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a
499 // byte range which is entirely contained in `A`.
500 // 3. `ptr` addresses a byte range whose length fits in an `isize`.
501 // 4. `ptr` addresses a byte range which does not wrap around the
502 // address space.
503 // 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed
504 // to live for at least `'a`.
505 // 6. SEE BELOW.
506 // 7. `ptr` conforms to the alignment invariant of
507 // [`I::Alignment`](invariant::Alignment).
508 // 8. `ptr` conforms to the validity invariant of
509 // [`I::Validity`](invariant::Validity).
510 //
511 // For aliasing (6 above), since `I::Aliasing: AtLeast<Shared>`,
512 // there are two cases for `I::Aliasing`:
513 // - For `invariant::Shared`: `'a` outlives `'b`, and so the
514 // returned `Ptr` does not permit accessing the referent any
515 // longer than is possible via `self`. For shared aliasing, it is
516 // sound for multiple `Ptr`s to exist simultaneously which
517 // reference the same memory, so creating a new one is not
518 // problematic.
519 // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we
520 // return a `Ptr` with lifetime `'b`, `self` is inaccessible to
521 // the caller for the lifetime `'b` - in other words, `self` is
522 // inaccessible to the caller as long as the returned `Ptr`
523 // exists. Since `self` is an exclusive `Ptr`, no other live
524 // references or `Ptr`s may exist which refer to the same memory
525 // while `self` is live. Thus, as long as the returned `Ptr`
526 // exists, no other references or `Ptr`s which refer to the same
527 // memory may be live.
528 unsafe { Ptr::new(self.as_non_null()) }
529 }
530 }
531
532 /// `Ptr<'a, T>` → `&'a mut T`
533 impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)>
534 where
535 T: 'a + ?Sized,
536 {
537 /// Converts `self` to a mutable reference.
538 #[allow(clippy::wrong_self_convention)]
539 pub(crate) fn as_mut(self) -> &'a mut T {
540 let mut raw = self.as_non_null();
541 // SAFETY: This invocation of `NonNull::as_mut` satisfies its
542 // documented safety preconditions:
543 //
544 // 1. The pointer is properly aligned. This is ensured by-contract
545 // on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`.
546 //
547 // 2. If the pointer's referent is not zero-sized, then the pointer
548 // must be “dereferenceable” in the sense defined in the module
549 // documentation; i.e.:
550 //
551 // > The memory range of the given size starting at the pointer
552 // > must all be within the bounds of a single allocated object.
553 // > [2]
554 //
555 // This is ensured by contract on all `Ptr`s.
556 //
557 // 3. The pointer must point to an initialized instance of `T`. This
558 // is ensured by-contract on `Ptr`, because the
559 // `VALIDITY_INVARIANT` is `Valid`.
560 //
561 // 4. You must enforce Rust’s aliasing rules. This is ensured by
562 // contract on `Ptr`, because the `ALIASING_INVARIANT` is
563 // `Exclusive`.
564 //
565 // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut
566 // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety
567 unsafe { raw.as_mut() }
568 }
569 }
570
571 /// `Ptr<'a, T = Wrapper<U>>` → `Ptr<'a, U>`
572 impl<'a, T, I> Ptr<'a, T, I>
573 where
574 T: 'a + TransparentWrapper<I, UnsafeCellVariance = Covariant> + ?Sized,
575 I: Invariants,
576 {
577 /// Converts `self` to a transparent wrapper type into a `Ptr` to the
578 /// wrapped inner type.
579 pub(crate) fn transparent_wrapper_into_inner(
580 self,
581 ) -> Ptr<
582 'a,
583 T::Inner,
584 (
585 I::Aliasing,
586 <T::AlignmentVariance as AlignmentVariance<I::Alignment>>::Applied,
587 <T::ValidityVariance as ValidityVariance<I::Validity>>::Applied,
588 ),
589 > {
590 // SAFETY:
591 // - By invariant on `TransparentWrapper::cast_into_inner`:
592 // - This cast preserves address and referent size, and thus the
593 // returned pointer addresses the same bytes as `p`
594 // - This cast preserves provenance
595 // - By invariant on `TransparentWrapper<UnsafeCellVariance =
596 // Covariant>`, `T` and `T::Inner` have `UnsafeCell`s at the same
597 // byte ranges. Since `p` and the returned pointer address the
598 // same byte range, they refer to `UnsafeCell`s at the same byte
599 // ranges.
600 let c = unsafe { self.cast_unsized(|p| T::cast_into_inner(p)) };
601 // SAFETY: By invariant on `TransparentWrapper`, since `self`
602 // satisfies the alignment invariant `I::Alignment`, `c` (of type
603 // `T::Inner`) satisfies the given "applied" alignment invariant.
604 let c = unsafe {
605 c.assume_alignment::<<T::AlignmentVariance as AlignmentVariance<I::Alignment>>::Applied>()
606 };
607 // SAFETY: By invariant on `TransparentWrapper`, since `self`
608 // satisfies the validity invariant `I::Validity`, `c` (of type
609 // `T::Inner`) satisfies the given "applied" validity invariant.
610 let c = unsafe {
611 c.assume_validity::<<T::ValidityVariance as ValidityVariance<I::Validity>>::Applied>()
612 };
613 c
614 }
615 }
616
617 /// `Ptr<'a, T, (_, _, _)>` → `Ptr<'a, Unalign<T>, (_, Aligned, _)>`
618 impl<'a, T, I> Ptr<'a, T, I>
619 where
620 I: Invariants,
621 {
622 /// Converts a `Ptr` an unaligned `T` into a `Ptr` to an aligned
623 /// `Unalign<T>`.
624 pub(crate) fn into_unalign(
625 self,
626 ) -> Ptr<'a, crate::Unalign<T>, (I::Aliasing, Aligned, I::Validity)> {
627 // SAFETY:
628 // - This cast preserves provenance.
629 // - This cast preserves address. `Unalign<T>` promises to have the
630 // same size as `T`, and so the cast returns a pointer addressing
631 // the same byte range as `p`.
632 // - By the same argument, the returned pointer refers to
633 // `UnsafeCell`s at the same locations as `p`.
634 let ptr = unsafe {
635 #[allow(clippy::as_conversions)]
636 self.cast_unsized(|p: *mut T| p as *mut crate::Unalign<T>)
637 };
638 // SAFETY: `Unalign<T>` promises to have the same bit validity as
639 // `T`.
640 let ptr = unsafe { ptr.assume_validity::<I::Validity>() };
641 // SAFETY: `Unalign<T>` promises to have alignment 1, and so it is
642 // trivially aligned.
643 let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
644 ptr
645 }
646 }
647}
648
649/// State transitions between invariants.
650mod _transitions {
651 use super::*;
652 use crate::{AlignmentError, TryFromBytes, ValidityError};
653
654 impl<'a, T, I> Ptr<'a, T, I>
655 where
656 T: 'a + ?Sized,
657 I: Invariants,
658 {
659 /// Returns a `Ptr` with [`Exclusive`] aliasing if `self` already has
660 /// `Exclusive` aliasing.
661 ///
662 /// This allows code which is generic over aliasing to down-cast to a
663 /// concrete aliasing.
664 ///
665 /// [`Exclusive`]: invariant::Exclusive
666 #[inline]
667 pub(crate) fn into_exclusive_or_post_monomorphization_error(
668 self,
669 ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> {
670 trait AliasingExt: Aliasing {
671 const IS_EXCLUSIVE: bool;
672 }
673
674 impl<A: Aliasing> AliasingExt for A {
675 const IS_EXCLUSIVE: bool = {
676 let is_exclusive =
677 strs_are_equal(<Self as Aliasing>::NAME, <Exclusive as Aliasing>::NAME);
678 const_assert!(is_exclusive);
679 true
680 };
681 }
682
683 const fn strs_are_equal(s: &str, t: &str) -> bool {
684 if s.len() != t.len() {
685 return false;
686 }
687
688 let s = s.as_bytes();
689 let t = t.as_bytes();
690
691 let mut i = 0;
692 #[allow(clippy::arithmetic_side_effects)]
693 while i < s.len() {
694 #[allow(clippy::indexing_slicing)]
695 if s[i] != t[i] {
696 return false;
697 }
698
699 i += 1;
700 }
701
702 true
703 }
704
705 assert!(I::Aliasing::IS_EXCLUSIVE);
706
707 // SAFETY: We've confirmed that `self` already has the aliasing
708 // `Exclusive`. If it didn't, either the preceding assert would fail
709 // or evaluating `I::Aliasing::IS_EXCLUSIVE` would fail. We're
710 // *pretty* sure that it's guaranteed to fail const eval, but the
711 // `assert!` provides a backstop in case that doesn't work.
712 unsafe { self.assume_exclusive() }
713 }
714
715 /// Assumes that `self` satisfies the invariants `H`.
716 ///
717 /// # Safety
718 ///
719 /// The caller promises that `self` satisfies the invariants `H`.
720 unsafe fn assume_invariants<H: Invariants>(self) -> Ptr<'a, T, H> {
721 // SAFETY: The caller has promised to satisfy all parameterized
722 // invariants of `Ptr`. `Ptr`'s other invariants are satisfied
723 // by-contract by the source `Ptr`.
724 unsafe { Ptr::new(self.as_non_null()) }
725 }
726
727 /// Helps the type system unify two distinct invariant types which are
728 /// actually the same.
729 pub(crate) fn unify_invariants<
730 H: Invariants<Aliasing = I::Aliasing, Alignment = I::Alignment, Validity = I::Validity>,
731 >(
732 self,
733 ) -> Ptr<'a, T, H> {
734 // SAFETY: The associated type bounds on `H` ensure that the
735 // invariants are unchanged.
736 unsafe { self.assume_invariants::<H>() }
737 }
738
739 /// Assumes that `self` satisfies the aliasing requirement of `A`.
740 ///
741 /// # Safety
742 ///
743 /// The caller promises that `self` satisfies the aliasing requirement
744 /// of `A`.
745 #[inline]
746 pub(crate) unsafe fn assume_aliasing<A: Aliasing>(
747 self,
748 ) -> Ptr<'a, T, (A, I::Alignment, I::Validity)> {
749 // SAFETY: The caller promises that `self` satisfies the aliasing
750 // requirements of `A`.
751 unsafe { self.assume_invariants() }
752 }
753
754 /// Assumes `self` satisfies the aliasing requirement of [`Exclusive`].
755 ///
756 /// # Safety
757 ///
758 /// The caller promises that `self` satisfies the aliasing requirement
759 /// of `Exclusive`.
760 ///
761 /// [`Exclusive`]: invariant::Exclusive
762 #[inline]
763 pub(crate) unsafe fn assume_exclusive(
764 self,
765 ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> {
766 // SAFETY: The caller promises that `self` satisfies the aliasing
767 // requirements of `Exclusive`.
768 unsafe { self.assume_aliasing::<Exclusive>() }
769 }
770
771 /// Assumes that `self`'s referent is validly-aligned for `T` if
772 /// required by `A`.
773 ///
774 /// # Safety
775 ///
776 /// The caller promises that `self`'s referent conforms to the alignment
777 /// invariant of `T` if required by `A`.
778 #[inline]
779 pub(crate) unsafe fn assume_alignment<A: Alignment>(
780 self,
781 ) -> Ptr<'a, T, (I::Aliasing, A, I::Validity)> {
782 // SAFETY: The caller promises that `self`'s referent is
783 // well-aligned for `T` if required by `A` .
784 unsafe { self.assume_invariants() }
785 }
786
787 /// Checks the `self`'s alignment at runtime, returning an aligned `Ptr`
788 /// on success.
789 pub(crate) fn bikeshed_try_into_aligned(
790 self,
791 ) -> Result<Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>, AlignmentError<Self, T>>
792 where
793 T: Sized,
794 {
795 if let Err(err) = crate::util::validate_aligned_to::<_, T>(self.as_non_null()) {
796 return Err(err.with_src(self));
797 }
798
799 // SAFETY: We just checked the alignment.
800 Ok(unsafe { self.assume_alignment::<Aligned>() })
801 }
802
803 /// Recalls that `self`'s referent is validly-aligned for `T`.
804 #[inline]
805 // TODO(#859): Reconsider the name of this method before making it
806 // public.
807 pub(crate) fn bikeshed_recall_aligned(
808 self,
809 ) -> Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>
810 where
811 T: crate::Unaligned,
812 {
813 // SAFETY: The bound `T: Unaligned` ensures that `T` has no
814 // non-trivial alignment requirement.
815 unsafe { self.assume_alignment::<Aligned>() }
816 }
817
818 /// Assumes that `self`'s referent conforms to the validity requirement
819 /// of `V`.
820 ///
821 /// # Safety
822 ///
823 /// The caller promises that `self`'s referent conforms to the validity
824 /// requirement of `V`.
825 #[doc(hidden)]
826 #[must_use]
827 #[inline]
828 pub unsafe fn assume_validity<V: Validity>(
829 self,
830 ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> {
831 // SAFETY: The caller promises that `self`'s referent conforms to
832 // the validity requirement of `V`.
833 unsafe { self.assume_invariants() }
834 }
835
836 /// A shorthand for `self.assume_validity<invariant::Initialized>()`.
837 ///
838 /// # Safety
839 ///
840 /// The caller promises to uphold the safety preconditions of
841 /// `self.assume_validity<invariant::Initialized>()`.
842 #[doc(hidden)]
843 #[must_use]
844 #[inline]
845 pub unsafe fn assume_initialized(
846 self,
847 ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> {
848 // SAFETY: The caller has promised to uphold the safety
849 // preconditions.
850 unsafe { self.assume_validity::<Initialized>() }
851 }
852
853 /// A shorthand for `self.assume_validity<Valid>()`.
854 ///
855 /// # Safety
856 ///
857 /// The caller promises to uphold the safety preconditions of
858 /// `self.assume_validity<Valid>()`.
859 #[doc(hidden)]
860 #[must_use]
861 #[inline]
862 pub unsafe fn assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> {
863 // SAFETY: The caller has promised to uphold the safety
864 // preconditions.
865 unsafe { self.assume_validity::<Valid>() }
866 }
867
868 /// Recalls that `self`'s referent is bit-valid for `T`.
869 #[doc(hidden)]
870 #[must_use]
871 #[inline]
872 // TODO(#859): Reconsider the name of this method before making it
873 // public.
874 pub fn bikeshed_recall_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>
875 where
876 T: crate::FromBytes,
877 I: Invariants<Validity = Initialized>,
878 {
879 // SAFETY: The bound `T: FromBytes` ensures that any initialized
880 // sequence of bytes is bit-valid for `T`. `I: Invariants<Validity =
881 // invariant::Initialized>` ensures that all of the referent bytes
882 // are initialized.
883 unsafe { self.assume_valid() }
884 }
885
886 /// Checks that `self`'s referent is validly initialized for `T`,
887 /// returning a `Ptr` with `Valid` on success.
888 ///
889 /// # Panics
890 ///
891 /// This method will panic if
892 /// [`T::is_bit_valid`][TryFromBytes::is_bit_valid] panics.
893 ///
894 /// # Safety
895 ///
896 /// On error, unsafe code may rely on this method's returned
897 /// `ValidityError` containing `self`.
898 #[inline]
899 pub(crate) fn try_into_valid(
900 mut self,
901 ) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>, ValidityError<Self, T>>
902 where
903 T: TryFromBytes,
904 I::Aliasing: AtLeast<Shared>,
905 I: Invariants<Validity = Initialized>,
906 {
907 // This call may panic. If that happens, it doesn't cause any soundness
908 // issues, as we have not generated any invalid state which we need to
909 // fix before returning.
910 if T::is_bit_valid(self.reborrow().forget_aligned()) {
911 // SAFETY: If `T::is_bit_valid`, code may assume that `self`
912 // contains a bit-valid instance of `Self`.
913 Ok(unsafe { self.assume_valid() })
914 } else {
915 Err(ValidityError::new(self))
916 }
917 }
918
919 /// Forgets that `self`'s referent exclusively references `T`,
920 /// downgrading to a shared reference.
921 #[doc(hidden)]
922 #[must_use]
923 #[inline]
924 pub fn forget_exclusive(self) -> Ptr<'a, T, (Shared, I::Alignment, I::Validity)>
925 where
926 I::Aliasing: AtLeast<Shared>,
927 {
928 // SAFETY: `I::Aliasing` is at least as restrictive as `Shared`.
929 unsafe { self.assume_invariants() }
930 }
931
932 /// Forgets that `self`'s referent is validly-aligned for `T`.
933 #[doc(hidden)]
934 #[must_use]
935 #[inline]
936 pub fn forget_aligned(self) -> Ptr<'a, T, (I::Aliasing, Any, I::Validity)> {
937 // SAFETY: `Any` is less restrictive than `Aligned`.
938 unsafe { self.assume_invariants() }
939 }
940 }
941}
942
943/// Casts of the referent type.
944mod _casts {
945 use super::*;
946 use crate::{
947 layout::{DstLayout, MetadataCastError},
948 pointer::aliasing_safety::*,
949 AlignmentError, CastError, PointerMetadata, SizeError,
950 };
951
952 impl<'a, T, I> Ptr<'a, T, I>
953 where
954 T: 'a + ?Sized,
955 I: Invariants,
956 {
957 /// Casts to a different (unsized) target type.
958 ///
959 /// # Safety
960 ///
961 /// The caller promises that `u = cast(p)` is a pointer cast with the
962 /// following properties:
963 /// - `u` addresses a subset of the bytes addressed by `p`
964 /// - `u` has the same provenance as `p`
965 /// - If `I::Aliasing` is [`Any`] or [`Shared`], `UnsafeCell`s in `*u`
966 /// must exist at ranges identical to those at which `UnsafeCell`s
967 /// exist in `*p`
968 #[doc(hidden)]
969 #[inline]
970 pub unsafe fn cast_unsized<U: 'a + ?Sized, F: FnOnce(*mut T) -> *mut U>(
971 self,
972 cast: F,
973 ) -> Ptr<'a, U, (I::Aliasing, Any, Any)> {
974 let ptr = cast(self.as_non_null().as_ptr());
975
976 // SAFETY: Caller promises that `cast` returns a pointer whose
977 // address is in the range of `self.as_non_null()`'s referent. By
978 // invariant, none of these addresses are null.
979 let ptr = unsafe { NonNull::new_unchecked(ptr) };
980
981 // SAFETY:
982 //
983 // Lemma 1: `ptr` has the same provenance as `self`. The caller
984 // promises that `cast` preserves provenance, and we call it with
985 // `self.as_non_null()`.
986 //
987 // 0. By invariant, if `self`'s referent is not zero sized, then
988 // `self` is derived from some valid Rust allocation, `A`. By
989 // Lemma 1, `ptr` has the same provenance as `self`. Thus, `ptr`
990 // is derived from `A`.
991 // 1. By invariant, if `self`'s referent is not zero sized, then
992 // `self` has valid provenance for `A`. By Lemma 1, so does
993 // `ptr`.
994 // 2. By invariant on `self` and caller precondition, if `ptr`'s
995 // referent is not zero sized, then `ptr` addresses a byte range
996 // which is entirely contained in `A`.
997 // 3. By invariant on `self` and caller precondition, `ptr`
998 // addresses a byte range whose length fits in an `isize`.
999 // 4. By invariant on `self` and caller precondition, `ptr`
1000 // addresses a byte range which does not wrap around the address
1001 // space.
1002 // 5. By invariant on `self`, if `self`'s referent is not zero
1003 // sized, then `A` is guaranteed to live for at least `'a`.
1004 // 6. `ptr` conforms to the aliasing invariant of `I::Aliasing`:
1005 // - `Exclusive`: `self` is the only `Ptr` or reference which is
1006 // permitted to read or modify the referent for the lifetime
1007 // `'a`. Since we consume `self` by value, the returned pointer
1008 // remains the only `Ptr` or reference which is permitted to
1009 // read or modify the referent for the lifetime `'a`.
1010 // - `Shared`: Since `self` has aliasing `Shared`, we know that
1011 // no other code may mutate the referent during the lifetime
1012 // `'a`, except via `UnsafeCell`s. The caller promises that
1013 // `UnsafeCell`s cover the same byte ranges in `*self` and
1014 // `*ptr`. For each byte in the referent, there are two cases:
1015 // - If the byte is not covered by an `UnsafeCell` in `*ptr`,
1016 // then it is not covered in `*self`. By invariant on `self`,
1017 // it will not be mutated during `'a`, as required by the
1018 // constructed pointer. Similarly, the returned pointer will
1019 // not permit any mutations to these locations, as required
1020 // by the invariant on `self`.
1021 // - If the byte is covered by an `UnsafeCell` in `*ptr`, then
1022 // the returned pointer's invariants do not assume that the
1023 // byte will not be mutated during `'a`. While the returned
1024 // pointer will permit mutation of this byte during `'a`, by
1025 // invariant on `self`, no other code assumes that this will
1026 // not happen.
1027 // 7. `ptr`, trivially, conforms to the alignment invariant of
1028 // `Any`.
1029 // 8. `ptr`, trivially, conforms to the validity invariant of `Any`.
1030 unsafe { Ptr::new(ptr) }
1031 }
1032 }
1033
1034 impl<'a, T, I> Ptr<'a, T, I>
1035 where
1036 T: 'a + KnownLayout + ?Sized,
1037 I: Invariants<Validity = Initialized>,
1038 {
1039 /// Casts this pointer-to-initialized into a pointer-to-bytes.
1040 #[allow(clippy::wrong_self_convention)]
1041 pub(crate) fn as_bytes<R>(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Valid)>
1042 where
1043 [u8]: AliasingSafe<T, I::Aliasing, R>,
1044 R: AliasingSafeReason,
1045 {
1046 let bytes = match T::size_of_val_raw(self.as_non_null()) {
1047 Some(bytes) => bytes,
1048 // SAFETY: `KnownLayout::size_of_val_raw` promises to always
1049 // return `Some` so long as the resulting size fits in a
1050 // `usize`. By invariant on `Ptr`, `self` refers to a range of
1051 // bytes whose size fits in an `isize`, which implies that it
1052 // also fits in a `usize`.
1053 None => unsafe { core::hint::unreachable_unchecked() },
1054 };
1055
1056 // SAFETY:
1057 // - `slice_from_raw_parts_mut` and `.cast` both preserve the
1058 // pointer's address, and `bytes` is the length of `p`, so the
1059 // returned pointer addresses the same bytes as `p`
1060 // - `slice_from_raw_parts_mut` and `.cast` both preserve provenance
1061 // - Because `[u8]: AliasingSafe<T, I::Aliasing, _>`, either:
1062 // - `I::Aliasing` is `Exclusive`
1063 // - `T` and `[u8]` are both `Immutable`, in which case they
1064 // trivially contain `UnsafeCell`s at identical locations
1065 let ptr: Ptr<'a, [u8], _> = unsafe {
1066 self.cast_unsized(|p: *mut T| {
1067 #[allow(clippy::as_conversions)]
1068 core::ptr::slice_from_raw_parts_mut(p.cast::<u8>(), bytes)
1069 })
1070 };
1071
1072 let ptr = ptr.bikeshed_recall_aligned();
1073
1074 // SAFETY: `ptr`'s referent begins as `Initialized`, denoting that
1075 // all bytes of the referent are initialized bytes. The referent
1076 // type is then casted to `[u8]`, whose only validity invariant is
1077 // that its bytes are initialized. This validity invariant is
1078 // satisfied by the `Initialized` invariant on the starting `ptr`.
1079 unsafe { ptr.assume_validity::<Valid>() }
1080 }
1081 }
1082
1083 impl<'a, T, I, const N: usize> Ptr<'a, [T; N], I>
1084 where
1085 T: 'a,
1086 I: Invariants,
1087 {
1088 /// Casts this pointer-to-array into a slice.
1089 #[allow(clippy::wrong_self_convention)]
1090 pub(crate) fn as_slice(self) -> Ptr<'a, [T], I> {
1091 let start = self.as_non_null().cast::<T>().as_ptr();
1092 let slice = core::ptr::slice_from_raw_parts_mut(start, N);
1093 // SAFETY: `slice` is not null, because it is derived from `start`
1094 // which is non-null.
1095 let slice = unsafe { NonNull::new_unchecked(slice) };
1096 // SAFETY: Lemma: In the following safety arguments, note that
1097 // `slice` is derived from `self` in two steps: first, by casting
1098 // `self: [T; N]` to `start: T`, then by constructing a pointer to a
1099 // slice starting at `start` of length `N`. As a result, `slice`
1100 // references exactly the same allocation as `self`, if any.
1101 //
1102 // 0. By the above lemma, if `slice`'s referent is not zero sized,
1103 // then `slice` is derived from the same allocation as `self`,
1104 // which, by invariant on `Ptr`, is valid.
1105 // 1. By the above lemma, if `slice`'s referent is not zero sized,
1106 // then , `slice` has valid provenance for `A`, since it is
1107 // derived from the pointer `self`, which, by invariant on `Ptr`,
1108 // has valid provenance for `A`.
1109 // 2. By the above lemma, if `slice`'s referent is not zero sized,
1110 // then `slice` addresses a byte range which is entirely
1111 // contained in `A`, because it references exactly the same byte
1112 // range as `self`, which, by invariant on `Ptr`, is entirely
1113 // contained in `A`.
1114 // 3. By the above lemma, `slice` addresses a byte range whose
1115 // length fits in an `isize`, since it addresses exactly the same
1116 // byte range as `self`, which, by invariant on `Ptr`, has a
1117 // length that fits in an `isize`.
1118 // 4. By the above lemma, `slice` addresses a byte range which does
1119 // not wrap around the address space, since it addresses exactly
1120 // the same byte range as `self`, which, by invariant on `Ptr`,
1121 // does not wrap around the address space.
1122 // 5. By the above lemma, if `slice`'s referent is not zero sized,
1123 // then `A` is guaranteed to live for at least `'a`, because it
1124 // is derived from the same allocation as `self`, which, by
1125 // invariant on `Ptr`, lives for at least `'a`.
1126 // 6. By the above lemma, `slice` conforms to the aliasing invariant
1127 // of `I::Aliasing`, because the operations that produced `slice`
1128 // from `self` do not impact aliasing.
1129 // 7. By the above lemma, `slice` conforms to the alignment
1130 // invariant of `I::Alignment`, because the operations that
1131 // produced `slice` from `self` do not impact alignment.
1132 // 8. By the above lemma, `slice` conforms to the validity invariant
1133 // of `I::Validity`, because the operations that produced `slice`
1134 // from `self` do not impact validity.
1135 unsafe { Ptr::new(slice) }
1136 }
1137 }
1138
1139 /// For caller convenience, these methods are generic over alignment
1140 /// invariant. In practice, the referent is always well-aligned, because the
1141 /// alignment of `[u8]` is 1.
1142 impl<'a, I> Ptr<'a, [u8], I>
1143 where
1144 I: Invariants<Validity = Valid>,
1145 {
1146 /// Attempts to cast `self` to a `U` using the given cast type.
1147 ///
1148 /// If `U` is a slice DST and pointer metadata (`meta`) is provided,
1149 /// then the cast will only succeed if it would produce an object with
1150 /// the given metadata.
1151 ///
1152 /// Returns `None` if the resulting `U` would be invalidly-aligned, if
1153 /// no `U` can fit in `self`, or if the provided pointer metadata
1154 /// describes an invalid instance of `U`. On success, returns a pointer
1155 /// to the largest-possible `U` which fits in `self`.
1156 ///
1157 /// # Safety
1158 ///
1159 /// The caller may assume that this implementation is correct, and may
1160 /// rely on that assumption for the soundness of their code. In
1161 /// particular, the caller may assume that, if `try_cast_into` returns
1162 /// `Some((ptr, remainder))`, then `ptr` and `remainder` refer to
1163 /// non-overlapping byte ranges within `self`, and that `ptr` and
1164 /// `remainder` entirely cover `self`. Finally:
1165 /// - If this is a prefix cast, `ptr` has the same address as `self`.
1166 /// - If this is a suffix cast, `remainder` has the same address as
1167 /// `self`.
1168 pub(crate) fn try_cast_into<U, R>(
1169 self,
1170 cast_type: CastType,
1171 meta: Option<U::PointerMetadata>,
1172 ) -> Result<
1173 (Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, Ptr<'a, [u8], I>),
1174 CastError<Self, U>,
1175 >
1176 where
1177 R: AliasingSafeReason,
1178 U: 'a + ?Sized + KnownLayout + AliasingSafe<[u8], I::Aliasing, R>,
1179 {
1180 let layout = match meta {
1181 None => U::LAYOUT,
1182 // This can return `None` if the metadata describes an object
1183 // which can't fit in an `isize`.
1184 Some(meta) => {
1185 let size = match meta.size_for_metadata(U::LAYOUT) {
1186 Some(size) => size,
1187 None => return Err(CastError::Size(SizeError::new(self))),
1188 };
1189 DstLayout { align: U::LAYOUT.align, size_info: crate::SizeInfo::Sized { size } }
1190 }
1191 };
1192 // PANICS: By invariant, the byte range addressed by `self.ptr` does
1193 // not wrap around the address space. This implies that the sum of
1194 // the address (represented as a `usize`) and length do not overflow
1195 // `usize`, as required by `validate_cast_and_convert_metadata`.
1196 // Thus, this call to `validate_cast_and_convert_metadata` will only
1197 // panic if `U` is a DST whose trailing slice element is zero-sized.
1198 let maybe_metadata = layout.validate_cast_and_convert_metadata(
1199 AsAddress::addr(self.as_non_null().as_ptr()),
1200 self.len(),
1201 cast_type,
1202 );
1203
1204 let (elems, split_at) = match maybe_metadata {
1205 Ok((elems, split_at)) => (elems, split_at),
1206 Err(MetadataCastError::Alignment) => {
1207 // SAFETY: Since `validate_cast_and_convert_metadata`
1208 // returned an alignment error, `U` must have an alignment
1209 // requirement greater than one.
1210 let err = unsafe { AlignmentError::<_, U>::new_unchecked(self) };
1211 return Err(CastError::Alignment(err));
1212 }
1213 Err(MetadataCastError::Size) => return Err(CastError::Size(SizeError::new(self))),
1214 };
1215
1216 // SAFETY: `validate_cast_and_convert_metadata` promises to return
1217 // `split_at <= self.len()`.
1218 let (l_slice, r_slice) = unsafe { self.split_at(split_at) };
1219
1220 let (target, remainder) = match cast_type {
1221 CastType::Prefix => (l_slice, r_slice),
1222 CastType::Suffix => (r_slice, l_slice),
1223 };
1224
1225 let base = target.as_non_null().cast::<u8>();
1226
1227 let elems = <U as KnownLayout>::PointerMetadata::from_elem_count(elems);
1228 // For a slice DST type, if `meta` is `Some(elems)`, then we
1229 // synthesize `layout` to describe a sized type whose size is equal
1230 // to the size of the instance that we are asked to cast. For sized
1231 // types, `validate_cast_and_convert_metadata` returns `elems == 0`.
1232 // Thus, in this case, we need to use the `elems` passed by the
1233 // caller, not the one returned by
1234 // `validate_cast_and_convert_metadata`.
1235 let elems = meta.unwrap_or(elems);
1236
1237 let ptr = U::raw_from_ptr_len(base, elems);
1238
1239 // SAFETY:
1240 // 0. By invariant, if `target`'s referent is not zero sized, then
1241 // `target` is derived from some valid Rust allocation, `A`. By
1242 // contract on `cast`, `ptr` is derived from `self`, and thus
1243 // from the same valid Rust allocation, `A`.
1244 // 1. By invariant, if `target`'s referent is not zero sized, then
1245 // `target` has provenance valid for some Rust allocation, `A`.
1246 // Because `ptr` is derived from `target` via
1247 // provenance-preserving operations, `ptr` will also have
1248 // provenance valid for `A`.
1249 // - `validate_cast_and_convert_metadata` promises that the object
1250 // described by `elems` and `split_at` lives at a byte range
1251 // which is a subset of the input byte range. Thus:
1252 // 2. Since, by invariant, if `target`'s referent is not zero
1253 // sized, then `target` addresses a byte range which is
1254 // entirely contained in `A`, so does `ptr`.
1255 // 3. Since, by invariant, `target` addresses a byte range whose
1256 // length fits in an `isize`, so does `ptr`.
1257 // 4. Since, by invariant, `target` addresses a byte range which
1258 // does not wrap around the address space, so does `ptr`.
1259 // 5. Since, by invariant, if `target`'s referent is not zero
1260 // sized, then `target` refers to an allocation which is
1261 // guaranteed to live for at least `'a`, so does `ptr`.
1262 // 6. Since `U: AliasingSafe<[u8], I::Aliasing, _>`, either:
1263 // - `I::Aliasing` is `Exclusive`, in which case both `src`
1264 // and `ptr` conform to `Exclusive`
1265 // - `I::Aliasing` is `Shared` or `Any` and both `U` and
1266 // `[u8]` are `Immutable`. In this case, neither pointer
1267 // permits mutation, and so `Shared` aliasing is satisfied.
1268 // 7. `ptr` conforms to the alignment invariant of `Aligned` because
1269 // it is derived from `validate_cast_and_convert_metadata`, which
1270 // promises that the object described by `target` is validly
1271 // aligned for `U`.
1272 // 8. By trait bound, `self` - and thus `target` - is a bit-valid
1273 // `[u8]`. All bit-valid `[u8]`s have all of their bytes
1274 // initialized, so `ptr` conforms to the validity invariant of
1275 // `Initialized`.
1276 Ok((unsafe { Ptr::new(ptr) }, remainder))
1277 }
1278
1279 /// Attempts to cast `self` into a `U`, failing if all of the bytes of
1280 /// `self` cannot be treated as a `U`.
1281 ///
1282 /// In particular, this method fails if `self` is not validly-aligned
1283 /// for `U` or if `self`'s size is not a valid size for `U`.
1284 ///
1285 /// # Safety
1286 ///
1287 /// On success, the caller may assume that the returned pointer
1288 /// references the same byte range as `self`.
1289 #[allow(unused)]
1290 #[inline(always)]
1291 pub(crate) fn try_cast_into_no_leftover<U, R>(
1292 self,
1293 meta: Option<U::PointerMetadata>,
1294 ) -> Result<Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, CastError<Self, U>>
1295 where
1296 U: 'a + ?Sized + KnownLayout + AliasingSafe<[u8], I::Aliasing, R>,
1297 R: AliasingSafeReason,
1298 {
1299 // TODO(#67): Remove this allow. See NonNulSlicelExt for more
1300 // details.
1301 #[allow(unstable_name_collisions)]
1302 match self.try_cast_into(CastType::Prefix, meta) {
1303 Ok((slf, remainder)) => {
1304 if remainder.len() == 0 {
1305 Ok(slf)
1306 } else {
1307 // Undo the cast so we can return the original bytes.
1308 let slf = slf.as_bytes();
1309 // Restore the initial alignment invariant of `self`.
1310 //
1311 // SAFETY: The referent type of `slf` is now equal to
1312 // that of `self`, but the alignment invariants
1313 // nominally differ. Since `slf` and `self` refer to the
1314 // same memory and no actions have been taken that would
1315 // violate the original invariants on `self`, it is
1316 // sound to apply the alignment invariant of `self` onto
1317 // `slf`.
1318 let slf = unsafe { slf.assume_alignment::<I::Alignment>() };
1319 let slf = slf.unify_invariants();
1320 Err(CastError::Size(SizeError::<_, U>::new(slf)))
1321 }
1322 }
1323 Err(err) => Err(err),
1324 }
1325 }
1326 }
1327
1328 impl<'a, T, I> Ptr<'a, core::cell::UnsafeCell<T>, I>
1329 where
1330 T: 'a + ?Sized,
1331 I: Invariants<Aliasing = Exclusive>,
1332 {
1333 /// Converts this `Ptr` into a pointer to the underlying data.
1334 ///
1335 /// This call borrows the `UnsafeCell` mutably (at compile-time) which
1336 /// guarantees that we possess the only reference.
1337 ///
1338 /// This is like [`UnsafeCell::get_mut`], but for `Ptr`.
1339 ///
1340 /// [`UnsafeCell::get_mut`]: core::cell::UnsafeCell::get_mut
1341 #[must_use]
1342 #[inline(always)]
1343 pub fn get_mut(self) -> Ptr<'a, T, I> {
1344 // SAFETY:
1345 // - The closure uses an `as` cast, which preserves address range
1346 // and provenance.
1347 // - We require `I: Invariants<Aliasing = Exclusive>`, so we are not
1348 // required to uphold `UnsafeCell` equality.
1349 #[allow(clippy::as_conversions)]
1350 let ptr = unsafe { self.cast_unsized(|p| p as *mut T) };
1351
1352 // SAFETY: `UnsafeCell<T>` has the same alignment as `T` [1],
1353 // and so if `self` is guaranteed to be aligned, then so is the
1354 // returned `Ptr`.
1355 //
1356 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
1357 //
1358 // `UnsafeCell<T>` has the same in-memory representation as
1359 // its inner type `T`. A consequence of this guarantee is that
1360 // it is possible to convert between `T` and `UnsafeCell<T>`.
1361 let ptr = unsafe { ptr.assume_alignment::<I::Alignment>() };
1362
1363 // SAFETY: `UnsafeCell<T>` has the same bit validity as `T` [1], and
1364 // so if `self` has a particular validity invariant, then the same
1365 // holds of the returned `Ptr`. Technically the term
1366 // "representation" doesn't guarantee this, but the subsequent
1367 // sentence in the documentation makes it clear that this is the
1368 // intention.
1369 //
1370 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:
1371 //
1372 // `UnsafeCell<T>` has the same in-memory representation as its
1373 // inner type `T`. A consequence of this guarantee is that it is
1374 // possible to convert between `T` and `UnsafeCell<T>`.
1375 let ptr = unsafe { ptr.assume_validity::<I::Validity>() };
1376 ptr.unify_invariants()
1377 }
1378 }
1379}
1380
1381/// Projections through the referent.
1382mod _project {
1383 use core::ops::Range;
1384
1385 #[allow(unused_imports)]
1386 use crate::util::polyfills::NumExt as _;
1387
1388 use super::*;
1389
1390 impl<'a, T, I> Ptr<'a, T, I>
1391 where
1392 T: 'a + ?Sized,
1393 I: Invariants<Validity = Initialized>,
1394 {
1395 /// Projects a field from `self`.
1396 ///
1397 /// # Safety
1398 ///
1399 /// `project` has the same safety preconditions as `cast_unsized`.
1400 #[doc(hidden)]
1401 #[inline]
1402 pub unsafe fn project<U: 'a + ?Sized>(
1403 self,
1404 projector: impl FnOnce(*mut T) -> *mut U,
1405 ) -> Ptr<'a, U, (I::Aliasing, Any, Initialized)> {
1406 // TODO(#1122): If `cast_unsized` were able to reason that, when
1407 // casting from an `Initialized` pointer, the result is another
1408 // `Initialized` pointer, we could remove this method entirely.
1409
1410 // SAFETY: This method has the same safety preconditions as
1411 // `cast_unsized`.
1412 let ptr = unsafe { self.cast_unsized(projector) };
1413
1414 // SAFETY: If all of the bytes of `self` are initialized (as
1415 // promised by `I: Invariants<Validity = Initialized>`), then any
1416 // subset of those bytes are also all initialized.
1417 unsafe { ptr.assume_validity::<Initialized>() }
1418 }
1419 }
1420
1421 impl<'a, T, I> Ptr<'a, T, I>
1422 where
1423 T: 'a + KnownLayout<PointerMetadata = usize> + ?Sized,
1424 I: Invariants,
1425 {
1426 /// The number of trailing slice elements in the object referenced by
1427 /// `self`.
1428 ///
1429 /// # Safety
1430 ///
1431 /// Unsafe code my rely on `trailing_slice_len` satisfying the above
1432 /// contract.
1433 pub(super) fn trailing_slice_len(&self) -> usize {
1434 T::pointer_to_metadata(self.as_non_null())
1435 }
1436 }
1437
1438 impl<'a, T, I> Ptr<'a, [T], I>
1439 where
1440 T: 'a,
1441 I: Invariants,
1442 {
1443 /// The number of slice elements in the object referenced by `self`.
1444 ///
1445 /// # Safety
1446 ///
1447 /// Unsafe code my rely on `len` satisfying the above contract.
1448 pub(crate) fn len(&self) -> usize {
1449 self.trailing_slice_len()
1450 }
1451
1452 /// Creates a pointer which addresses the given `range` of self.
1453 ///
1454 /// # Safety
1455 ///
1456 /// `range` is a valid range (`start <= end`) and `end <= self.len()`.
1457 pub(crate) unsafe fn slice_unchecked(self, range: Range<usize>) -> Self {
1458 let base = self.as_non_null().cast::<T>().as_ptr();
1459
1460 // SAFETY: The caller promises that `start <= end <= self.len()`. By
1461 // invariant, if `self`'s referent is not zero-sized, then `self`
1462 // refers to a byte range which is contained within a single
1463 // allocation, which is no more than `isize::MAX` bytes long, and
1464 // which does not wrap around the address space. Thus, this pointer
1465 // arithmetic remains in-bounds of the same allocation, and does not
1466 // wrap around the address space. The offset (in bytes) does not
1467 // overflow `isize`.
1468 //
1469 // If `self`'s referent is zero-sized, then these conditions are
1470 // trivially satisfied.
1471 let base = unsafe { base.add(range.start) };
1472
1473 // SAFETY: The caller promises that `start <= end`, and so this will
1474 // not underflow.
1475 #[allow(unstable_name_collisions, clippy::incompatible_msrv)]
1476 let len = unsafe { range.end.unchecked_sub(range.start) };
1477
1478 let ptr = core::ptr::slice_from_raw_parts_mut(base, len);
1479
1480 // SAFETY: By invariant, `self`'s address is non-null and its range
1481 // does not wrap around the address space. Since, by the preceding
1482 // lemma, `ptr` addresses a range within that addressed by `self`,
1483 // `ptr` is non-null.
1484 let ptr = unsafe { NonNull::new_unchecked(ptr) };
1485
1486 // SAFETY:
1487 //
1488 // Lemma 0: `ptr` addresses a subset of the bytes addressed by
1489 // `self`, and has the same provenance.
1490 // Proof: The caller guarantees that `start <= end <= self.len()`.
1491 // Thus, `base` is in-bounds of `self`, and `base + (end -
1492 // start)` is also in-bounds of self. Finally, `ptr` is
1493 // constructed using provenance-preserving operations.
1494 //
1495 // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is
1496 // not zero sized, then `ptr` is derived from some valid Rust
1497 // allocation, `A`.
1498 // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is
1499 // not zero sized, then `ptr` has valid provenance for `A`.
1500 // 2. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is
1501 // not zero sized, then `ptr` addresses a byte range which is
1502 // entirely contained in `A`.
1503 // 3. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
1504 // range whose length fits in an `isize`.
1505 // 4. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
1506 // range which does not wrap around the address space.
1507 // 5. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is
1508 // not zero sized, then `A` is guaranteed to live for at least
1509 // `'a`.
1510 // 6. Per Lemma 0 and by invariant on `self`, `ptr` conforms to the
1511 // aliasing invariant of [`I::Aliasing`](invariant::Aliasing).
1512 // 7. Per Lemma 0 and by invariant on `self`, `ptr` conforms to the
1513 // alignment invariant of [`I::Alignment`](invariant::Alignment).
1514 // 8. Per Lemma 0 and by invariant on `self`, `ptr` conforms to the
1515 // validity invariant of [`I::Validity`](invariant::Validity).
1516 unsafe { Ptr::new(ptr) }
1517 }
1518
1519 /// Splits the slice in two.
1520 ///
1521 /// # Safety
1522 ///
1523 /// The caller promises that `l_len <= self.len()`.
1524 pub(crate) unsafe fn split_at(self, l_len: usize) -> (Self, Self) {
1525 // SAFETY: `Any` imposes no invariants, and so this is always sound.
1526 let slf = unsafe { self.assume_aliasing::<Any>() };
1527
1528 // SAFETY: The caller promises that `l_len <= self.len()`.
1529 // Trivially, `0 <= l_len`.
1530 let left = unsafe { slf.slice_unchecked(0..l_len) };
1531
1532 // SAFETY: The caller promises that `l_len <= self.len() =
1533 // slf.len()`. Trivially, `slf.len() <= slf.len()`.
1534 let right = unsafe { slf.slice_unchecked(l_len..slf.len()) };
1535
1536 // LEMMA: `left` and `right` are non-overlapping. Proof: `left` is
1537 // constructed from `slf` with `l_len` as its (exclusive) upper
1538 // bound, while `right` is constructed from `slf` with `l_len` as
1539 // its (inclusive) lower bound. Thus, no index is a member of both
1540 // ranges.
1541
1542 // SAFETY: By the preceding lemma, `left` and `right` do not alias.
1543 // We do not construct any other `Ptr`s or references which alias
1544 // `left` or `right`. Thus, the only `Ptr`s or references which
1545 // alias `left` or `right` are outside of this method. By invariant,
1546 // `self` obeys the aliasing invariant `I::Aliasing` with respect to
1547 // those other `Ptr`s or references, and so `left` and `right` do as
1548 // well.
1549 let (left, right) = unsafe {
1550 (left.assume_aliasing::<I::Aliasing>(), right.assume_aliasing::<I::Aliasing>())
1551 };
1552 (left.unify_invariants(), right.unify_invariants())
1553 }
1554
1555 /// Iteratively projects the elements `Ptr<T>` from `Ptr<[T]>`.
1556 pub(crate) fn iter(&self) -> impl Iterator<Item = Ptr<'a, T, I>> {
1557 // TODO(#429): Once `NonNull::cast` documents that it preserves
1558 // provenance, cite those docs.
1559 let base = self.as_non_null().cast::<T>().as_ptr();
1560 (0..self.len()).map(move |i| {
1561 // TODO(https://github.com/rust-lang/rust/issues/74265): Use
1562 // `NonNull::get_unchecked_mut`.
1563
1564 // SAFETY: If the following conditions are not satisfied
1565 // `pointer::cast` may induce Undefined Behavior [1]:
1566 //
1567 // > - The computed offset, `count * size_of::<T>()` bytes, must
1568 // > not overflow `isize``.
1569 // > - If the computed offset is non-zero, then `self` must be
1570 // > derived from a pointer to some allocated object, and the
1571 // > entire memory range between `self` and the result must be
1572 // > in bounds of that allocated object. In particular, this
1573 // > range must not “wrap around” the edge of the address
1574 // > space.
1575 //
1576 // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add
1577 //
1578 // We satisfy both of these conditions here:
1579 // - By invariant on `Ptr`, `self` addresses a byte range whose
1580 // length fits in an `isize`. Since `elem` is contained in
1581 // `self`, the computed offset of `elem` must fit within
1582 // `isize.`
1583 // - If the computed offset is non-zero, then this means that
1584 // the referent is not zero-sized. In this case, `base` points
1585 // to an allocated object (by invariant on `self`). Thus:
1586 // - By contract, `self.len()` accurately reflects the number
1587 // of elements in the slice. `i` is in bounds of `c.len()`
1588 // by construction, and so the result of this addition
1589 // cannot overflow past the end of the allocation referred
1590 // to by `c`.
1591 // - By invariant on `Ptr`, `self` addresses a byte range
1592 // which does not wrap around the address space. Since
1593 // `elem` is contained in `self`, the computed offset of
1594 // `elem` must wrap around the address space.
1595 //
1596 // TODO(#429): Once `pointer::add` documents that it preserves
1597 // provenance, cite those docs.
1598 let elem = unsafe { base.add(i) };
1599
1600 // SAFETY:
1601 // - `elem` must not be null. `base` is constructed from a
1602 // `NonNull` pointer, and the addition that produces `elem`
1603 // must not overflow or wrap around, so `elem >= base > 0`.
1604 //
1605 // TODO(#429): Once `NonNull::new_unchecked` documents that it
1606 // preserves provenance, cite those docs.
1607 let elem = unsafe { NonNull::new_unchecked(elem) };
1608
1609 // SAFETY: The safety invariants of `Ptr::new` (see definition)
1610 // are satisfied:
1611 // 0. If `elem`'s referent is not zero sized, then `elem` is
1612 // derived from a valid Rust allocation, because `self` is
1613 // derived from a valid Rust allocation, by invariant on
1614 // `Ptr`.
1615 // 1. If `elem`'s referent is not zero sized, then `elem` has
1616 // valid provenance for `self`, because it derived from
1617 // `self` using a series of provenance-preserving operations.
1618 // 2. If `elem`'s referent is not zero sized, then `elem` is
1619 // entirely contained in the allocation of `self` (see
1620 // above).
1621 // 3. `elem` addresses a byte range whose length fits in an
1622 // `isize` (see above).
1623 // 4. `elem` addresses a byte range which does not wrap around
1624 // the address space (see above).
1625 // 5. If `elem`'s referent is not zero sized, then the
1626 // allocation of `elem` is guaranteed to live for at least
1627 // `'a`, because `elem` is entirely contained in `self`,
1628 // which lives for at least `'a` by invariant on `Ptr`.
1629 // 6. `elem` conforms to the aliasing invariant of `I::Aliasing`
1630 // because projection does not impact the aliasing invariant.
1631 // 7. `elem`, conditionally, conforms to the validity invariant
1632 // of `I::Alignment`. If `elem` is projected from data
1633 // well-aligned for `[T]`, `elem` will be valid for `T`.
1634 // 8. `elem`, conditionally, conforms to the validity invariant
1635 // of `I::Validity`. If `elem` is projected from data valid
1636 // for `[T]`, `elem` will be valid for `T`.
1637 unsafe { Ptr::new(elem) }
1638 })
1639 }
1640 }
1641}
1642
1643#[cfg(test)]
1644mod tests {
1645 use core::mem::{self, MaybeUninit};
1646
1647 use static_assertions::{assert_impl_all, assert_not_impl_any};
1648
1649 use super::*;
1650 use crate::{pointer::BecauseImmutable, util::testutil::AU64, FromBytes, Immutable};
1651
1652 #[test]
1653 fn test_split_at() {
1654 const N: usize = 16;
1655 let mut arr = [1; N];
1656 let mut ptr = Ptr::from_mut(&mut arr).as_slice();
1657 for i in 0..=N {
1658 assert_eq!(ptr.len(), N);
1659 // SAFETY: `i` is in bounds by construction.
1660 let (l, r) = unsafe { ptr.reborrow().split_at(i) };
1661 let l_sum: usize = l.iter().map(Ptr::read_unaligned).sum();
1662 let r_sum: usize = r.iter().map(Ptr::read_unaligned).sum();
1663 assert_eq!(l_sum, i);
1664 assert_eq!(r_sum, N - i);
1665 assert_eq!(l_sum + r_sum, N);
1666 }
1667 }
1668
1669 mod test_ptr_try_cast_into_soundness {
1670 use super::*;
1671
1672 // This test is designed so that if `Ptr::try_cast_into_xxx` are
1673 // buggy, it will manifest as unsoundness that Miri can detect.
1674
1675 // - If `size_of::<T>() == 0`, `N == 4`
1676 // - Else, `N == 4 * size_of::<T>()`
1677 //
1678 // Each test will be run for each metadata in `metas`.
1679 fn test<T, I, const N: usize>(metas: I)
1680 where
1681 T: ?Sized + KnownLayout + Immutable + FromBytes,
1682 I: IntoIterator<Item = Option<T::PointerMetadata>> + Clone,
1683 {
1684 let mut bytes = [MaybeUninit::<u8>::uninit(); N];
1685 let initialized = [MaybeUninit::new(0u8); N];
1686 for start in 0..=bytes.len() {
1687 for end in start..=bytes.len() {
1688 // Set all bytes to uninitialized other than those in
1689 // the range we're going to pass to `try_cast_from`.
1690 // This allows Miri to detect out-of-bounds reads
1691 // because they read uninitialized memory. Without this,
1692 // some out-of-bounds reads would still be in-bounds of
1693 // `bytes`, and so might spuriously be accepted.
1694 bytes = [MaybeUninit::<u8>::uninit(); N];
1695 let bytes = &mut bytes[start..end];
1696 // Initialize only the byte range we're going to pass to
1697 // `try_cast_from`.
1698 bytes.copy_from_slice(&initialized[start..end]);
1699
1700 let bytes = {
1701 let bytes: *const [MaybeUninit<u8>] = bytes;
1702 #[allow(clippy::as_conversions)]
1703 let bytes = bytes as *const [u8];
1704 // SAFETY: We just initialized these bytes to valid
1705 // `u8`s.
1706 unsafe { &*bytes }
1707 };
1708
1709 // SAFETY: The bytes in `slf` must be initialized.
1710 unsafe fn validate_and_get_len<T: ?Sized + KnownLayout + FromBytes>(
1711 slf: Ptr<'_, T, (Shared, Aligned, Initialized)>,
1712 ) -> usize {
1713 let t = slf.bikeshed_recall_valid().as_ref();
1714
1715 let bytes = {
1716 let len = mem::size_of_val(t);
1717 let t: *const T = t;
1718 // SAFETY:
1719 // - We know `t`'s bytes are all initialized
1720 // because we just read it from `slf`, which
1721 // points to an initialized range of bytes. If
1722 // there's a bug and this doesn't hold, then
1723 // that's exactly what we're hoping Miri will
1724 // catch!
1725 // - Since `T: FromBytes`, `T` doesn't contain
1726 // any `UnsafeCell`s, so it's okay for `t: T`
1727 // and a `&[u8]` to the same memory to be
1728 // alive concurrently.
1729 unsafe { core::slice::from_raw_parts(t.cast::<u8>(), len) }
1730 };
1731
1732 // This assertion ensures that `t`'s bytes are read
1733 // and compared to another value, which in turn
1734 // ensures that Miri gets a chance to notice if any
1735 // of `t`'s bytes are uninitialized, which they
1736 // shouldn't be (see the comment above).
1737 assert_eq!(bytes, vec![0u8; bytes.len()]);
1738
1739 mem::size_of_val(t)
1740 }
1741
1742 for meta in metas.clone().into_iter() {
1743 for cast_type in [CastType::Prefix, CastType::Suffix] {
1744 if let Ok((slf, remaining)) = Ptr::from_ref(bytes)
1745 .try_cast_into::<T, BecauseImmutable>(cast_type, meta)
1746 {
1747 // SAFETY: All bytes in `bytes` have been
1748 // initialized.
1749 let len = unsafe { validate_and_get_len(slf) };
1750 assert_eq!(remaining.len(), bytes.len() - len);
1751 #[allow(unstable_name_collisions)]
1752 let bytes_addr = bytes.as_ptr().addr();
1753 #[allow(unstable_name_collisions)]
1754 let remaining_addr = remaining.as_non_null().as_ptr().addr();
1755 match cast_type {
1756 CastType::Prefix => {
1757 assert_eq!(remaining_addr, bytes_addr + len)
1758 }
1759 CastType::Suffix => assert_eq!(remaining_addr, bytes_addr),
1760 }
1761
1762 if let Some(want) = meta {
1763 let got = KnownLayout::pointer_to_metadata(slf.as_non_null());
1764 assert_eq!(got, want);
1765 }
1766 }
1767 }
1768
1769 if let Ok(slf) = Ptr::from_ref(bytes)
1770 .try_cast_into_no_leftover::<T, BecauseImmutable>(meta)
1771 {
1772 // SAFETY: All bytes in `bytes` have been
1773 // initialized.
1774 let len = unsafe { validate_and_get_len(slf) };
1775 assert_eq!(len, bytes.len());
1776
1777 if let Some(want) = meta {
1778 let got = KnownLayout::pointer_to_metadata(slf.as_non_null());
1779 assert_eq!(got, want);
1780 }
1781 }
1782 }
1783 }
1784 }
1785 }
1786
1787 #[derive(FromBytes, KnownLayout, Immutable)]
1788 #[repr(C)]
1789 struct SliceDst<T> {
1790 a: u8,
1791 trailing: [T],
1792 }
1793
1794 // Each test case becomes its own `#[test]` function. We do this because
1795 // this test in particular takes far, far longer to execute under Miri
1796 // than all of our other tests combined. Previously, we had these
1797 // execute sequentially in a single test function. We run Miri tests in
1798 // parallel in CI, but this test being sequential meant that most of
1799 // that parallelism was wasted, as all other tests would finish in a
1800 // fraction of the total execution time, leaving this test to execute on
1801 // a single thread for the remainder of the test. By putting each test
1802 // case in its own function, we permit better use of available
1803 // parallelism.
1804 macro_rules! test {
1805 ($test_name:ident: $ty:ty) => {
1806 #[test]
1807 #[allow(non_snake_case)]
1808 fn $test_name() {
1809 const S: usize = core::mem::size_of::<$ty>();
1810 const N: usize = if S == 0 { 4 } else { S * 4 };
1811 test::<$ty, _, N>([None]);
1812
1813 // If `$ty` is a ZST, then we can't pass `None` as the
1814 // pointer metadata, or else computing the correct trailing
1815 // slice length will panic.
1816 if S == 0 {
1817 test::<[$ty], _, N>([Some(0), Some(1), Some(2), Some(3)]);
1818 test::<SliceDst<$ty>, _, N>([Some(0), Some(1), Some(2), Some(3)]);
1819 } else {
1820 test::<[$ty], _, N>([None, Some(0), Some(1), Some(2), Some(3)]);
1821 test::<SliceDst<$ty>, _, N>([None, Some(0), Some(1), Some(2), Some(3)]);
1822 }
1823 }
1824 };
1825 ($ty:ident) => {
1826 test!($ty: $ty);
1827 };
1828 ($($ty:ident),*) => { $(test!($ty);)* }
1829 }
1830
1831 test!(empty_tuple: ());
1832 test!(u8, u16, u32, u64, u128, usize, AU64);
1833 test!(i8, i16, i32, i64, i128, isize);
1834 test!(f32, f64);
1835 }
1836
1837 #[test]
1838 fn test_invariants() {
1839 // Test that the correct invariant relationships hold.
1840 use super::invariant::*;
1841
1842 assert_not_impl_any!(Any: AtLeast<Shared>);
1843 assert_impl_all!(Shared: AtLeast<Shared>);
1844 assert_impl_all!(Exclusive: AtLeast<Shared>);
1845
1846 assert_not_impl_any!(Any: AtLeast<AsInitialized>);
1847 assert_impl_all!(AsInitialized: AtLeast<AsInitialized>);
1848 assert_impl_all!(Initialized: AtLeast<AsInitialized>);
1849 assert_impl_all!(Valid: AtLeast<AsInitialized>);
1850 }
1851
1852 #[test]
1853 fn test_try_cast_into_explicit_count() {
1854 macro_rules! test {
1855 ($ty:ty, $bytes:expr, $elems:expr, $expect:expr) => {{
1856 let bytes = [0u8; $bytes];
1857 let ptr = Ptr::from_ref(&bytes[..]);
1858 let res =
1859 ptr.try_cast_into::<$ty, BecauseImmutable>(CastType::Prefix, Some($elems));
1860 if let Some(expect) = $expect {
1861 let (ptr, _) = res.unwrap();
1862 assert_eq!(KnownLayout::pointer_to_metadata(ptr.as_non_null()), expect);
1863 } else {
1864 let _ = res.unwrap_err();
1865 }
1866 }};
1867 }
1868
1869 #[derive(KnownLayout, Immutable)]
1870 #[repr(C)]
1871 struct ZstDst {
1872 u: [u8; 8],
1873 slc: [()],
1874 }
1875
1876 test!(ZstDst, 8, 0, Some(0));
1877 test!(ZstDst, 7, 0, None);
1878
1879 test!(ZstDst, 8, usize::MAX, Some(usize::MAX));
1880 test!(ZstDst, 7, usize::MAX, None);
1881
1882 #[derive(KnownLayout, Immutable)]
1883 #[repr(C)]
1884 struct Dst {
1885 u: [u8; 8],
1886 slc: [u8],
1887 }
1888
1889 test!(Dst, 8, 0, Some(0));
1890 test!(Dst, 7, 0, None);
1891
1892 test!(Dst, 9, 1, Some(1));
1893 test!(Dst, 8, 1, None);
1894
1895 // If we didn't properly check for overflow, this would cause the
1896 // metadata to overflow to 0, and thus the cast would spuriously
1897 // succeed.
1898 test!(Dst, 8, usize::MAX - 8 + 1, None);
1899 }
1900}