/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerocopy-0.8.48/src/pointer/invariant.rs
Line | Count | Source |
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 | | #[doc(hidden)] |
44 | | #[must_use] |
45 | | fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T |
46 | | where |
47 | | T: Copy + Read<I::Aliasing, R>, |
48 | | I: Invariants<Alignment = Self, Validity = Valid>, |
49 | | I::Aliasing: Reference; |
50 | | } |
51 | | |
52 | | /// The validity invariant of a [`Ptr`][super::Ptr]. |
53 | | /// |
54 | | /// # Safety |
55 | | /// |
56 | | /// In this section, we will use `Ptr<T, V>` as a shorthand for `Ptr<T, I: |
57 | | /// Invariants<Validity = V>>` for brevity. |
58 | | /// |
59 | | /// Each `V: Validity` defines a set of bit values which may appear in the |
60 | | /// referent of a `Ptr<T, V>`, denoted `S(T, V)`. Each `V: Validity`, in its |
61 | | /// documentation, provides a definition of `S(T, V)` which must be valid for |
62 | | /// all `T: ?Sized`. Any `V: Validity` must guarantee that this set is only a |
63 | | /// function of the *bit validity* of the referent type, `T`, and not of any |
64 | | /// other property of `T`. As a consequence, given `V: Validity`, `T`, and `U` |
65 | | /// where `T` and `U` have the same bit validity, `S(V, T) = S(V, U)`. |
66 | | /// |
67 | | /// It is guaranteed that the referent of any `ptr: Ptr<T, V>` is a member of |
68 | | /// `S(T, V)`. Unsafe code must ensure that this guarantee will be upheld for |
69 | | /// any existing `Ptr`s or any `Ptr`s that that code creates. |
70 | | /// |
71 | | /// An important implication of this guarantee is that it restricts what |
72 | | /// transmutes are sound, where "transmute" is used in this context to refer to |
73 | | /// changing the referent type or validity invariant of a `Ptr`, as either |
74 | | /// change may change the set of bit values permitted to appear in the referent. |
75 | | /// In particular, the following are necessary (but not sufficient) conditions |
76 | | /// in order for a transmute from `src: Ptr<T, V>` to `dst: Ptr<U, W>` to be |
77 | | /// sound: |
78 | | /// - If `S(T, V) = S(U, W)`, then no restrictions apply; otherwise, |
79 | | /// - If `dst` permits mutation of its referent (e.g. via `Exclusive` aliasing |
80 | | /// or interior mutation under `Shared` aliasing), then it must hold that |
81 | | /// `S(T, V) ⊇ S(U, W)` - in other words, the transmute must not expand the |
82 | | /// set of allowed referent bit patterns. A violation of this requirement |
83 | | /// would permit using `dst` to write `x` where `x ∈ S(U, W)` but `x ∉ S(T, |
84 | | /// V)`, which would violate the guarantee that `src`'s referent may only |
85 | | /// contain values in `S(T, V)`. |
86 | | /// - If the referent may be mutated without going through `dst` while `dst` is |
87 | | /// live (e.g. via interior mutation on a `Shared`-aliased `Ptr` or `&` |
88 | | /// reference), then it must hold that `S(T, V) ⊆ S(U, W)` - in other words, |
89 | | /// the transmute must not shrink the set of allowed referent bit patterns. A |
90 | | /// violation of this requirement would permit using `src` or another |
91 | | /// mechanism (e.g. a `&` reference used to derive `src`) to write `x` where |
92 | | /// `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that |
93 | | /// `dst`'s referent may only contain values in `S(U, W)`. |
94 | | pub unsafe trait Validity: Sealed { |
95 | | const KIND: ValidityKind; |
96 | | } |
97 | | |
98 | | pub enum ValidityKind { |
99 | | Uninit, |
100 | | AsInitialized, |
101 | | Initialized, |
102 | | Valid, |
103 | | } |
104 | | |
105 | | /// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`]. |
106 | | /// |
107 | | /// # Safety |
108 | | /// |
109 | | /// Given `A: Reference`, callers may assume that either `A = Shared` or `A = |
110 | | /// Exclusive`. |
111 | | pub trait Reference: Aliasing + Sealed {} |
112 | | |
113 | | /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`. |
114 | | /// |
115 | | /// The referent of a shared-aliased `Ptr` may be concurrently referenced by any |
116 | | /// number of shared-aliased `Ptr` or `&T` references, or by any number of |
117 | | /// `Ptr<U>` or `&U` references as permitted by `T`'s library safety invariants, |
118 | | /// and may not be concurrently referenced by any exclusively-aliased `Ptr`s or |
119 | | /// `&mut` references. The referent must not be mutated, except via |
120 | | /// [`UnsafeCell`]s, and only when permitted by `T`'s library safety invariants. |
121 | | /// |
122 | | /// [`UnsafeCell`]: core::cell::UnsafeCell |
123 | | pub enum Shared {} |
124 | | impl Aliasing for Shared { |
125 | | const IS_EXCLUSIVE: bool = false; |
126 | | } |
127 | | impl Reference for Shared {} |
128 | | |
129 | | /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`. |
130 | | /// |
131 | | /// The referent of an exclusively-aliased `Ptr` may not be concurrently |
132 | | /// referenced by any other `Ptr`s or references, and may not be accessed (read |
133 | | /// or written) other than via this `Ptr`. |
134 | | pub enum Exclusive {} |
135 | | impl Aliasing for Exclusive { |
136 | | const IS_EXCLUSIVE: bool = true; |
137 | | } |
138 | | impl Reference for Exclusive {} |
139 | | |
140 | | /// It is unknown whether the pointer is aligned. |
141 | | pub enum Unaligned {} |
142 | | |
143 | | impl Alignment for Unaligned { |
144 | | #[inline(always)] |
145 | 0 | fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T |
146 | 0 | where |
147 | 0 | T: Copy + Read<I::Aliasing, R>, |
148 | 0 | I: Invariants<Alignment = Self, Validity = Valid>, |
149 | 0 | I::Aliasing: Reference, |
150 | | { |
151 | 0 | (*ptr.into_unalign().as_ref()).into_inner() |
152 | 0 | } |
153 | | } |
154 | | |
155 | | /// The referent is aligned: for `Ptr<T>`, the referent's address is a multiple |
156 | | /// of the `T`'s alignment. |
157 | | pub enum Aligned {} |
158 | | impl Alignment for Aligned { |
159 | | #[inline(always)] |
160 | 0 | fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T |
161 | 0 | where |
162 | 0 | T: Copy + Read<I::Aliasing, R>, |
163 | 0 | I: Invariants<Alignment = Self, Validity = Valid>, |
164 | 0 | I::Aliasing: Reference, |
165 | | { |
166 | 0 | *ptr.as_ref() |
167 | 0 | } |
168 | | } |
169 | | |
170 | | /// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized |
171 | | /// bytes. |
172 | | pub enum Uninit {} |
173 | | // SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a |
174 | | // function of any property of `T` other than its bit validity (in fact, it's |
175 | | // not even a property of `T`'s bit validity, but this is more than we are |
176 | | // required to uphold). |
177 | | unsafe impl Validity for Uninit { |
178 | | const KIND: ValidityKind = ValidityKind::Uninit; |
179 | | } |
180 | | |
181 | | /// The byte ranges initialized in `T` are also initialized in the referent of a |
182 | | /// `Ptr<T>`. |
183 | | /// |
184 | | /// Formally: uninitialized bytes may only be present in `Ptr<T>`'s referent |
185 | | /// where they are guaranteed to be present in `T`. This is a dynamic property: |
186 | | /// if, at a particular byte offset, a valid enum discriminant is set, the |
187 | | /// subsequent bytes may only have uninitialized bytes as specified by the |
188 | | /// corresponding enum. |
189 | | /// |
190 | | /// Formally, given `len = size_of_val_raw(ptr)`, at every byte offset, `b`, in |
191 | | /// the range `[0, len)`: |
192 | | /// - If, in any instance `t: T` of length `len`, the byte at offset `b` in `t` |
193 | | /// is initialized, then the byte at offset `b` within `*ptr` must be |
194 | | /// initialized. |
195 | | /// - Let `c` be the contents of the byte range `[0, b)` in `*ptr`. Let `S` be |
196 | | /// the subset of valid instances of `T` of length `len` which contain `c` in |
197 | | /// the offset range `[0, b)`. If, in any instance of `t: T` in `S`, the byte |
198 | | /// at offset `b` in `t` is initialized, then the byte at offset `b` in `*ptr` |
199 | | /// must be initialized. |
200 | | /// |
201 | | /// Pragmatically, this means that if `*ptr` is guaranteed to contain an enum |
202 | | /// type at a particular offset, and the enum discriminant stored in `*ptr` |
203 | | /// corresponds to a valid variant of that enum type, then it is guaranteed |
204 | | /// that the appropriate bytes of `*ptr` are initialized as defined by that |
205 | | /// variant's bit validity (although note that the variant may contain another |
206 | | /// enum type, in which case the same rules apply depending on the state of |
207 | | /// its discriminant, and so on recursively). |
208 | | pub enum AsInitialized {} |
209 | | // SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and |
210 | | // is not a function of any property of `T` other than its bit validity. |
211 | | unsafe impl Validity for AsInitialized { |
212 | | const KIND: ValidityKind = ValidityKind::AsInitialized; |
213 | | } |
214 | | |
215 | | /// The byte ranges in the referent are fully initialized. In other words, if |
216 | | /// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`. |
217 | | pub enum Initialized {} |
218 | | // SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is |
219 | | // not a function of any property of `T` other than its bit validity (in fact, |
220 | | // it's not even a property of `T`'s bit validity, but this is more than we are |
221 | | // required to uphold). |
222 | | unsafe impl Validity for Initialized { |
223 | | const KIND: ValidityKind = ValidityKind::Initialized; |
224 | | } |
225 | | |
226 | | /// The referent of a `Ptr<T>` is valid for `T`, upholding bit validity and any |
227 | | /// library safety invariants. |
228 | | pub enum Valid {} |
229 | | // SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a |
230 | | // function of any property of `T` other than its bit validity. |
231 | | unsafe impl Validity for Valid { |
232 | | const KIND: ValidityKind = ValidityKind::Valid; |
233 | | } |
234 | | |
235 | | /// # Safety |
236 | | /// |
237 | | /// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV = |
238 | | /// Initialized`. |
239 | | pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {} |
240 | | |
241 | | // SAFETY: `SV = DV = Uninit`. |
242 | | unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {} |
243 | | // SAFETY: `SV = DV = Initialized`. |
244 | | unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {} |
245 | | |
246 | | /// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations. |
247 | | /// |
248 | | /// `T: Read<A, R>` implies that a pointer to `T` with aliasing `A` permits |
249 | | /// unsynchronized read operations. This can be because `A` is [`Exclusive`] or |
250 | | /// because `T` does not permit interior mutation. |
251 | | /// |
252 | | /// # Safety |
253 | | /// |
254 | | /// `T: Read<A, R>` if either of the following conditions holds: |
255 | | /// - `A` is [`Exclusive`] |
256 | | /// - `T` implements [`Immutable`](crate::Immutable) |
257 | | /// |
258 | | /// As a consequence, if `T: Read<A, R>`, then any `Ptr<T, (A, ...)>` is |
259 | | /// permitted to perform unsynchronized reads from its referent. |
260 | | pub trait Read<A: Aliasing, R> {} |
261 | | |
262 | | impl<A: Aliasing, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {} |
263 | | impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {} |
264 | | |
265 | | /// Unsynchronized reads are permitted because only one live [`Ptr`](crate::Ptr) |
266 | | /// or reference may exist to the referent bytes at a time. |
267 | | #[derive(Copy, Clone, Debug)] |
268 | | #[doc(hidden)] |
269 | | pub enum BecauseExclusive {} |
270 | | |
271 | | /// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s or |
272 | | /// references permit interior mutation. |
273 | | #[derive(Copy, Clone, Debug)] |
274 | | #[doc(hidden)] |
275 | | pub enum BecauseImmutable {} |
276 | | |
277 | | use sealed::Sealed; |
278 | | mod sealed { |
279 | | use super::*; |
280 | | |
281 | | pub trait Sealed {} |
282 | | |
283 | | impl Sealed for Shared {} |
284 | | impl Sealed for Exclusive {} |
285 | | |
286 | | impl Sealed for Unaligned {} |
287 | | impl Sealed for Aligned {} |
288 | | |
289 | | impl Sealed for Uninit {} |
290 | | impl Sealed for AsInitialized {} |
291 | | impl Sealed for Initialized {} |
292 | | impl Sealed for Valid {} |
293 | | |
294 | | impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {} |
295 | | |
296 | | impl Sealed for BecauseImmutable {} |
297 | | impl Sealed for BecauseExclusive {} |
298 | | } |