1586 lines · 67.3 KB · Rust
RawDownload
// 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

Lines 1–500 of 1586.