• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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