Skip to content

Commit

Permalink
[pointer] Rename Any -> Unknown/Inaccessible
Browse files Browse the repository at this point in the history
For aliasing, use `Inaccessible`. For alignment and validity, use
`Unknown`.
  • Loading branch information
joshlf committed Oct 14, 2024
1 parent 85a12e2 commit e124ea0
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 33 deletions.
31 changes: 17 additions & 14 deletions src/pointer/invariant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,24 +81,26 @@ pub trait Validity: Sealed {}
/// Exclusive`.
pub trait Reference: Aliasing + Sealed {}

/// No requirement - any invariant is allowed.
pub enum Any {}
impl Aliasing for Any {
/// It is unknown whether any invariant holds.
pub enum Unknown {}

impl Alignment for Unknown {}
impl Validity for Unknown {}

/// The `Ptr<'a, T>` does not permit any reads or writes from or to its referent.
pub enum Inaccessible {}

impl Aliasing for Inaccessible {
const IS_EXCLUSIVE: bool = false;

// SAFETY: Since we don't know what aliasing model this is, we have to be
// conservative. Invariance is strictly more restrictive than any other
// variance model, so this can never cause soundness issues.
//
// `fn() -> T` and `fn(T) -> ()` are covariant and contravariant in `T`,
// respectively. [1] Thus, `fn(T) -> T` is invariant in `T`. Thus, `fn(&'a
// T) -> &'a T` is invariant in `'a` and `T`.
// SAFETY: Inaccessible `Ptr`s permit neither reads nor writes, and so it
// doesn't matter how long the referent actually lives. Thus, covariance is
// fine (and is chosen because it is maximally permissive). Shared
// references are covariant [1].
//
// [1] https://doc.rust-lang.org/1.81.0/reference/subtyping.html#variance
type Variance<'a, T: 'a + ?Sized> = fn(&'a T) -> &'a T;
type Variance<'a, T: 'a + ?Sized> = &'a T;
}
impl Alignment for Any {}
impl Validity for Any {}

/// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`.
///
Expand Down Expand Up @@ -212,8 +214,9 @@ mod sealed {

pub trait Sealed {}

impl Sealed for Any {}
impl Sealed for Unknown {}

impl Sealed for Inaccessible {}
impl Sealed for Shared {}
impl Sealed for Exclusive {}

Expand Down
4 changes: 2 additions & 2 deletions src/pointer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ use crate::Unaligned;
/// to [`TryFromBytes::is_bit_valid`].
///
/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Any> =
pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unknown> =
Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>;

/// A semi-user-facing wrapper type representing a maybe-aligned reference, for
/// use in [`TryFromBytes::is_bit_valid`].
///
/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
pub type MaybeAligned<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Any> =
pub type MaybeAligned<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unknown> =
Ptr<'a, T, (Aliasing, Alignment, invariant::Valid)>;

// These methods are defined on the type alias, `MaybeAligned`, so as to bring
Expand Down
33 changes: 19 additions & 14 deletions src/pointer/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,8 +676,8 @@ mod _transitions {
#[doc(hidden)]
#[must_use]
#[inline]
pub const fn forget_aligned(self) -> Ptr<'a, T, I::WithAlignment<Any>> {
// SAFETY: `Any` is less restrictive than `Aligned`.
pub const fn forget_aligned(self) -> Ptr<'a, T, I::WithAlignment<Unknown>> {
// SAFETY: `Unknown` is less restrictive than `Aligned`.
unsafe { self.assume_invariants() }
}
}
Expand Down Expand Up @@ -706,15 +706,14 @@ mod _casts {
/// following properties:
/// - `u` addresses a subset of the bytes addressed by `p`
/// - `u` has the same provenance as `p`
/// - If `I::Aliasing` is [`Any`] or [`Shared`], `UnsafeCell`s in `*u`
/// must exist at ranges identical to those at which `UnsafeCell`s
/// exist in `*p`
/// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist
/// at ranges identical to those at which `UnsafeCell`s exist in `*p`
#[doc(hidden)]
#[inline]
pub unsafe fn cast_unsized_unchecked<U: 'a + ?Sized, F: FnOnce(*mut T) -> *mut U>(
self,
cast: F,
) -> Ptr<'a, U, (I::Aliasing, Any, Any)> {
) -> Ptr<'a, U, (I::Aliasing, Unknown, Unknown)> {
let ptr = cast(self.as_inner().as_non_null().as_ptr());

// SAFETY: Caller promises that `cast` returns a pointer whose
Expand Down Expand Up @@ -768,9 +767,11 @@ mod _casts {
// pointer will permit mutation of this byte during `'a`, by
// invariant on `self`, no other code assumes that this will
// not happen.
// - `Inaccessible`: There are no restrictions we need to uphold.
// 7. `ptr`, trivially, conforms to the alignment invariant of
// `Any`.
// 8. `ptr`, trivially, conforms to the validity invariant of `Any`.
// `Unknown`.
// 8. `ptr`, trivially, conforms to the validity invariant of
// `Unknown`.
unsafe { Ptr::new(ptr) }
}

Expand All @@ -784,7 +785,10 @@ mod _casts {
/// - `u` has the same provenance as `p`
#[doc(hidden)]
#[inline]
pub unsafe fn cast_unsized<U, F, R, S>(self, cast: F) -> Ptr<'a, U, (I::Aliasing, Any, Any)>
pub unsafe fn cast_unsized<U, F, R, S>(
self,
cast: F,
) -> Ptr<'a, U, (I::Aliasing, Unknown, Unknown)>
where
T: Read<I::Aliasing, R>,
U: 'a + ?Sized + Read<I::Aliasing, S>,
Expand Down Expand Up @@ -927,10 +931,11 @@ mod _casts {
// 0. Since `U: Read<I::Aliasing, _>`, either:
// - `I::Aliasing` is `Exclusive`, in which case both `src` and
// `ptr` conform to `Exclusive`
// - `I::Aliasing` is `Shared` or `Any` and `U` is `Immutable`
// (we already know that `[u8]: Immutable`). In this case,
// neither `U` nor `[u8]` permit mutation, and so `Shared`
// aliasing is satisfied.
// - `I::Aliasing` is `Shared` or `Inaccessible` and `U` is
// `Immutable` (we already know that `[u8]: Immutable`). In
// this case, neither `U` nor `[u8]` permit mutation, and so
// `Shared` aliasing is satisfied. `Inaccessible` is trivially
// satisfied since it imposes no requirements.
// 1. `ptr` conforms to the alignment invariant of `Aligned` because
// it is derived from `try_cast_into`, which promises that the
// object described by `target` is validly aligned for `U`.
Expand Down Expand Up @@ -1070,7 +1075,7 @@ mod _project {
pub unsafe fn project<U: 'a + ?Sized>(
self,
projector: impl FnOnce(*mut T) -> *mut U,
) -> Ptr<'a, U, (I::Aliasing, Any, Initialized)> {
) -> Ptr<'a, U, (I::Aliasing, Unknown, Initialized)> {
// TODO(#1122): If `cast_unsized` were able to reason that, when
// casting from an `Initialized` pointer, the result is another
// `Initialized` pointer, we could remove this method entirely.
Expand Down
2 changes: 1 addition & 1 deletion src/util/macro_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>(
fn try_cast_or_pme<Src, Dst, I, R>(
src: Ptr<'_, Src, I>,
) -> Result<
Ptr<'_, Dst, (I::Aliasing, invariant::Any, invariant::Valid)>,
Ptr<'_, Dst, (I::Aliasing, invariant::Unknown, invariant::Valid)>,
ValidityError<Ptr<'_, Src, I>, Dst>,
>
where
Expand Down
4 changes: 2 additions & 2 deletions src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ impl<I: invariant::Validity> ValidityVariance<I> for Covariant {
pub enum Invariant {}

impl<I: invariant::Alignment> AlignmentVariance<I> for Invariant {
type Applied = invariant::Any;
type Applied = invariant::Unknown;
}

impl<I: invariant::Validity> ValidityVariance<I> for Invariant {
type Applied = invariant::Any;
type Applied = invariant::Unknown;
}

// SAFETY:
Expand Down

0 comments on commit e124ea0

Please sign in to comment.