Skip to content

Commit 7c245c5

Browse files
committed
[pointer] Make invariants opaque, more ergonomic
Closes #1876
1 parent 3ab2c00 commit 7c245c5

File tree

1 file changed

+43
-23
lines changed

1 file changed

+43
-23
lines changed

src/pointer/ptr.rs

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,40 @@ pub mod invariant {
140140
type Aliasing: Aliasing;
141141
type Alignment: Alignment;
142142
type Validity: Validity;
143+
144+
/// Invariants identical to `Self` except with a different aliasing
145+
/// invariant.
146+
type WithAliasing<A: Aliasing>: Invariants<
147+
Aliasing = A,
148+
Alignment = Self::Alignment,
149+
Validity = Self::Validity,
150+
>;
151+
152+
/// Invariants identical to `Self` except with a different alignment
153+
/// invariant.
154+
type WithAlignment<A: Alignment>: Invariants<
155+
Aliasing = Self::Aliasing,
156+
Alignment = A,
157+
Validity = Self::Validity,
158+
>;
159+
160+
/// Invariants identical to `Self` except with a different validity
161+
/// invariant.
162+
type WithValidity<V: Validity>: Invariants<
163+
Aliasing = Self::Aliasing,
164+
Alignment = Self::Alignment,
165+
Validity = V,
166+
>;
143167
}
144168

145169
impl<A: Aliasing, AA: Alignment, V: Validity> Invariants for (A, AA, V) {
146170
type Aliasing = A;
147171
type Alignment = AA;
148172
type Validity = V;
173+
174+
type WithAliasing<AB: Aliasing> = (AB, AA, V);
175+
type WithAlignment<AB: Alignment> = (A, AB, V);
176+
type WithValidity<VB: Validity> = (A, AA, VB);
149177
}
150178

151179
/// The aliasing invariant of a [`Ptr`][super::Ptr].
@@ -576,9 +604,7 @@ mod _conversions {
576604
{
577605
/// Converts a `Ptr` an unaligned `T` into a `Ptr` to an aligned
578606
/// `Unalign<T>`.
579-
pub(crate) fn into_unalign(
580-
self,
581-
) -> Ptr<'a, crate::Unalign<T>, (I::Aliasing, Aligned, I::Validity)> {
607+
pub(crate) fn into_unalign(self) -> Ptr<'a, crate::Unalign<T>, I::WithAlignment<Aligned>> {
582608
// SAFETY:
583609
// - This cast preserves provenance.
584610
// - This cast preserves address. `Unalign<T>` promises to have the
@@ -596,7 +622,7 @@ mod _conversions {
596622
// SAFETY: `Unalign<T>` promises to have alignment 1, and so it is
597623
// trivially aligned.
598624
let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
599-
ptr
625+
ptr.unify_invariants()
600626
}
601627
}
602628
}
@@ -621,7 +647,7 @@ mod _transitions {
621647
#[inline]
622648
pub(crate) fn into_exclusive_or_post_monomorphization_error(
623649
self,
624-
) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> {
650+
) -> Ptr<'a, T, I::WithAliasing<Exclusive>> {
625651
// NOTE(https://github.com/rust-lang/rust/issues/131625): We do this
626652
// rather than just having `Aliasing::IS_EXCLUSIVE` have the panic
627653
// behavior because doing it that way causes rustdoc to fail while
@@ -681,7 +707,7 @@ mod _transitions {
681707
#[inline]
682708
pub(crate) const unsafe fn assume_aliasing<A: Aliasing>(
683709
self,
684-
) -> Ptr<'a, T, (A, I::Alignment, I::Validity)> {
710+
) -> Ptr<'a, T, I::WithAliasing<A>> {
685711
// SAFETY: The caller promises that `self` satisfies the aliasing
686712
// requirements of `A`.
687713
unsafe { self.assume_invariants() }
@@ -698,7 +724,7 @@ mod _transitions {
698724
#[inline]
699725
pub(crate) const unsafe fn assume_exclusive(
700726
self,
701-
) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> {
727+
) -> Ptr<'a, T, I::WithAliasing<Exclusive>> {
702728
// SAFETY: The caller promises that `self` satisfies the aliasing
703729
// requirements of `Exclusive`.
704730
unsafe { self.assume_aliasing::<Exclusive>() }
@@ -714,7 +740,7 @@ mod _transitions {
714740
#[inline]
715741
pub(crate) const unsafe fn assume_alignment<A: Alignment>(
716742
self,
717-
) -> Ptr<'a, T, (I::Aliasing, A, I::Validity)> {
743+
) -> Ptr<'a, T, I::WithAlignment<A>> {
718744
// SAFETY: The caller promises that `self`'s referent is
719745
// well-aligned for `T` if required by `A` .
720746
unsafe { self.assume_invariants() }
@@ -724,7 +750,7 @@ mod _transitions {
724750
/// on success.
725751
pub(crate) fn bikeshed_try_into_aligned(
726752
self,
727-
) -> Result<Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>, AlignmentError<Self, T>>
753+
) -> Result<Ptr<'a, T, I::WithAlignment<Aligned>>, AlignmentError<Self, T>>
728754
where
729755
T: Sized,
730756
{
@@ -742,9 +768,7 @@ mod _transitions {
742768
#[inline]
743769
// TODO(#859): Reconsider the name of this method before making it
744770
// public.
745-
pub(crate) const fn bikeshed_recall_aligned(
746-
self,
747-
) -> Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>
771+
pub(crate) const fn bikeshed_recall_aligned(self) -> Ptr<'a, T, I::WithAlignment<Aligned>>
748772
where
749773
T: crate::Unaligned,
750774
{
@@ -763,9 +787,7 @@ mod _transitions {
763787
#[doc(hidden)]
764788
#[must_use]
765789
#[inline]
766-
pub const unsafe fn assume_validity<V: Validity>(
767-
self,
768-
) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> {
790+
pub const unsafe fn assume_validity<V: Validity>(self) -> Ptr<'a, T, I::WithValidity<V>> {
769791
// SAFETY: The caller promises that `self`'s referent conforms to
770792
// the validity requirement of `V`.
771793
unsafe { self.assume_invariants() }
@@ -780,9 +802,7 @@ mod _transitions {
780802
#[doc(hidden)]
781803
#[must_use]
782804
#[inline]
783-
pub const unsafe fn assume_initialized(
784-
self,
785-
) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> {
805+
pub const unsafe fn assume_initialized(self) -> Ptr<'a, T, I::WithValidity<Initialized>> {
786806
// SAFETY: The caller has promised to uphold the safety
787807
// preconditions.
788808
unsafe { self.assume_validity::<Initialized>() }
@@ -797,7 +817,7 @@ mod _transitions {
797817
#[doc(hidden)]
798818
#[must_use]
799819
#[inline]
800-
pub const unsafe fn assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> {
820+
pub const unsafe fn assume_valid(self) -> Ptr<'a, T, I::WithValidity<Valid>> {
801821
// SAFETY: The caller has promised to uphold the safety
802822
// preconditions.
803823
unsafe { self.assume_validity::<Valid>() }
@@ -809,7 +829,7 @@ mod _transitions {
809829
#[inline]
810830
// TODO(#859): Reconsider the name of this method before making it
811831
// public.
812-
pub const fn bikeshed_recall_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>
832+
pub const fn bikeshed_recall_valid(self) -> Ptr<'a, T, I::WithValidity<Valid>>
813833
where
814834
T: crate::FromBytes,
815835
I: Invariants<Validity = Initialized>,
@@ -836,7 +856,7 @@ mod _transitions {
836856
#[inline]
837857
pub(crate) fn try_into_valid(
838858
mut self,
839-
) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>, ValidityError<Self, T>>
859+
) -> Result<Ptr<'a, T, I::WithValidity<Valid>>, ValidityError<Self, T>>
840860
where
841861
T: TryFromBytes,
842862
I::Aliasing: Reference,
@@ -845,7 +865,7 @@ mod _transitions {
845865
// This call may panic. If that happens, it doesn't cause any soundness
846866
// issues, as we have not generated any invalid state which we need to
847867
// fix before returning.
848-
if T::is_bit_valid(self.reborrow().forget_aligned()) {
868+
if T::is_bit_valid(self.reborrow().forget_aligned().unify_invariants()) {
849869
// SAFETY: If `T::is_bit_valid`, code may assume that `self`
850870
// contains a bit-valid instance of `Self`.
851871
Ok(unsafe { self.assume_valid() })
@@ -858,7 +878,7 @@ mod _transitions {
858878
#[doc(hidden)]
859879
#[must_use]
860880
#[inline]
861-
pub const fn forget_aligned(self) -> Ptr<'a, T, (I::Aliasing, Any, I::Validity)> {
881+
pub const fn forget_aligned(self) -> Ptr<'a, T, I::WithAlignment<Any>> {
862882
// SAFETY: `Any` is less restrictive than `Aligned`.
863883
unsafe { self.assume_invariants() }
864884
}

0 commit comments

Comments
 (0)