Skip to content

Commit 38e538b

Browse files
committed
[pointer][WIP] Validity in referent
gherrit-pr-id: Icdd795ee43df33bd553deb69675c1cdca686a1d8
1 parent bd18425 commit 38e538b

File tree

6 files changed

+236
-196
lines changed

6 files changed

+236
-196
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
///
@@ -128,14 +138,24 @@ impl Alignment for Unaligned {}
128138
pub enum Aligned {}
129139
impl Alignment for Aligned {}
130140

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

140160
/// The byte ranges initialized in `T` are also initialized in the referent of a
141161
/// `Ptr<T>`.
@@ -164,36 +184,48 @@ unsafe impl Validity for Uninit {}
164184
/// variant's bit validity (although note that the variant may contain another
165185
/// enum type, in which case the same rules apply depending on the state of
166186
/// its discriminant, and so on recursively).
167-
pub enum AsInitialized {}
187+
pub struct AsInitialized<T: ?Sized>(NeverPhantomData<T>);
168188
// SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and
169189
// 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> {}
171195

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

181209
/// The referent of a `Ptr<T>` is bit-valid for `T`.
182-
pub enum Valid {}
210+
pub struct Valid<T: ?Sized>(NeverPhantomData<T>);
183211
// SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a
184212
// 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> {}
186218

187219
/// # Safety
188220
///
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> {}
192224

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

198230
/// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations.
199231
///
@@ -238,12 +270,12 @@ mod sealed {
238270
impl Sealed for Unaligned {}
239271
impl Sealed for Aligned {}
240272

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

246-
impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {}
278+
impl<A: Sealed, AA: Sealed> Sealed for (A, AA) {}
247279

248280
impl Sealed for BecauseImmutable {}
249281
impl Sealed for BecauseExclusive {}

src/pointer/mod.rs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,54 +15,49 @@ mod ptr;
1515
mod transmute;
1616

1717
#[doc(hidden)]
18-
pub use invariant::{BecauseExclusive, BecauseImmutable, Read};
19-
#[doc(hidden)]
20-
pub use ptr::Ptr;
21-
22-
use crate::Unaligned;
18+
pub use {invariant::*, ptr::Ptr};
2319

2420
/// A shorthand for a maybe-valid, maybe-aligned reference. Used as the argument
2521
/// to [`TryFromBytes::is_bit_valid`].
2622
///
2723
/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
28-
pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unaligned> =
29-
Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>;
24+
pub type Maybe<'a, T, Aliasing = Shared, Alignment = Unaligned> =
25+
Ptr<'a, Initialized<T>, (Aliasing, Alignment)>;
3026

3127
/// A semi-user-facing wrapper type representing a maybe-aligned reference, for
3228
/// use in [`TryFromBytes::is_bit_valid`].
3329
///
3430
/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
35-
pub type MaybeAligned<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unaligned> =
36-
Ptr<'a, T, (Aliasing, Alignment, invariant::Valid)>;
31+
pub type MaybeAligned<'a, T, Aliasing = Shared, Alignment = Unaligned> =
32+
Ptr<'a, Valid<T>, (Aliasing, Alignment)>;
3733

3834
// These methods are defined on the type alias, `MaybeAligned`, so as to bring
3935
// them to the forefront of the rendered rustdoc for that type alias.
40-
impl<'a, T, Aliasing, Alignment> MaybeAligned<'a, T, Aliasing, Alignment>
36+
impl<'a, T, A, AA> MaybeAligned<'a, T, A, AA>
4137
where
4238
T: 'a + ?Sized,
43-
Aliasing: invariant::Aliasing,
44-
Alignment: invariant::Alignment,
39+
A: Aliasing,
40+
AA: Alignment,
4541
{
4642
/// Reads the value from `MaybeAligned`.
4743
#[must_use]
4844
#[inline]
4945
pub fn read_unaligned<R>(self) -> T
5046
where
51-
T: Copy,
52-
T: invariant::Read<Aliasing, R>,
47+
T: Read<A, R> + Copy,
5348
{
5449
// SAFETY: By invariant on `MaybeAligned`, `self` contains
55-
// validly-initialized data for `T`. By `T: Read<Aliasing>`, we are
56-
// permitted to perform a read of `self`'s referent.
50+
// validly-initialized data for `T`. By `T: Read<A>`, we are permitted
51+
// to perform a read of `self`'s referent.
5752
unsafe { self.as_inner().read_unaligned() }
5853
}
5954
}
6055

61-
impl<'a, T, Aliasing, Alignment> MaybeAligned<'a, T, Aliasing, Alignment>
56+
impl<'a, T, A, AA> MaybeAligned<'a, T, A, AA>
6257
where
6358
T: 'a + ?Sized,
64-
Aliasing: invariant::Reference,
65-
Alignment: invariant::Alignment,
59+
A: Reference,
60+
AA: Alignment,
6661
{
6762
/// Views the value as an aligned reference.
6863
///
@@ -71,18 +66,18 @@ where
7166
#[inline]
7267
pub fn unaligned_as_ref(self) -> &'a T
7368
where
74-
T: Unaligned,
69+
T: crate::Unaligned,
7570
{
7671
self.bikeshed_recall_aligned().as_ref()
7772
}
7873
}
7974

8075
/// Checks if the referent is zeroed.
81-
pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, T, I>) -> bool
76+
pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, Initialized<T>, I>) -> bool
8277
where
83-
T: crate::Immutable + crate::KnownLayout,
84-
I: invariant::Invariants<Validity = invariant::Initialized>,
85-
I::Aliasing: invariant::Reference,
78+
T: crate::Immutable + crate::KnownLayout + ?Sized,
79+
I: Invariants,
80+
I::Aliasing: Reference,
8681
{
8782
ptr.as_bytes::<BecauseImmutable>().as_ref().iter().all(|&byte| byte == 0)
8883
}

0 commit comments

Comments
 (0)