|
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 | ///
|
@@ -130,14 +140,24 @@ impl Alignment for Unaligned {}
|
130 | 140 | pub enum Aligned {}
|
131 | 141 | impl Alignment for Aligned {}
|
132 | 142 |
|
| 143 | +struct NeverPhantomData<T: ?Sized> { |
| 144 | + _marker: core::marker::PhantomData<T>, |
| 145 | + _never: core::convert::Infallible, |
| 146 | +} |
| 147 | + |
133 | 148 | /// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized
|
134 | 149 | /// bytes.
|
135 |
| -pub enum Uninit {} |
| 150 | +pub struct Uninit<T: ?Sized>(NeverPhantomData<T>); |
136 | 151 | // SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a
|
137 | 152 | // function of any property of `T` other than its bit validity (in fact, it's
|
138 | 153 | // not even a property of `T`'s bit validity, but this is more than we are
|
139 | 154 | // required to uphold).
|
140 |
| -unsafe impl Validity for Uninit {} |
| 155 | +unsafe impl<T: ?Sized> Validity for Uninit<T> { |
| 156 | + type Inner = T; |
| 157 | +} |
| 158 | + |
| 159 | +// SAFETY: The same validity (`Uninit`) is used for both types. |
| 160 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Uninit<T>> for Uninit<U> {} |
141 | 161 |
|
142 | 162 | /// The byte ranges initialized in `T` are also initialized in the referent of a
|
143 | 163 | /// `Ptr<T>`.
|
@@ -166,37 +186,49 @@ unsafe impl Validity for Uninit {}
|
166 | 186 | /// variant's bit validity (although note that the variant may contain another
|
167 | 187 | /// enum type, in which case the same rules apply depending on the state of
|
168 | 188 | /// its discriminant, and so on recursively).
|
169 |
| -pub enum AsInitialized {} |
| 189 | +pub struct AsInitialized<T: ?Sized>(NeverPhantomData<T>); |
170 | 190 | // SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and
|
171 | 191 | // is not a function of any property of `T` other than its bit validity.
|
172 |
| -unsafe impl Validity for AsInitialized {} |
| 192 | +unsafe impl<T: ?Sized> Validity for AsInitialized<T> { |
| 193 | + type Inner = T; |
| 194 | +} |
| 195 | +// SAFETY: The same validity (`AsInitialized`) is used for both types. |
| 196 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<AsInitialized<T>> for AsInitialized<U> {} |
173 | 197 |
|
174 | 198 | /// The byte ranges in the referent are fully initialized. In other words, if
|
175 | 199 | /// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`.
|
176 |
| -pub enum Initialized {} |
| 200 | +pub struct Initialized<T: ?Sized>(NeverPhantomData<T>); |
177 | 201 | // SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is
|
178 | 202 | // not a function of any property of `T` other than its bit validity (in fact,
|
179 | 203 | // it's not even a property of `T`'s bit validity, but this is more than we are
|
180 | 204 | // required to uphold).
|
181 |
| -unsafe impl Validity for Initialized {} |
| 205 | +unsafe impl<T: ?Sized> Validity for Initialized<T> { |
| 206 | + type Inner = T; |
| 207 | +} |
| 208 | +// SAFETY: The same validity (`Initialized`) is used for both types. |
| 209 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Initialized<T>> for Initialized<U> {} |
182 | 210 |
|
183 | 211 | /// The referent of a `Ptr<T>` is valid for `T`, upholding bit validity and any
|
184 | 212 | /// library safety invariants.
|
185 |
| -pub enum Valid {} |
| 213 | +pub struct Valid<T: ?Sized>(NeverPhantomData<T>); |
186 | 214 | // SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a
|
187 | 215 | // function of any property of `T` other than its bit validity.
|
188 |
| -unsafe impl Validity for Valid {} |
| 216 | +unsafe impl<T: ?Sized> Validity for Valid<T> { |
| 217 | + type Inner = T; |
| 218 | +} |
| 219 | +// SAFETY: The same validity (`Valid`) is used for both types. |
| 220 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Valid<T>> for Valid<U> {} |
189 | 221 |
|
190 | 222 | /// # Safety
|
191 | 223 | ///
|
192 |
| -/// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV = |
193 |
| -/// Initialized`. |
194 |
| -pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {} |
| 224 | +/// `U: CastableFrom<T>` is sound if `T` and `U` have the same validity, and |
| 225 | +/// that validity is either [`Uninit`] or [`Initialized`]. |
| 226 | +pub unsafe trait CastableFrom<T: ?Sized> {} |
195 | 227 |
|
196 |
| -// SAFETY: `SV = DV = Uninit`. |
197 |
| -unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {} |
198 |
| -// SAFETY: `SV = DV = Initialized`. |
199 |
| -unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {} |
| 228 | +// SAFETY: Both types have validity `Uninit`. |
| 229 | +unsafe impl<T: ?Sized, U: ?Sized> CastableFrom<Uninit<T>> for Uninit<U> {} |
| 230 | +// SAFETY: Both types have validity `Initialized`. |
| 231 | +unsafe impl<T: ?Sized, U: ?Sized> CastableFrom<Initialized<T>> for Initialized<U> {} |
200 | 232 |
|
201 | 233 | /// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
|
202 | 234 | ///
|
@@ -241,12 +273,12 @@ mod sealed {
|
241 | 273 | impl Sealed for Unaligned {}
|
242 | 274 | impl Sealed for Aligned {}
|
243 | 275 |
|
244 |
| - impl Sealed for Uninit {} |
245 |
| - impl Sealed for AsInitialized {} |
246 |
| - impl Sealed for Initialized {} |
247 |
| - impl Sealed for Valid {} |
| 276 | + impl<T: ?Sized> Sealed for Uninit<T> {} |
| 277 | + impl<T: ?Sized> Sealed for AsInitialized<T> {} |
| 278 | + impl<T: ?Sized> Sealed for Initialized<T> {} |
| 279 | + impl<T: ?Sized> Sealed for Valid<T> {} |
248 | 280 |
|
249 |
| - impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {} |
| 281 | + impl<A: Sealed, AA: Sealed> Sealed for (A, AA) {} |
250 | 282 |
|
251 | 283 | impl Sealed for BecauseImmutable {}
|
252 | 284 | impl Sealed for BecauseExclusive {}
|
|
0 commit comments