@@ -172,7 +172,10 @@ mod _external {
172172/// Methods for converting to and from `Ptr` and Rust's safe reference types.
173173mod _conversions {
174174 use super :: * ;
175- use crate :: util:: { AlignmentVariance , Covariant , TransparentWrapper , ValidityVariance } ;
175+ use crate :: {
176+ pointer:: transmute:: { CastFrom , TransmuteFromAlignment , TransmuteFromPtr } ,
177+ util:: { AlignmentVariance , Covariant , TransparentWrapper , ValidityVariance } ,
178+ } ;
176179
177180 /// `&'a T` → `Ptr<'a, T>`
178181 impl < ' a , T : ?Sized > Ptr < ' a , Valid < T > , ( Shared , Aligned ) > {
@@ -338,6 +341,54 @@ mod _conversions {
338341 }
339342 }
340343
344+ /// `Ptr<'a, T>` → `Ptr<'a, U>`
345+ impl < ' a , V , I > Ptr < ' a , V , I >
346+ where
347+ V : Validity ,
348+ I : Invariants ,
349+ {
350+ /// # Safety
351+ /// - TODO: `UnsafeCell` agreement
352+ /// - The caller promises that the returned `Ptr` satisfies alignment
353+ /// `A`
354+ /// - The caller promises that the returned `Ptr` satisfies validity `V`
355+ pub ( crate ) unsafe fn transmute_unchecked < U , A > ( self ) -> Ptr < ' a , U , ( I :: Aliasing , A ) >
356+ where
357+ A : Alignment ,
358+ U : Validity ,
359+ U :: Inner : CastFrom < V :: Inner > ,
360+ {
361+ // SAFETY:
362+ // - By invariant on `CastFrom::cast_from`:
363+ // - This cast preserves address and referent size, and thus the
364+ // returned pointer addresses the same bytes as `p`
365+ // - This cast preserves provenance
366+ // - TODO: `UnsafeCell` agreement
367+ let ptr =
368+ unsafe { self . cast_unsized_unchecked :: < U :: Inner , _ > ( |p| U :: Inner :: cast_from ( p) ) } ;
369+ // SAFETY: The caller promises that alignment is satisfied.
370+ let ptr = unsafe { ptr. assume_alignment ( ) } ;
371+ // SAFETY: The caller promises that validity is satisfied.
372+ let ptr = unsafe { ptr. assume_validity :: < U > ( ) } ;
373+ ptr. unify_validity ( )
374+ }
375+
376+ pub ( crate ) fn transmute < U , A , RT , RA > ( self ) -> Ptr < ' a , U , ( I :: Aliasing , A ) >
377+ where
378+ A : Alignment ,
379+ U : TransmuteFromPtr < V , I :: Aliasing , RT > ,
380+ U :: Inner : TransmuteFromAlignment < U :: Inner , I :: Alignment , A , RA > + CastFrom < V :: Inner > ,
381+ {
382+ // SAFETY:
383+ // - TODO: `UnsafeCell` agreement
384+ // - By invariant on `TransmuteFromPtr`, it is sound to treat the
385+ // resulting pointer as having alignment `A`
386+ // - By invariant on `TransmuteFromPtr`, it is sound to treat the
387+ // resulting pointer as having validity `V`
388+ unsafe { self . transmute_unchecked ( ) }
389+ }
390+ }
391+
341392 /// `Ptr<'a, T = Wrapper<U>>` → `Ptr<'a, U>`
342393 impl < ' a , V , I > Ptr < ' a , V , I >
343394 where
@@ -429,7 +480,11 @@ mod _conversions {
429480/// State transitions between invariants.
430481mod _transitions {
431482 use super :: * ;
432- use crate :: { AlignmentError , TryFromBytes , ValidityError } ;
483+ use crate :: {
484+ error:: TryCastError ,
485+ pointer:: transmute:: { CastFrom , TransmuteFromPtr , TryTransmuteFromPtr } ,
486+ AlignmentError , TryFromBytes , ValidityError ,
487+ } ;
433488
434489 impl < ' a , V , I > Ptr < ' a , V , I >
435490 where
@@ -650,6 +705,22 @@ mod _transitions {
650705 }
651706 }
652707
708+ impl < ' a , V , I > Ptr < ' a , V , I >
709+ where
710+ V : Validity ,
711+ I : Invariants ,
712+ I :: Aliasing : Reference ,
713+ {
714+ /// Forgets that `self` is an `Exclusive` pointer, downgrading it to a
715+ /// `Shared` pointer.
716+ #[ doc( hidden) ]
717+ #[ must_use]
718+ #[ inline]
719+ pub const fn forget_exclusive ( self ) -> Ptr < ' a , V , I :: WithAliasing < Shared > > {
720+ unsafe { self . assume_invariants ( ) }
721+ }
722+ }
723+
653724 impl < ' a , T , I > Ptr < ' a , Initialized < T > , I >
654725 where
655726 T : ?Sized ,
@@ -661,14 +732,11 @@ mod _transitions {
661732 #[ inline]
662733 // TODO(#859): Reconsider the name of this method before making it
663734 // public.
664- pub const fn bikeshed_recall_valid ( self ) -> Ptr < ' a , Valid < T > , I >
735+ pub fn bikeshed_recall_valid ( self ) -> Ptr < ' a , Valid < T > , I >
665736 where
666- T : crate :: FromBytes ,
737+ T : crate :: FromBytes + crate :: IntoBytes ,
667738 {
668- // SAFETY: The bound `T: FromBytes` ensures that any initialized
669- // sequence of bytes is bit-valid for `T`. `V = Initialized<T>`
670- // ensures that all of the referent bytes are initialized.
671- unsafe { self . assume_valid ( ) }
739+ self . transmute ( ) . unify_invariants ( )
672740 }
673741
674742 /// Checks that `self`'s referent is validly initialized for `T`,
@@ -688,7 +756,12 @@ mod _transitions {
688756 mut self ,
689757 ) -> Result < Ptr < ' a , Valid < T > , I > , ValidityError < Self , T > >
690758 where
691- T : TryFromBytes + Read < I :: Aliasing , R > ,
759+ T : TryFromBytes , // + Read<I::Aliasing, R>,
760+ Valid < T > : TryTransmuteFromPtr < Initialized < T > , I :: Aliasing , R > ,
761+ // NOTE: This bound ought to be implied, but leaving it out causes
762+ // Rust to infinite loop during trait solving.
763+ <Valid < T > as Validity >:: Inner :
764+ crate :: pointer:: transmute:: CastFrom < <Initialized < T > as Validity >:: Inner > ,
692765 I :: Aliasing : Reference ,
693766 {
694767 // This call may panic. If that happens, it doesn't cause any soundness
@@ -703,6 +776,64 @@ mod _transitions {
703776 }
704777 }
705778 }
779+
780+ impl < ' a , V , I > Ptr < ' a , V , I >
781+ where
782+ V : Validity ,
783+ I : Invariants ,
784+ {
785+ /// Attempts to transmute a `Ptr<T>` into a `Ptr<U>`.
786+ ///
787+ /// # Panics
788+ ///
789+ /// This method will panic if
790+ /// [`U::is_bit_valid`][TryFromBytes::is_bit_valid] panics.
791+ ///
792+ /// # Safety
793+ ///
794+ /// On error, unsafe code may rely on this method's returned
795+ /// `ValidityError` containing `self`.
796+ #[ inline]
797+ pub ( crate ) fn try_transmute < U , A , R , RR > (
798+ mut self ,
799+ ) -> Result < Ptr < ' a , U , I :: WithAlignment < A > > , TryCastError < Self , U :: Inner > >
800+ where
801+ U : Validity + TryTransmuteFromPtr < V , I :: Aliasing , R > ,
802+ U :: Inner : TryFromBytes + CastFrom < V :: Inner > ,
803+ Initialized < U :: Inner > : TransmuteFromPtr < V , I :: Aliasing , RR > ,
804+ // TODO: The `Sized` bound here is only required in order to call
805+ // `.bikeshed_try_into_aligned`. There are other ways of getting the
806+ // alignment of a type, and we could use these if we need to drop
807+ // this bound.
808+ <Initialized < U :: Inner > as Validity >:: Inner : Sized + CastFrom < V :: Inner > ,
809+ I :: Aliasing : Reference ,
810+ A : Alignment ,
811+ {
812+ // TODO: Validate alignment
813+ if true {
814+ todo ! ( )
815+ }
816+
817+ let is_bit_valid = {
818+ let ptr = self . reborrow ( ) ;
819+ let mut ptr = ptr. transmute :: < Initialized < U :: Inner > , Unknown , _ , _ > ( ) ;
820+ if let Err ( err) = ptr. reborrow ( ) . bikeshed_try_into_aligned ( ) {
821+ return Err ( todo ! ( ) ) ;
822+ }
823+ // This call may panic. If that happens, it doesn't cause any
824+ // soundness issues, as we have not generated any invalid state
825+ // which we need to fix before returning.
826+ <U :: Inner as TryFromBytes >:: is_bit_valid ( ptr)
827+ } ;
828+
829+ if is_bit_valid {
830+ let ptr = unsafe { self . transmute_unchecked ( ) } ;
831+ Ok ( ptr. unify_invariants ( ) )
832+ } else {
833+ Err ( ValidityError :: new ( self ) . into ( ) )
834+ }
835+ }
836+ }
706837}
707838
708839/// Casts of the referent type.
0 commit comments