Skip to content

Commit 689b42c

Browse files
committed
[pointer][WIP] Validity in referent
gherrit-pr-id: Icdd795ee43df33bd553deb69675c1cdca686a1d8
1 parent b0dfb32 commit 689b42c

File tree

4 files changed

+205
-166
lines changed

4 files changed

+205
-166
lines changed

src/pointer/invariant.rs

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
pub trait Invariants: Sealed {
1818
type Aliasing: Aliasing;
1919
type Alignment: Alignment;
20-
type Validity: Validity;
20+
// type Validity: Validity;
2121
}
2222

23-
impl<A: Aliasing, AA: Alignment, V: Validity> Invariants for (A, AA, V) {
23+
impl<A: Aliasing, AA: Alignment> Invariants for (A, AA) {
2424
type Aliasing = A;
2525
type Alignment = AA;
26-
type Validity = V;
26+
// type Validity = V;
2727
}
2828

2929
/// The aliasing invariant of a [`Ptr`][super::Ptr].
@@ -83,7 +83,17 @@ pub trait Alignment: Sealed {}
8383
/// mechanism (e.g. a `&` reference used to derive `src`) to write `x` where
8484
/// `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that
8585
/// `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 {}
8797

8898
/// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`].
8999
///
@@ -130,14 +140,24 @@ impl Alignment for Unaligned {}
130140
pub enum Aligned {}
131141
impl Alignment for Aligned {}
132142

143+
struct NeverPhantomData<T: ?Sized> {
144+
_marker: core::marker::PhantomData<T>,
145+
_never: core::convert::Infallible,
146+
}
147+
133148
/// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized
134149
/// bytes.
135-
pub enum Uninit {}
150+
pub struct Uninit<T: ?Sized>(NeverPhantomData<T>);
136151
// SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a
137152
// function of any property of `T` other than its bit validity (in fact, it's
138153
// not even a property of `T`'s bit validity, but this is more than we are
139154
// 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> {}
141161

142162
/// The byte ranges initialized in `T` are also initialized in the referent of a
143163
/// `Ptr<T>`.
@@ -166,37 +186,49 @@ unsafe impl Validity for Uninit {}
166186
/// variant's bit validity (although note that the variant may contain another
167187
/// enum type, in which case the same rules apply depending on the state of
168188
/// its discriminant, and so on recursively).
169-
pub enum AsInitialized {}
189+
pub struct AsInitialized<T: ?Sized>(NeverPhantomData<T>);
170190
// SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and
171191
// 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> {}
173197

174198
/// The byte ranges in the referent are fully initialized. In other words, if
175199
/// 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>);
177201
// SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is
178202
// not a function of any property of `T` other than its bit validity (in fact,
179203
// it's not even a property of `T`'s bit validity, but this is more than we are
180204
// 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> {}
182210

183211
/// The referent of a `Ptr<T>` is valid for `T`, upholding bit validity and any
184212
/// library safety invariants.
185-
pub enum Valid {}
213+
pub struct Valid<T: ?Sized>(NeverPhantomData<T>);
186214
// SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a
187215
// 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> {}
189221

190222
/// # Safety
191223
///
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> {}
195227

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> {}
200232

201233
/// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
202234
///
@@ -241,12 +273,12 @@ mod sealed {
241273
impl Sealed for Unaligned {}
242274
impl Sealed for Aligned {}
243275

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> {}
248280

249-
impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {}
281+
impl<A: Sealed, AA: Sealed> Sealed for (A, AA) {}
250282

251283
impl Sealed for BecauseImmutable {}
252284
impl Sealed for BecauseExclusive {}

src/pointer/mod.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,21 @@ mod transmute;
1717
#[doc(hidden)]
1818
pub(crate) use transmute::*;
1919
#[doc(hidden)]
20-
pub use {
21-
invariant::{BecauseExclusive, BecauseImmutable, Read},
22-
ptr::Ptr,
23-
};
20+
pub use {invariant::*, ptr::Ptr};
2421

2522
/// A shorthand for a maybe-valid, maybe-aligned reference. Used as the argument
2623
/// to [`TryFromBytes::is_bit_valid`].
2724
///
2825
/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
29-
pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unaligned> =
30-
Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>;
26+
pub type Maybe<'a, T, Aliasing = Shared, Alignment = Unaligned> =
27+
Ptr<'a, Initialized<T>, (Aliasing, Alignment)>;
3128

3229
/// Checks if the referent is zeroed.
33-
pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, T, I>) -> bool
30+
pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, Initialized<T>, I>) -> bool
3431
where
35-
T: crate::Immutable + crate::KnownLayout,
36-
I: invariant::Invariants<Validity = invariant::Initialized>,
37-
I::Aliasing: invariant::Reference,
32+
T: crate::Immutable + crate::KnownLayout + ?Sized,
33+
I: Invariants,
34+
I::Aliasing: Reference,
3835
{
3936
ptr.as_bytes::<BecauseImmutable>().as_ref().iter().all(|&byte| byte == 0)
4037
}

0 commit comments

Comments
 (0)