| 
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,37 +184,49 @@ 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 valid for `T`, upholding bit validity and any  | 
182 | 210 | /// library safety invariants.  | 
183 |  | -pub enum Valid {}  | 
 | 211 | +pub struct Valid<T: ?Sized>(NeverPhantomData<T>);  | 
184 | 212 | // SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a  | 
185 | 213 | // function of any property of `T` other than its bit validity.  | 
186 |  | -unsafe impl Validity for Valid {}  | 
 | 214 | +unsafe impl<T: ?Sized> Validity for Valid<T> {  | 
 | 215 | +    type Inner = T;  | 
 | 216 | +}  | 
 | 217 | +// SAFETY: The same validity (`Valid`) is used for both types.  | 
 | 218 | +unsafe impl<T: ?Sized, U: ?Sized> SameValidity<Valid<T>> for Valid<U> {}  | 
187 | 219 | 
 
  | 
188 | 220 | /// # Safety  | 
189 | 221 | ///  | 
190 |  | -/// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV =  | 
191 |  | -/// Initialized`.  | 
192 |  | -pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {}  | 
 | 222 | +/// `U: CastableFrom<T>` is sound if `T` and `U` have the same validity, and  | 
 | 223 | +/// that validity is either [`Uninit`] or [`Initialized`].  | 
 | 224 | +pub unsafe trait CastableFrom<T: ?Sized> {}  | 
193 | 225 | 
 
  | 
194 |  | -// SAFETY: `SV = DV = Uninit`.  | 
195 |  | -unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {}  | 
196 |  | -// SAFETY: `SV = DV = Initialized`.  | 
197 |  | -unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {}  | 
 | 226 | +// SAFETY: Both types have validity `Uninit`.  | 
 | 227 | +unsafe impl<T: ?Sized, U: ?Sized> CastableFrom<Uninit<T>> for Uninit<U> {}  | 
 | 228 | +// SAFETY: Both types have validity `Initialized`.  | 
 | 229 | +unsafe impl<T: ?Sized, U: ?Sized> CastableFrom<Initialized<T>> for Initialized<U> {}  | 
198 | 230 | 
 
  | 
199 | 231 | /// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.  | 
200 | 232 | ///  | 
@@ -239,12 +271,12 @@ mod sealed {  | 
239 | 271 |     impl Sealed for Unaligned {}  | 
240 | 272 |     impl Sealed for Aligned {}  | 
241 | 273 | 
 
  | 
242 |  | -    impl Sealed for Uninit {}  | 
243 |  | -    impl Sealed for AsInitialized {}  | 
244 |  | -    impl Sealed for Initialized {}  | 
245 |  | -    impl Sealed for Valid {}  | 
 | 274 | +    impl<T: ?Sized> Sealed for Uninit<T> {}  | 
 | 275 | +    impl<T: ?Sized> Sealed for AsInitialized<T> {}  | 
 | 276 | +    impl<T: ?Sized> Sealed for Initialized<T> {}  | 
 | 277 | +    impl<T: ?Sized> Sealed for Valid<T> {}  | 
246 | 278 | 
 
  | 
247 |  | -    impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {}  | 
 | 279 | +    impl<A: Sealed, AA: Sealed> Sealed for (A, AA) {}  | 
248 | 280 | 
 
  | 
249 | 281 |     impl Sealed for BecauseImmutable {}  | 
250 | 282 |     impl Sealed for BecauseExclusive {}  | 
 | 
0 commit comments