1 // Copyright 2024 The Fuchsia Authors 2 // 3 // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 4 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 6 // This file may not be copied, modified, or distributed except according to 7 // those terms. 8 9 #![allow(missing_copy_implementations, missing_debug_implementations)] 10 11 //! The parameterized invariants of a [`Ptr`][super::Ptr]. 12 //! 13 //! Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`]) 14 //! triples implementing the [`Invariants`] trait. 15 16 /// The invariants of a [`Ptr`][super::Ptr]. 17 pub trait Invariants: Sealed { 18 type Aliasing: Aliasing; 19 type Alignment: Alignment; 20 type Validity: Validity; 21 } 22 23 impl<A: Aliasing, AA: Alignment, V: Validity> Invariants for (A, AA, V) { 24 type Aliasing = A; 25 type Alignment = AA; 26 type Validity = V; 27 } 28 29 /// The aliasing invariant of a [`Ptr`][super::Ptr]. 30 /// 31 /// All aliasing invariants must permit reading from the bytes of a pointer's 32 /// referent which are not covered by [`UnsafeCell`]s. 33 /// 34 /// [`UnsafeCell`]: core::cell::UnsafeCell 35 pub trait Aliasing: Sealed { 36 /// Is `Self` [`Exclusive`]? 37 #[doc(hidden)] 38 const IS_EXCLUSIVE: bool; 39 } 40 41 /// The alignment invariant of a [`Ptr`][super::Ptr]. 42 pub trait Alignment: Sealed {} 43 44 /// The validity invariant of a [`Ptr`][super::Ptr]. 45 pub trait Validity: Sealed {} 46 47 /// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`]. 48 /// 49 /// # Safety 50 /// 51 /// Given `A: Reference`, callers may assume that either `A = Shared` or `A = 52 /// Exclusive`. 53 pub trait Reference: Aliasing + Sealed {} 54 55 /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`. 56 /// 57 /// The referent of a shared-aliased `Ptr` may be concurrently referenced by any 58 /// number of shared-aliased `Ptr` or `&T` references, and may not be 59 /// concurrently referenced by any exclusively-aliased `Ptr`s or `&mut T` 60 /// references. The referent must not be mutated, except via [`UnsafeCell`]s. 61 /// 62 /// [`UnsafeCell`]: core::cell::UnsafeCell 63 pub enum Shared {} 64 impl Aliasing for Shared { 65 const IS_EXCLUSIVE: bool = false; 66 } 67 impl Reference for Shared {} 68 69 /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`. 70 /// 71 /// The referent of an exclusively-aliased `Ptr` may not be concurrently 72 /// referenced by any other `Ptr`s or references, and may not be accessed (read 73 /// or written) other than via this `Ptr`. 74 pub enum Exclusive {} 75 impl Aliasing for Exclusive { 76 const IS_EXCLUSIVE: bool = true; 77 } 78 impl Reference for Exclusive {} 79 80 /// It is unknown whether the pointer is aligned. 81 pub enum Unaligned {} 82 83 impl Alignment for Unaligned {} 84 85 /// The referent is aligned: for `Ptr<T>`, the referent's address is a multiple 86 /// of the `T`'s alignment. 87 pub enum Aligned {} 88 impl Alignment for Aligned {} 89 90 /// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized 91 /// bytes. 92 pub enum Uninit {} 93 impl Validity for Uninit {} 94 95 /// The byte ranges initialized in `T` are also initialized in the referent. 96 /// 97 /// Formally: uninitialized bytes may only be present in `Ptr<T>`'s referent 98 /// where they are guaranteed to be present in `T`. This is a dynamic property: 99 /// if, at a particular byte offset, a valid enum discriminant is set, the 100 /// subsequent bytes may only have uninitialized bytes as specificed by the 101 /// corresponding enum. 102 /// 103 /// Formally, given `len = size_of_val_raw(ptr)`, at every byte offset, `b`, in 104 /// the range `[0, len)`: 105 /// - If, in any instance `t: T` of length `len`, the byte at offset `b` in `t` 106 /// is initialized, then the byte at offset `b` within `*ptr` must be 107 /// initialized. 108 /// - Let `c` be the contents of the byte range `[0, b)` in `*ptr`. Let `S` be 109 /// the subset of valid instances of `T` of length `len` which contain `c` in 110 /// the offset range `[0, b)`. If, in any instance of `t: T` in `S`, the byte 111 /// at offset `b` in `t` is initialized, then the byte at offset `b` in `*ptr` 112 /// must be initialized. 113 /// 114 /// Pragmatically, this means that if `*ptr` is guaranteed to contain an enum 115 /// type at a particular offset, and the enum discriminant stored in `*ptr` 116 /// corresponds to a valid variant of that enum type, then it is guaranteed 117 /// that the appropriate bytes of `*ptr` are initialized as defined by that 118 /// variant's bit validity (although note that the variant may contain another 119 /// enum type, in which case the same rules apply depending on the state of 120 /// its discriminant, and so on recursively). 121 pub enum AsInitialized {} 122 impl Validity for AsInitialized {} 123 124 /// The byte ranges in the referent are fully initialized. In other words, if 125 /// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`. 126 pub enum Initialized {} 127 impl Validity for Initialized {} 128 129 /// The referent is bit-valid for `T`. 130 pub enum Valid {} 131 impl Validity for Valid {} 132 133 /// # Safety 134 /// 135 /// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV = 136 /// Initialized`. 137 pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {} 138 139 // SAFETY: `SV = DV = Uninit`. 140 unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {} 141 // SAFETY: `SV = DV = Initialized`. 142 unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {} 143 144 /// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations. 145 /// 146 /// `T: Read<A, R>` implies that a pointer to `T` with aliasing `A` permits 147 /// unsynchronized read oeprations. This can be because `A` is [`Exclusive`] or 148 /// because `T` does not permit interior mutation. 149 /// 150 /// # Safety 151 /// 152 /// `T: Read<A, R>` if either of the following conditions holds: 153 /// - `A` is [`Exclusive`] 154 /// - `T` implements [`Immutable`](crate::Immutable) 155 /// 156 /// As a consequence, if `T: Read<A, R>`, then any `Ptr<T, (A, ...)>` is 157 /// permitted to perform unsynchronized reads from its referent. 158 pub trait Read<A: Aliasing, R> {} 159 160 impl<A: Aliasing, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {} 161 impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {} 162 163 /// Unsynchronized reads are permitted because only one live [`Ptr`](crate::Ptr) 164 /// or reference may exist to the referent bytes at a time. 165 #[derive(Copy, Clone, Debug)] 166 #[doc(hidden)] 167 pub enum BecauseExclusive {} 168 169 /// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s or 170 /// references permit interior mutation. 171 #[derive(Copy, Clone, Debug)] 172 #[doc(hidden)] 173 pub enum BecauseImmutable {} 174 175 use sealed::Sealed; 176 mod sealed { 177 use super::*; 178 179 pub trait Sealed {} 180 181 impl Sealed for Shared {} 182 impl Sealed for Exclusive {} 183 184 impl Sealed for Unaligned {} 185 impl Sealed for Aligned {} 186 187 impl Sealed for Uninit {} 188 impl Sealed for AsInitialized {} 189 impl Sealed for Initialized {} 190 impl Sealed for Valid {} 191 192 impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {} 193 194 impl Sealed for BecauseImmutable {} 195 impl Sealed for BecauseExclusive {} 196 } 197