// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT // Copyright 2023 The Fuchsia Authors//// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.// This file may not be copied, modified, or distributed except according to// those terms. #![allow(missing_docs)] use core::{ fmt::{Debug, Formatter}, marker::PhantomData,}; use crate::{ pointer::{ inner::PtrInner, invariant::*, transmute::{MutationCompatible, SizeEq, TransmuteFromPtr}, }, AlignmentError, CastError, CastType, KnownLayout, SizeError, TryFromBytes, ValidityError,}; /// Module used to gate access to [`Ptr`]'s fields.mod def { #[cfg(doc)] use super::super::invariant; use super::*; /// A raw pointer with more restrictions. /// /// `Ptr<T>` is similar to [`NonNull<T>`], but it is more restrictive in the /// following ways (note that these requirements only hold of non-zero-sized /// referents): /// - It must derive from a valid allocation. /// - It must reference a byte range which is contained inside the /// allocation from which it derives. /// - As a consequence, the byte range it references must have a size /// which does not overflow `isize`. /// /// Depending on how `Ptr` is parameterized, it may have additional /// invariants: /// - `ptr` conforms to the aliasing invariant of /// [`I::Aliasing`](invariant::Aliasing). /// - `ptr` conforms to the alignment invariant of /// [`I::Alignment`](invariant::Alignment). /// - `ptr` conforms to the validity invariant of /// [`I::Validity`](invariant::Validity). /// /// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`. /// /// [`NonNull<T>`]: core::ptr::NonNull /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html pub struct Ptr<'a, T, I> where T: ?Sized, I: Invariants, { /// # Invariants /// /// 0. `ptr` conforms to the aliasing invariant of /// [`I::Aliasing`](invariant::Aliasing). /// 1. `ptr` conforms to the alignment invariant of /// [`I::Alignment`](invariant::Alignment). /// 2. `ptr` conforms to the validity invariant of /// [`I::Validity`](invariant::Validity). // SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`. ptr: PtrInner<'a, T>, _invariants: PhantomData<I>, } impl<'a, T, I> Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants, { /// Constructs a new `Ptr` from a [`PtrInner`]. /// /// # Safety /// /// The caller promises that: /// /// 0. `ptr` conforms to the aliasing invariant of /// [`I::Aliasing`](invariant::Aliasing). /// 1. `ptr` conforms to the alignment invariant of /// [`I::Alignment`](invariant::Alignment). /// 2. `ptr` conforms to the validity invariant of /// [`I::Validity`](invariant::Validity). pub(crate) unsafe fn from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I> { // SAFETY: The caller has promised to satisfy all safety invariants // of `Ptr`. Self { ptr, _invariants: PhantomData } } /// Converts this `Ptr<T>` to a [`PtrInner<T>`]. /// /// Note that this method does not consume `self`. The caller should /// watch out for `unsafe` code which uses the returned value in a way /// that violates the safety invariants of `self`. #[inline] #[must_use] pub fn as_inner(&self) -> PtrInner<'a, T> { self.ptr } }} #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.pub use def::Ptr; /// External trait implementations on [`Ptr`].mod _external { use super::*; /// SAFETY: Shared pointers are safely `Copy`. `Ptr`'s other invariants /// (besides aliasing) are unaffected by the number of references that exist /// to `Ptr`'s referent. The notable cases are: /// - Alignment is a property of the referent type (`T`) and the address, /// both of which are unchanged /// - Let `S(T, V)` be the set of bit values permitted to appear in the /// referent of a `Ptr<T, I: Invariants<Validity = V>>`. Since this copy /// does not change `I::Validity` or `T`, `S(T, I::Validity)` is also /// unchanged. /// /// We are required to guarantee that the referents of the original `Ptr` /// and of the copy (which, of course, are actually the same since they /// live in the same byte address range) both remain in the set `S(T, /// I::Validity)`. Since this invariant holds on the original `Ptr`, it /// cannot be violated by the original `Ptr`, and thus the original `Ptr` /// cannot be used to violate this invariant on the copy. The inverse /// holds as well. impl<'a, T, I> Copy for Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants<Aliasing = Shared>, { } /// SAFETY: See the safety comment on `Copy`. impl<'a, T, I> Clone for Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants<Aliasing = Shared>, { #[inline] fn clone(&self) -> Self { *self } } impl<'a, T, I> Debug for Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants, { #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { self.as_inner().as_non_null().fmt(f) } }} /// Methods for converting to and from `Ptr` and Rust's safe reference types.mod _conversions { use super::*; use crate::pointer::cast::{CastExact, CastSized, IdCast}; /// `&'a T` → `Ptr<'a, T>` impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)> where T: 'a + ?Sized, { /// Constructs a `Ptr` from a shared reference. #[inline(always)] pub fn from_ref(ptr: &'a T) -> Self { let inner = PtrInner::from_ref(ptr); // SAFETY: // 0. `ptr`, by invariant on `&'a T`, conforms to the aliasing // invariant of `Shared`. // 1. `ptr`, by invariant on `&'a T`, conforms to the alignment // invariant of `Aligned`. // 2. `ptr`'s referent, by invariant on `&'a T`, is a bit-valid `T`. // This satisfies the requirement that a `Ptr<T, (_, _, Valid)>` // point to a bit-valid `T`. Even if `T` permits interior // mutation, this invariant guarantees that the returned `Ptr` // can only ever be used to modify the referent to store // bit-valid `T`s, which ensures that the returned `Ptr` cannot // be used to violate the soundness of the original `ptr: &'a T` // or of any other references that may exist to the same // referent. unsafe { Self::from_inner(inner) } } } /// `&'a mut T` → `Ptr<'a, T>` impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> where T: 'a + ?Sized, { /// Constructs a `Ptr` from an exclusive reference. #[inline(always)] pub fn from_mut(ptr: &'a mut T) -> Self { let inner = PtrInner::from_mut(ptr); // SAFETY: // 0. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing // invariant of `Exclusive`. // 1. `ptr`, by invariant on `&'a mut T`, conforms to the alignment // invariant of `Aligned`. // 2. `ptr`'s referent, by invariant on `&'a mut T`, is a bit-valid // `T`. This satisfies the requirement that a `Ptr<T, (_, _, // Valid)>` point to a bit-valid `T`. This invariant guarantees // that the returned `Ptr` can only ever be used to modify the // referent to store bit-valid `T`s, which ensures that the // returned `Ptr` cannot be used to violate the soundness of the // original `ptr: &'a mut T`. unsafe { Self::from_inner(inner) } } } /// `Ptr<'a, T>` → `&'a T` impl<'a, T, I> Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants<Alignment = Aligned, Validity = Valid>, I::Aliasing: Reference, { /// Converts `self` to a shared reference. // This consumes `self`, not `&self`, because `self` is, logically, a // pointer. For `I::Aliasing = invariant::Shared`, `Self: Copy`, and so // this doesn't prevent the caller from still using the pointer after // calling `as_ref`. #[allow(clippy::wrong_self_convention)] #[inline] #[must_use] pub fn as_ref(self) -> &'a T { let raw = self.as_inner().as_non_null(); // SAFETY: `self` satisfies the `Aligned` invariant, so we know that // `raw` is validly-aligned for `T`. #[cfg(miri)] unsafe { crate::util::miri_promise_symbolic_alignment( raw.as_ptr().cast(), core::mem::align_of_val_raw(raw.as_ptr()), ); } // SAFETY: This invocation of `NonNull::as_ref` satisfies its // documented safety preconditions: // // 1. The pointer is properly aligned. This is ensured by-contract // on `Ptr`, because the `I::Alignment` is `Aligned`. // // 2. If the pointer's referent is not zero-sized, then the pointer // must be “dereferenceable” in the sense defined in the module // documentation; i.e.: // // > The memory range of the given size starting at the pointer // > must all be within the bounds of a single allocated object. // > [2] // // This is ensured by contract on all `PtrInner`s. // // 3. The pointer must point to a validly-initialized instance of // `T`. This is ensured by-contract on `Ptr`, because the // `I::Validity` is `Valid`. // // 4. You must enforce Rust’s aliasing rules. This is ensured by // contract on `Ptr`, because `I::Aliasing: Reference`. Either it // is `Shared` or `Exclusive`. If it is `Shared`, other // references may not mutate the referent outside of // `UnsafeCell`s. // // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ref // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety unsafe { raw.as_ref() } } } impl<'a, T, I> Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants, I::Aliasing: Reference, { /// Reborrows `self`, producing another `Ptr`. /// /// Since `self` is borrowed mutably, this prevents any methods from /// being called on `self` as long as the returned `Ptr` exists. #[inline] #[must_use] #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below. pub fn reborrow<'b>(&'b mut self) -> Ptr<'b, T, I> where 'a: 'b, { // SAFETY: The following all hold by invariant on `self`, and thus // hold of `ptr = self.as_inner()`: // 0. SEE BELOW. // 1. `ptr` conforms to the alignment invariant of // [`I::Alignment`](invariant::Alignment). // 2. `ptr` conforms to the validity invariant of // [`I::Validity`](invariant::Validity). `self` and the returned // `Ptr` permit the same bit values in their referents since they // have the same referent type (`T`) and the same validity // (`I::Validity`). Thus, regardless of what mutation is // permitted (`Exclusive` aliasing or `Shared`-aliased interior // mutation), neither can be used to write a value to the // referent which violates the other's validity invariant. // // For aliasing (0 above), since `I::Aliasing: Reference`, // there are two cases for `I::Aliasing`: // - For `invariant::Shared`: `'a` outlives `'b`, and so the // returned `Ptr` does not permit accessing the referent any // longer than is possible via `self`. For shared aliasing, it is // sound for multiple `Ptr`s to exist simultaneously which // reference the same memory, so creating a new one is not // problematic. // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we // return a `Ptr` with lifetime `'b`, `self` is inaccessible to // the caller for the lifetime `'b` - in other words, `self` is // inaccessible to the caller as long as the returned `Ptr` // exists. Since `self` is an exclusive `Ptr`, no other live // references or `Ptr`s may exist which refer to the same memory // while `self` is live. Thus, as long as the returned `Ptr` // exists, no other references or `Ptr`s which refer to the same // memory may be live. unsafe { Ptr::from_inner(self.as_inner()) } } /// Reborrows `self` as shared, producing another `Ptr` with `Shared` /// aliasing. /// /// Since `self` is borrowed mutably, this prevents any methods from /// being called on `self` as long as the returned `Ptr` exists. #[inline] #[must_use] #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below. pub fn reborrow_shared<'b>(&'b mut self) -> Ptr<'b, T, (Shared, I::Alignment, I::Validity)> where 'a: 'b, { // SAFETY: The following all hold by invariant on `self`, and thus // hold of `ptr = self.as_inner()`: // 0. SEE BELOW. // 1. `ptr` conforms to the alignment invariant of // [`I::Alignment`](invariant::Alignment). // 2. `ptr` conforms to the validity invariant of // [`I::Validity`](invariant::Validity). `self` and the returned // `Ptr` permit the same bit values in their referents since they // have the same referent type (`T`) and the same validity // (`I::Validity`). Thus, regardless of what mutation is // permitted (`Exclusive` aliasing or `Shared`-aliased interior // mutation), neither can be used to write a value to the // referent which violates the other's validity invariant. // // For aliasing (0 above), since `I::Aliasing: Reference`, // there are two cases for `I::Aliasing`: // - For `invariant::Shared`: `'a` outlives `'b`, and so the // returned `Ptr` does not permit accessing the referent any // longer than is possible via `self`. For shared aliasing, it is // sound for multiple `Ptr`s to exist simultaneously which // reference the same memory, so creating a new one is not // problematic. // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we // return a `Ptr` with lifetime `'b`, `self` is inaccessible to // the caller for the lifetime `'b` - in other words, `self` is // inaccessible to the caller as long as the returned `Ptr` // exists. Since `self` is an exclusive `Ptr`, no other live // references or `Ptr`s may exist which refer to the same memory // while `self` is live. Thus, as long as the returned `Ptr` // exists, no other references or `Ptr`s which refer to the same // memory may be live. unsafe { Ptr::from_inner(self.as_inner()) } } } /// `Ptr<'a, T>` → `&'a mut T` impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> where T: 'a + ?Sized, { /// Converts `self` to a mutable reference. #[allow(clippy::wrong_self_convention)] #[inline] #[must_use] pub fn as_mut(self) -> &'a mut T { let mut raw = self.as_inner().as_non_null(); // SAFETY: `self` satisfies the `Aligned` invariant, so we know that // `raw` is validly-aligned for `T`. #[cfg(miri)] unsafe { crate::util::miri_promise_symbolic_alignment( raw.as_ptr().cast(), core::mem::align_of_val_raw(raw.as_ptr()), ); } // SAFETY: This invocation of `NonNull::as_mut` satisfies its // documented safety preconditions: // // 1. The pointer is properly aligned. This is ensured by-contract // on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`. // // 2. If the pointer's referent is not zero-sized, then the pointer // must be “dereferenceable” in the sense defined in the module // documentation; i.e.: // // > The memory range of the given size starting at the pointer // > must all be within the bounds of a single allocated object. // > [2] // // This is ensured by contract on all `PtrInner`s. // // 3. The pointer must point to a validly-initialized instance of // `T`. This is ensured by-contract on `Ptr`, because the // validity invariant is `Valid`. // // 4. You must enforce Rust’s aliasing rules. This is ensured by // contract on `Ptr`, because the `ALIASING_INVARIANT` is // `Exclusive`. // // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety unsafe { raw.as_mut() } } } /// `Ptr<'a, T>` → `Ptr<'a, U>` impl<'a, T: ?Sized, I> Ptr<'a, T, I> where I: Invariants, { #[must_use] #[inline(always)] pub fn transmute<U, V, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> where V: Validity, U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, <U as SizeEq<T>>::CastFrom, R> + SizeEq<T> + ?Sized, { self.transmute_with::<U, V, <U as SizeEq<T>>::CastFrom, R>() } #[inline] #[must_use] pub fn transmute_with<U, V, C, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> where V: Validity, U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, C, R> + ?Sized, C: CastExact<T, U>, { // SAFETY: // - By `C: CastExact`, `C` preserves referent address, and so we // don't need to consider projections in the following safety // arguments. // - If aliasing is `Shared`, then by `U: TransmuteFromPtr<T>`, at // least one of the following holds: // - `T: Immutable` and `U: Immutable`, in which case it is // trivially sound for shared code to operate on a `&T` and `&U` // at the same time, as neither can perform interior mutation // - It is directly guaranteed that it is sound for shared code to // operate on these references simultaneously // - By `U: TransmuteFromPtr<T, I::Aliasing, I::Validity, C, V>`, it // is sound to perform this transmute using `C`. unsafe { self.project_transmute_unchecked::<_, _, C>() } } #[inline] #[must_use] pub fn recall_validity<V, R>(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> where V: Validity, T: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, IdCast, R>, { let ptr = self.transmute_with::<T, V, IdCast, R>(); // SAFETY: `self` and `ptr` have the same address and referent type. // Therefore, if `self` satisfies `I::Alignment`, then so does // `ptr`. unsafe { ptr.assume_alignment::<I::Alignment>() } } /// Projects and/or transmutes to a different (unsized) referent type /// without checking interior mutability. /// /// Callers should prefer [`cast`] or [`project`] where possible. /// /// [`cast`]: Ptr::cast /// [`project`]: Ptr::project /// /// # Safety /// /// The caller promises that: /// - If `I::Aliasing` is [`Shared`], it must not be possible for safe /// code, operating on a `&T` and `&U`, with the referents of `self` /// and `self.project_transmute_unchecked()`, respectively, to cause /// undefined behavior. /// - It is sound to project and/or transmute a pointer of type `T` with /// aliasing `I::Aliasing` and validity `I::Validity` to a pointer ofLines 1–500 of 1586. Load more
// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT // Copyright 2023 The Fuchsia Authors // // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. // This file may not be copied, modified, or distributed except according to // those terms. #![allow(missing_docs)] use core::{ fmt::{Debug, Formatter}, marker::PhantomData, }; use crate::{ pointer::{ inner::PtrInner, invariant::*, transmute::{MutationCompatible, SizeEq, TransmuteFromPtr}, }, AlignmentError, CastError, CastType, KnownLayout, SizeError, TryFromBytes, ValidityError, }; /// Module used to gate access to [`Ptr`]'s fields. mod def { #[cfg(doc)] use super::super::invariant; use super::*; /// A raw pointer with more restrictions. /// /// `Ptr<T>` is similar to [`NonNull<T>`], but it is more restrictive in the /// following ways (note that these requirements only hold of non-zero-sized /// referents): /// - It must derive from a valid allocation. /// - It must reference a byte range which is contained inside the /// allocation from which it derives. /// - As a consequence, the byte range it references must have a size /// which does not overflow `isize`. /// /// Depending on how `Ptr` is parameterized, it may have additional /// invariants: /// - `ptr` conforms to the aliasing invariant of /// [`I::Aliasing`](invariant::Aliasing). /// - `ptr` conforms to the alignment invariant of /// [`I::Alignment`](invariant::Alignment). /// - `ptr` conforms to the validity invariant of /// [`I::Validity`](invariant::Validity). /// /// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`. /// /// [`NonNull<T>`]: core::ptr::NonNull /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html pub struct Ptr<'a, T, I> where T: ?Sized, I: Invariants, { /// # Invariants /// /// 0. `ptr` conforms to the aliasing invariant of /// [`I::Aliasing`](invariant::Aliasing). /// 1. `ptr` conforms to the alignment invariant of /// [`I::Alignment`](invariant::Alignment). /// 2. `ptr` conforms to the validity invariant of /// [`I::Validity`](invariant::Validity). // SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`. ptr: PtrInner<'a, T>, _invariants: PhantomData<I>, } impl<'a, T, I> Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants, { /// Constructs a new `Ptr` from a [`PtrInner`]. /// /// # Safety /// /// The caller promises that: /// /// 0. `ptr` conforms to the aliasing invariant of /// [`I::Aliasing`](invariant::Aliasing). /// 1. `ptr` conforms to the alignment invariant of /// [`I::Alignment`](invariant::Alignment). /// 2. `ptr` conforms to the validity invariant of /// [`I::Validity`](invariant::Validity). pub(crate) unsafe fn from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I> { // SAFETY: The caller has promised to satisfy all safety invariants // of `Ptr`. Self { ptr, _invariants: PhantomData } } /// Converts this `Ptr<T>` to a [`PtrInner<T>`]. /// /// Note that this method does not consume `self`. The caller should /// watch out for `unsafe` code which uses the returned value in a way /// that violates the safety invariants of `self`. #[inline] #[must_use] pub fn as_inner(&self) -> PtrInner<'a, T> { self.ptr } } } #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. pub use def::Ptr; /// External trait implementations on [`Ptr`]. mod _external { use super::*; /// SAFETY: Shared pointers are safely `Copy`. `Ptr`'s other invariants /// (besides aliasing) are unaffected by the number of references that exist /// to `Ptr`'s referent. The notable cases are: /// - Alignment is a property of the referent type (`T`) and the address, /// both of which are unchanged /// - Let `S(T, V)` be the set of bit values permitted to appear in the /// referent of a `Ptr<T, I: Invariants<Validity = V>>`. Since this copy /// does not change `I::Validity` or `T`, `S(T, I::Validity)` is also /// unchanged. /// /// We are required to guarantee that the referents of the original `Ptr` /// and of the copy (which, of course, are actually the same since they /// live in the same byte address range) both remain in the set `S(T, /// I::Validity)`. Since this invariant holds on the original `Ptr`, it /// cannot be violated by the original `Ptr`, and thus the original `Ptr` /// cannot be used to violate this invariant on the copy. The inverse /// holds as well. impl<'a, T, I> Copy for Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants<Aliasing = Shared>, { } /// SAFETY: See the safety comment on `Copy`. impl<'a, T, I> Clone for Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants<Aliasing = Shared>, { #[inline] fn clone(&self) -> Self { *self } } impl<'a, T, I> Debug for Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants, { #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { self.as_inner().as_non_null().fmt(f) } } } /// Methods for converting to and from `Ptr` and Rust's safe reference types. mod _conversions { use super::*; use crate::pointer::cast::{CastExact, CastSized, IdCast}; /// `&'a T` → `Ptr<'a, T>` impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)> where T: 'a + ?Sized, { /// Constructs a `Ptr` from a shared reference. #[inline(always)] pub fn from_ref(ptr: &'a T) -> Self { let inner = PtrInner::from_ref(ptr); // SAFETY: // 0. `ptr`, by invariant on `&'a T`, conforms to the aliasing // invariant of `Shared`. // 1. `ptr`, by invariant on `&'a T`, conforms to the alignment // invariant of `Aligned`. // 2. `ptr`'s referent, by invariant on `&'a T`, is a bit-valid `T`. // This satisfies the requirement that a `Ptr<T, (_, _, Valid)>` // point to a bit-valid `T`. Even if `T` permits interior // mutation, this invariant guarantees that the returned `Ptr` // can only ever be used to modify the referent to store // bit-valid `T`s, which ensures that the returned `Ptr` cannot // be used to violate the soundness of the original `ptr: &'a T` // or of any other references that may exist to the same // referent. unsafe { Self::from_inner(inner) } } } /// `&'a mut T` → `Ptr<'a, T>` impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> where T: 'a + ?Sized, { /// Constructs a `Ptr` from an exclusive reference. #[inline(always)] pub fn from_mut(ptr: &'a mut T) -> Self { let inner = PtrInner::from_mut(ptr); // SAFETY: // 0. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing // invariant of `Exclusive`. // 1. `ptr`, by invariant on `&'a mut T`, conforms to the alignment // invariant of `Aligned`. // 2. `ptr`'s referent, by invariant on `&'a mut T`, is a bit-valid // `T`. This satisfies the requirement that a `Ptr<T, (_, _, // Valid)>` point to a bit-valid `T`. This invariant guarantees // that the returned `Ptr` can only ever be used to modify the // referent to store bit-valid `T`s, which ensures that the // returned `Ptr` cannot be used to violate the soundness of the // original `ptr: &'a mut T`. unsafe { Self::from_inner(inner) } } } /// `Ptr<'a, T>` → `&'a T` impl<'a, T, I> Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants<Alignment = Aligned, Validity = Valid>, I::Aliasing: Reference, { /// Converts `self` to a shared reference. // This consumes `self`, not `&self`, because `self` is, logically, a // pointer. For `I::Aliasing = invariant::Shared`, `Self: Copy`, and so // this doesn't prevent the caller from still using the pointer after // calling `as_ref`. #[allow(clippy::wrong_self_convention)] #[inline] #[must_use] pub fn as_ref(self) -> &'a T { let raw = self.as_inner().as_non_null(); // SAFETY: `self` satisfies the `Aligned` invariant, so we know that // `raw` is validly-aligned for `T`. #[cfg(miri)] unsafe { crate::util::miri_promise_symbolic_alignment( raw.as_ptr().cast(), core::mem::align_of_val_raw(raw.as_ptr()), ); } // SAFETY: This invocation of `NonNull::as_ref` satisfies its // documented safety preconditions: // // 1. The pointer is properly aligned. This is ensured by-contract // on `Ptr`, because the `I::Alignment` is `Aligned`. // // 2. If the pointer's referent is not zero-sized, then the pointer // must be “dereferenceable” in the sense defined in the module // documentation; i.e.: // // > The memory range of the given size starting at the pointer // > must all be within the bounds of a single allocated object. // > [2] // // This is ensured by contract on all `PtrInner`s. // // 3. The pointer must point to a validly-initialized instance of // `T`. This is ensured by-contract on `Ptr`, because the // `I::Validity` is `Valid`. // // 4. You must enforce Rust’s aliasing rules. This is ensured by // contract on `Ptr`, because `I::Aliasing: Reference`. Either it // is `Shared` or `Exclusive`. If it is `Shared`, other // references may not mutate the referent outside of // `UnsafeCell`s. // // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ref // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety unsafe { raw.as_ref() } } } impl<'a, T, I> Ptr<'a, T, I> where T: 'a + ?Sized, I: Invariants, I::Aliasing: Reference, { /// Reborrows `self`, producing another `Ptr`. /// /// Since `self` is borrowed mutably, this prevents any methods from /// being called on `self` as long as the returned `Ptr` exists. #[inline] #[must_use] #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below. pub fn reborrow<'b>(&'b mut self) -> Ptr<'b, T, I> where 'a: 'b, { // SAFETY: The following all hold by invariant on `self`, and thus // hold of `ptr = self.as_inner()`: // 0. SEE BELOW. // 1. `ptr` conforms to the alignment invariant of // [`I::Alignment`](invariant::Alignment). // 2. `ptr` conforms to the validity invariant of // [`I::Validity`](invariant::Validity). `self` and the returned // `Ptr` permit the same bit values in their referents since they // have the same referent type (`T`) and the same validity // (`I::Validity`). Thus, regardless of what mutation is // permitted (`Exclusive` aliasing or `Shared`-aliased interior // mutation), neither can be used to write a value to the // referent which violates the other's validity invariant. // // For aliasing (0 above), since `I::Aliasing: Reference`, // there are two cases for `I::Aliasing`: // - For `invariant::Shared`: `'a` outlives `'b`, and so the // returned `Ptr` does not permit accessing the referent any // longer than is possible via `self`. For shared aliasing, it is // sound for multiple `Ptr`s to exist simultaneously which // reference the same memory, so creating a new one is not // problematic. // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we // return a `Ptr` with lifetime `'b`, `self` is inaccessible to // the caller for the lifetime `'b` - in other words, `self` is // inaccessible to the caller as long as the returned `Ptr` // exists. Since `self` is an exclusive `Ptr`, no other live // references or `Ptr`s may exist which refer to the same memory // while `self` is live. Thus, as long as the returned `Ptr` // exists, no other references or `Ptr`s which refer to the same // memory may be live. unsafe { Ptr::from_inner(self.as_inner()) } } /// Reborrows `self` as shared, producing another `Ptr` with `Shared` /// aliasing. /// /// Since `self` is borrowed mutably, this prevents any methods from /// being called on `self` as long as the returned `Ptr` exists. #[inline] #[must_use] #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below. pub fn reborrow_shared<'b>(&'b mut self) -> Ptr<'b, T, (Shared, I::Alignment, I::Validity)> where 'a: 'b, { // SAFETY: The following all hold by invariant on `self`, and thus // hold of `ptr = self.as_inner()`: // 0. SEE BELOW. // 1. `ptr` conforms to the alignment invariant of // [`I::Alignment`](invariant::Alignment). // 2. `ptr` conforms to the validity invariant of // [`I::Validity`](invariant::Validity). `self` and the returned // `Ptr` permit the same bit values in their referents since they // have the same referent type (`T`) and the same validity // (`I::Validity`). Thus, regardless of what mutation is // permitted (`Exclusive` aliasing or `Shared`-aliased interior // mutation), neither can be used to write a value to the // referent which violates the other's validity invariant. // // For aliasing (0 above), since `I::Aliasing: Reference`, // there are two cases for `I::Aliasing`: // - For `invariant::Shared`: `'a` outlives `'b`, and so the // returned `Ptr` does not permit accessing the referent any // longer than is possible via `self`. For shared aliasing, it is // sound for multiple `Ptr`s to exist simultaneously which // reference the same memory, so creating a new one is not // problematic. // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we // return a `Ptr` with lifetime `'b`, `self` is inaccessible to // the caller for the lifetime `'b` - in other words, `self` is // inaccessible to the caller as long as the returned `Ptr` // exists. Since `self` is an exclusive `Ptr`, no other live // references or `Ptr`s may exist which refer to the same memory // while `self` is live. Thus, as long as the returned `Ptr` // exists, no other references or `Ptr`s which refer to the same // memory may be live. unsafe { Ptr::from_inner(self.as_inner()) } } } /// `Ptr<'a, T>` → `&'a mut T` impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> where T: 'a + ?Sized, { /// Converts `self` to a mutable reference. #[allow(clippy::wrong_self_convention)] #[inline] #[must_use] pub fn as_mut(self) -> &'a mut T { let mut raw = self.as_inner().as_non_null(); // SAFETY: `self` satisfies the `Aligned` invariant, so we know that // `raw` is validly-aligned for `T`. #[cfg(miri)] unsafe { crate::util::miri_promise_symbolic_alignment( raw.as_ptr().cast(), core::mem::align_of_val_raw(raw.as_ptr()), ); } // SAFETY: This invocation of `NonNull::as_mut` satisfies its // documented safety preconditions: // // 1. The pointer is properly aligned. This is ensured by-contract // on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`. // // 2. If the pointer's referent is not zero-sized, then the pointer // must be “dereferenceable” in the sense defined in the module // documentation; i.e.: // // > The memory range of the given size starting at the pointer // > must all be within the bounds of a single allocated object. // > [2] // // This is ensured by contract on all `PtrInner`s. // // 3. The pointer must point to a validly-initialized instance of // `T`. This is ensured by-contract on `Ptr`, because the // validity invariant is `Valid`. // // 4. You must enforce Rust’s aliasing rules. This is ensured by // contract on `Ptr`, because the `ALIASING_INVARIANT` is // `Exclusive`. // // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety unsafe { raw.as_mut() } } } /// `Ptr<'a, T>` → `Ptr<'a, U>` impl<'a, T: ?Sized, I> Ptr<'a, T, I> where I: Invariants, { #[must_use] #[inline(always)] pub fn transmute<U, V, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> where V: Validity, U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, <U as SizeEq<T>>::CastFrom, R> + SizeEq<T> + ?Sized, { self.transmute_with::<U, V, <U as SizeEq<T>>::CastFrom, R>() } #[inline] #[must_use] pub fn transmute_with<U, V, C, R>(self) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> where V: Validity, U: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, C, R> + ?Sized, C: CastExact<T, U>, { // SAFETY: // - By `C: CastExact`, `C` preserves referent address, and so we // don't need to consider projections in the following safety // arguments. // - If aliasing is `Shared`, then by `U: TransmuteFromPtr<T>`, at // least one of the following holds: // - `T: Immutable` and `U: Immutable`, in which case it is // trivially sound for shared code to operate on a `&T` and `&U` // at the same time, as neither can perform interior mutation // - It is directly guaranteed that it is sound for shared code to // operate on these references simultaneously // - By `U: TransmuteFromPtr<T, I::Aliasing, I::Validity, C, V>`, it // is sound to perform this transmute using `C`. unsafe { self.project_transmute_unchecked::<_, _, C>() } } #[inline] #[must_use] pub fn recall_validity<V, R>(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> where V: Validity, T: TransmuteFromPtr<T, I::Aliasing, I::Validity, V, IdCast, R>, { let ptr = self.transmute_with::<T, V, IdCast, R>(); // SAFETY: `self` and `ptr` have the same address and referent type. // Therefore, if `self` satisfies `I::Alignment`, then so does // `ptr`. unsafe { ptr.assume_alignment::<I::Alignment>() } } /// Projects and/or transmutes to a different (unsized) referent type /// without checking interior mutability. /// /// Callers should prefer [`cast`] or [`project`] where possible. /// /// [`cast`]: Ptr::cast /// [`project`]: Ptr::project /// /// # Safety /// /// The caller promises that: /// - If `I::Aliasing` is [`Shared`], it must not be possible for safe /// code, operating on a `&T` and `&U`, with the referents of `self` /// and `self.project_transmute_unchecked()`, respectively, to cause /// undefined behavior. /// - It is sound to project and/or transmute a pointer of type `T` with /// aliasing `I::Aliasing` and validity `I::Validity` to a pointer of