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