@@ -28,11 +28,7 @@ use core::{
2828} ;
2929
3030use crate :: {
31- pointer:: {
32- cast:: { CastSized , IdCast } ,
33- invariant:: { self , BecauseExclusive , BecauseImmutable , Invariants } ,
34- BecauseInvariantsEq , Read , TryTransmuteFromPtr ,
35- } ,
31+ pointer:: { cast:: CastSized , invariant, BecauseInvariantsEq } ,
3632 FromBytes , Immutable , IntoBytes , KnownLayout , Ptr , ReadOnly , TryFromBytes , ValidityError ,
3733} ;
3834
@@ -600,63 +596,6 @@ pub const fn hash_name(name: &str) -> i128 {
600596 i128:: from_ne_bytes ( hash. to_ne_bytes ( ) )
601597}
602598
603- /// Is a given source a valid instance of `Dst`?
604- ///
605- /// If so, returns `src` casted to a `Ptr<Dst, _>`. Otherwise returns `None`.
606- ///
607- /// # Safety
608- ///
609- /// Unsafe code may assume that, if `try_cast_or_pme(src)` returns `Ok`,
610- /// `*src` is a bit-valid instance of `Dst`, and that the size of `Src` is
611- /// greater than or equal to the size of `Dst`.
612- ///
613- /// Unsafe code may assume that, if `try_cast_or_pme(src)` returns `Err`, the
614- /// encapsulated `Ptr` value is the original `src`. `try_cast_or_pme` cannot
615- /// guarantee that the referent has not been modified, as it calls user-defined
616- /// code (`TryFromBytes::is_bit_valid`).
617- ///
618- /// # Panics
619- ///
620- /// `try_cast_or_pme` may either produce a post-monomorphization error or a
621- /// panic if `Dst` not the same size as `Src`. Otherwise, `try_cast_or_pme`
622- /// panics under the same circumstances as [`is_bit_valid`].
623- ///
624- /// [`is_bit_valid`]: TryFromBytes::is_bit_valid
625- #[ doc( hidden) ]
626- #[ inline]
627- fn try_cast_or_pme < Src , Dst , I , R , S > (
628- src : Ptr < ' _ , Src , I > ,
629- ) -> Result <
630- Ptr < ' _ , Dst , ( I :: Aliasing , invariant:: Unaligned , invariant:: Valid ) > ,
631- ValidityError < Ptr < ' _ , Src , I > , Dst > ,
632- >
633- where
634- // FIXME(#2226): There should be a `Src: FromBytes` bound here, but doing so
635- // requires deeper surgery.
636- Src : invariant:: Read < I :: Aliasing , R > ,
637- Dst : TryFromBytes
638- + invariant:: Read < I :: Aliasing , R >
639- + TryTransmuteFromPtr < Dst , I :: Aliasing , invariant:: Initialized , invariant:: Valid , IdCast , S > ,
640- ReadOnly < Dst > : Read < I :: Aliasing , R > ,
641- I : Invariants < Validity = invariant:: Initialized > ,
642- I :: Aliasing : invariant:: Reference ,
643- {
644- let c_ptr = src. cast :: < _ , CastSized , _ > ( ) ;
645- match c_ptr. try_into_valid ( ) {
646- Ok ( ptr) => Ok ( ptr) ,
647- Err ( err) => {
648- // Re-cast `Ptr<Dst>` to `Ptr<Src>`.
649- let ptr = err. into_src ( ) ;
650- let ptr = ptr. cast :: < _ , CastSized , _ > ( ) ;
651- // SAFETY: `ptr` is `src`, and has the same alignment invariant.
652- let ptr = unsafe { ptr. assume_alignment :: < I :: Alignment > ( ) } ;
653- // SAFETY: `ptr` is `src` and has the same validity invariant.
654- let ptr = unsafe { ptr. assume_validity :: < I :: Validity > ( ) } ;
655- Err ( ValidityError :: new ( ptr. unify_invariants ( ) ) )
656- }
657- }
658- }
659-
660599/// Attempts to transmute `Src` into `Dst`.
661600///
662601/// A helper for `try_transmute!`.
@@ -677,32 +616,28 @@ where
677616 static_assert ! ( Src , Dst => mem:: size_of:: <Dst >( ) == mem:: size_of:: <Src >( ) ) ;
678617
679618 let mu_src = mem:: MaybeUninit :: new ( src) ;
680- // SAFETY: By invariant on `&`, the following are satisfied:
681- // - `&mu_src` is valid for reads
682- // - `&mu_src` is properly aligned
683- // - `&mu_src`'s referent is bit-valid
684- let mu_src_copy = unsafe { core:: ptr:: read ( & mu_src) } ;
685- // SAFETY: `MaybeUninit` has no validity constraints.
619+ // SAFETY: `MaybeUninit` has no validity requirements.
686620 let mu_dst: mem:: MaybeUninit < ReadOnly < Dst > > =
687- unsafe { crate :: util:: transmute_unchecked ( mu_src_copy ) } ;
621+ unsafe { crate :: util:: transmute_unchecked ( mu_src ) } ;
688622
689623 let ptr = Ptr :: from_ref ( & mu_dst) ;
690624
691625 // SAFETY: Since `Src: IntoBytes`, and since `size_of::<Src>() ==
692626 // size_of::<Dst>()` by the preceding assertion, all of `mu_dst`'s bytes are
693- // initialized.
627+ // initialized. `MaybeUninit` has no validity requirements, so even if
628+ // `ptr` is used to mutate its referent (which it actually can't be - it's
629+ // a shared `ReadOnly` pointer), that won't violate its referent's validity.
694630 let ptr = unsafe { ptr. assume_validity :: < invariant:: Initialized > ( ) } ;
695-
696- let ptr: Ptr < ' _ , ReadOnly < Dst > , _ > = ptr. cast :: < _ , crate :: pointer:: cast:: CastSized , _ > ( ) ;
697-
698- if Dst :: is_bit_valid ( ptr. transmute :: < _ , _ , BecauseImmutable > ( ) . forget_aligned ( ) ) {
631+ if Dst :: is_bit_valid ( ptr. cast :: < _ , CastSized , _ > ( ) ) {
699632 // SAFETY: Since `Dst::is_bit_valid`, we know that `ptr`'s referent is
700633 // bit-valid for `Dst`. `ptr` points to `mu_dst`, and no intervening
701634 // operations have mutated it, so it is a bit-valid `Dst`.
702635 Ok ( ReadOnly :: into_inner ( unsafe { mu_dst. assume_init ( ) } ) )
703636 } else {
704- // SAFETY: `mu_src` was constructed from `src` and never modified, so it
705- // is still bit-valid.
637+ // SAFETY: `MaybeUninit` has no validity requirements.
638+ let mu_src: mem:: MaybeUninit < Src > = unsafe { crate :: util:: transmute_unchecked ( mu_dst) } ;
639+ // SAFETY: `mu_dst`/`mu_src` was constructed from `src` and never
640+ // modified, so it is still bit-valid.
706641 Err ( ValidityError :: new ( unsafe { mu_src. assume_init ( ) } ) )
707642 }
708643}
@@ -727,7 +662,8 @@ where
727662{
728663 let ptr = Ptr :: from_ref ( src) ;
729664 let ptr = ptr. recall_validity :: < invariant:: Initialized , _ > ( ) ;
730- match try_cast_or_pme :: < Src , Dst , _ , BecauseImmutable , _ > ( ptr) {
665+ let ptr = ptr. cast :: < _ , CastSized , _ > ( ) ;
666+ match ptr. try_into_valid ( ) {
731667 Ok ( ptr) => {
732668 static_assert ! ( Src , Dst => mem:: align_of:: <Dst >( ) <= mem:: align_of:: <Src >( ) ) ;
733669 // SAFETY: We have checked that `Dst` does not have a stricter
@@ -736,13 +672,17 @@ where
736672 Ok ( ptr. as_ref ( ) )
737673 }
738674 Err ( err) => Err ( err. map_src ( |ptr| {
675+ let ptr = ptr. cast :: < _ , CastSized , _ > ( ) ;
676+ // SAFETY: `ptr` has the same address as `src: &Src`, which is
677+ // aligned by invariant on `&Src`.
678+ let ptr = unsafe { ptr. assume_alignment :: < invariant:: Aligned > ( ) } ;
739679 // SAFETY: Because `Src: Immutable` and we create a `Ptr` via
740680 // `Ptr::from_ref`, the resulting `Ptr` is a shared-and-`Immutable`
741681 // `Ptr`, which does not permit mutation of its referent. Therefore,
742682 // no mutation could have happened during the call to
743- // `try_cast_or_pme ` (any such mutation would be unsound).
683+ // `try_into_valid ` (any such mutation would be unsound).
744684 //
745- // `try_cast_or_pme ` promises to return its original argument, and
685+ // `try_into_valid ` promises to return its original argument, and
746686 // so we know that we are getting back the same `ptr` that we
747687 // originally passed, and that `ptr` was a bit-valid `Src`.
748688 let ptr = unsafe { ptr. assume_valid ( ) } ;
@@ -771,7 +711,8 @@ where
771711{
772712 let ptr = Ptr :: from_mut ( src) ;
773713 let ptr = ptr. recall_validity :: < invariant:: Initialized , ( _ , ( _ , _ ) ) > ( ) ;
774- match try_cast_or_pme :: < Src , Dst , _ , BecauseExclusive , _ > ( ptr) {
714+ let ptr = ptr. cast :: < _ , CastSized , _ > ( ) ;
715+ match ptr. try_into_valid ( ) {
775716 Ok ( ptr) => {
776717 static_assert ! ( Src , Dst => mem:: align_of:: <Dst >( ) <= mem:: align_of:: <Src >( ) ) ;
777718 // SAFETY: We have checked that `Dst` does not have a stricter
@@ -780,7 +721,13 @@ where
780721 Ok ( ptr. as_mut ( ) )
781722 }
782723 Err ( err) => {
783- Err ( err. map_src ( |ptr| ptr. recall_validity :: < _ , ( _ , BecauseInvariantsEq ) > ( ) . as_mut ( ) ) )
724+ Err ( err. map_src ( |ptr| {
725+ let ptr = ptr. cast :: < _ , CastSized , _ > ( ) ;
726+ // SAFETY: `ptr` has the same address as `src: &mut Src`, which
727+ // is aligned by invariant on `&mut Src`.
728+ let ptr = unsafe { ptr. assume_alignment :: < invariant:: Aligned > ( ) } ;
729+ ptr. recall_validity :: < _ , ( _ , BecauseInvariantsEq ) > ( ) . as_mut ( )
730+ } ) )
784731 }
785732 }
786733}
@@ -895,15 +842,15 @@ where
895842
896843 #[ inline( always) ]
897844 fn transmute_ref ( self ) -> & ' a Dst {
898- static_assert ! ( Src : ?Sized + KnownLayout , Dst : ?Sized + KnownLayout => {
899- Src :: LAYOUT . align. get( ) >= Dst :: LAYOUT . align. get( )
900- } , "cannot transmute reference when destination type has higher alignment than source type" ) ;
901-
902845 let ptr = Ptr :: from_ref ( self . 0 )
903846 . recall_validity :: < invariant:: Initialized , _ > ( )
904847 . transmute_with :: < Dst , invariant:: Initialized , crate :: layout:: CastFrom < Dst > , ( crate :: pointer:: BecauseMutationCompatible , _ ) > ( )
905848 . recall_validity :: < invariant:: Valid , _ > ( ) ;
906849
850+ static_assert ! ( Src : ?Sized + KnownLayout , Dst : ?Sized + KnownLayout => {
851+ Src :: LAYOUT . align. get( ) >= Dst :: LAYOUT . align. get( )
852+ } , "cannot transmute reference when destination type has higher alignment than source type" ) ;
853+
907854 // SAFETY: The preceding `static_assert!` ensures that
908855 // `Src::LAYOUT.align >= Dst::LAYOUT.align`. Since `self` is
909856 // validly-aligned for `Src`, it is also validly-aligned for `Dst`.
@@ -928,16 +875,15 @@ where
928875
929876 #[ inline( always) ]
930877 fn transmute_mut ( self ) -> & ' a mut Dst {
931- static_assert ! ( Src : ?Sized + KnownLayout , Dst : ?Sized + KnownLayout => {
932- Src :: LAYOUT . align. get( ) >= Dst :: LAYOUT . align. get( )
933- } , "cannot transmute reference when destination type has higher alignment than source type" ) ;
934-
935878 let ptr = Ptr :: from_mut ( self . 0 )
936879 . recall_validity :: < invariant:: Initialized , ( _ , ( _ , _ ) ) > ( )
937880 . transmute_with :: < Dst , invariant:: Initialized , crate :: layout:: CastFrom < Dst > , _ > ( )
938881 . recall_validity :: < invariant:: Valid , ( _ , ( _ , _ ) ) > ( ) ;
939882
940- #[ allow( unused_unsafe) ]
883+ static_assert ! ( Src : ?Sized + KnownLayout , Dst : ?Sized + KnownLayout => {
884+ Src :: LAYOUT . align. get( ) >= Dst :: LAYOUT . align. get( )
885+ } , "cannot transmute reference when destination type has higher alignment than source type" ) ;
886+
941887 // SAFETY: The preceding `static_assert!` ensures that
942888 // `Src::LAYOUT.align >= Dst::LAYOUT.align`. Since `self` is
943889 // validly-aligned for `Src`, it is also validly-aligned for `Dst`.
0 commit comments