|
17 | 17 | pub trait Invariants: Sealed {
|
18 | 18 | type Aliasing: Aliasing;
|
19 | 19 | type Alignment: Alignment;
|
20 |
| - type Validity: Validity; |
| 20 | + // type Validity: Validity; |
21 | 21 | }
|
22 | 22 |
|
23 |
| -impl<A: Aliasing, AA: Alignment, V: Validity> Invariants for (A, AA, V) { |
| 23 | +impl<A: Aliasing, AA: Alignment> Invariants for (A, AA) { |
24 | 24 | type Aliasing = A;
|
25 | 25 | type Alignment = AA;
|
26 |
| - type Validity = V; |
| 26 | + // type Validity = V; |
27 | 27 | }
|
28 | 28 |
|
29 | 29 | /// The aliasing invariant of a [`Ptr`][super::Ptr].
|
@@ -83,7 +83,17 @@ pub trait Alignment: Sealed {}
|
83 | 83 | /// mechanism (e.g. a `&` reference used to derive `src`) to write `x` where
|
84 | 84 | /// `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that
|
85 | 85 | /// `dst`'s referent may only contain values in `S(U, W)`.
|
86 |
| -pub unsafe trait Validity: Sealed {} |
| 86 | +pub unsafe trait Validity: Sealed { |
| 87 | + type Inner: ?Sized; |
| 88 | +} |
| 89 | + |
| 90 | +/// Does `V` have the same validity invariant as `Self`? |
| 91 | +/// |
| 92 | +/// # Safety |
| 93 | +/// |
| 94 | +/// Unsafe code may assume that `W: SameValidity<V>` guarantees that `V` and `W` |
| 95 | +/// have the same validity invariant. |
| 96 | +pub unsafe trait SameValidity<V>: Sealed {} |
87 | 97 |
|
88 | 98 | /// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`].
|
89 | 99 | ///
|
@@ -128,14 +138,24 @@ impl Alignment for Unaligned {}
|
128 | 138 | pub enum Aligned {}
|
129 | 139 | impl Alignment for Aligned {}
|
130 | 140 |
|
| 141 | +struct NeverPhantomData<T: ?Sized> { |
| 142 | + _marker: core::marker::PhantomData<T>, |
| 143 | + _never: core::convert::Infallible, |
| 144 | +} |
| 145 | + |
131 | 146 | /// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized
|
132 | 147 | /// bytes.
|
133 |
| -pub enum Uninit {} |
| 148 | +pub struct Uninit<T: ?Sized>(NeverPhantomData<T>); |
134 | 149 | // SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a
|
135 | 150 | // function of any property of `T` other than its bit validity (in fact, it's
|
136 | 151 | // not even a property of `T`'s bit validity, but this is more than we are
|
137 | 152 | // required to uphold).
|
138 |
| -unsafe impl Validity for Uninit {} |
| 153 | +unsafe impl<T: ?Sized> Validity for Uninit<T> { |
| 154 | + type Inner = T; |
| 155 | +} |
| 156 | + |
| 157 | +// SAFETY: The same validity (`Uninit`) is used for both types. |
| 158 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Uninit<T>> for Uninit<U> {} |
139 | 159 |
|
140 | 160 | /// The byte ranges initialized in `T` are also initialized in the referent of a
|
141 | 161 | /// `Ptr<T>`.
|
@@ -164,36 +184,48 @@ unsafe impl Validity for Uninit {}
|
164 | 184 | /// variant's bit validity (although note that the variant may contain another
|
165 | 185 | /// enum type, in which case the same rules apply depending on the state of
|
166 | 186 | /// its discriminant, and so on recursively).
|
167 |
| -pub enum AsInitialized {} |
| 187 | +pub struct AsInitialized<T: ?Sized>(NeverPhantomData<T>); |
168 | 188 | // SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and
|
169 | 189 | // is not a function of any property of `T` other than its bit validity.
|
170 |
| -unsafe impl Validity for AsInitialized {} |
| 190 | +unsafe impl<T: ?Sized> Validity for AsInitialized<T> { |
| 191 | + type Inner = T; |
| 192 | +} |
| 193 | +// SAFETY: The same validity (`AsInitialized`) is used for both types. |
| 194 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<AsInitialized<T>> for AsInitialized<U> {} |
171 | 195 |
|
172 | 196 | /// The byte ranges in the referent are fully initialized. In other words, if
|
173 | 197 | /// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`.
|
174 |
| -pub enum Initialized {} |
| 198 | +pub struct Initialized<T: ?Sized>(NeverPhantomData<T>); |
175 | 199 | // SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is
|
176 | 200 | // not a function of any property of `T` other than its bit validity (in fact,
|
177 | 201 | // it's not even a property of `T`'s bit validity, but this is more than we are
|
178 | 202 | // required to uphold).
|
179 |
| -unsafe impl Validity for Initialized {} |
| 203 | +unsafe impl<T: ?Sized> Validity for Initialized<T> { |
| 204 | + type Inner = T; |
| 205 | +} |
| 206 | +// SAFETY: The same validity (`Initialized`) is used for both types. |
| 207 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Initialized<T>> for Initialized<U> {} |
180 | 208 |
|
181 | 209 | /// The referent of a `Ptr<T>` is bit-valid for `T`.
|
182 |
| -pub enum Valid {} |
| 210 | +pub struct Valid<T: ?Sized>(NeverPhantomData<T>); |
183 | 211 | // SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a
|
184 | 212 | // function of any property of `T` other than its bit validity.
|
185 |
| -unsafe impl Validity for Valid {} |
| 213 | +unsafe impl<T: ?Sized> Validity for Valid<T> { |
| 214 | + type Inner = T; |
| 215 | +} |
| 216 | +// SAFETY: The same validity (`Valid`) is used for both types. |
| 217 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Valid<T>> for Valid<U> {} |
186 | 218 |
|
187 | 219 | /// # Safety
|
188 | 220 | ///
|
189 |
| -/// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV = |
190 |
| -/// Initialized`. |
191 |
| -pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {} |
| 221 | +/// `U: CastableFrom<T>` is sound if `T` and `U` have the same validity, and |
| 222 | +/// that validity is either [`Uninit`] or [`Initialized`]. |
| 223 | +pub unsafe trait CastableFrom<T: ?Sized> {} |
192 | 224 |
|
193 |
| -// SAFETY: `SV = DV = Uninit`. |
194 |
| -unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {} |
195 |
| -// SAFETY: `SV = DV = Initialized`. |
196 |
| -unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {} |
| 225 | +// SAFETY: Both types have validity `Uninit`. |
| 226 | +unsafe impl<T: ?Sized, U: ?Sized> CastableFrom<Uninit<T>> for Uninit<U> {} |
| 227 | +// SAFETY: Both types have validity `Initialized`. |
| 228 | +unsafe impl<T: ?Sized, U: ?Sized> CastableFrom<Initialized<T>> for Initialized<U> {} |
197 | 229 |
|
198 | 230 | /// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
|
199 | 231 | ///
|
@@ -238,12 +270,12 @@ mod sealed {
|
238 | 270 | impl Sealed for Unaligned {}
|
239 | 271 | impl Sealed for Aligned {}
|
240 | 272 |
|
241 |
| - impl Sealed for Uninit {} |
242 |
| - impl Sealed for AsInitialized {} |
243 |
| - impl Sealed for Initialized {} |
244 |
| - impl Sealed for Valid {} |
| 273 | + impl<T: ?Sized> Sealed for Uninit<T> {} |
| 274 | + impl<T: ?Sized> Sealed for AsInitialized<T> {} |
| 275 | + impl<T: ?Sized> Sealed for Initialized<T> {} |
| 276 | + impl<T: ?Sized> Sealed for Valid<T> {} |
245 | 277 |
|
246 |
| - impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {} |
| 278 | + impl<A: Sealed, AA: Sealed> Sealed for (A, AA) {} |
247 | 279 |
|
248 | 280 | impl Sealed for BecauseImmutable {}
|
249 | 281 | impl Sealed for BecauseExclusive {}
|
|
0 commit comments