@@ -377,7 +377,7 @@ mod _conversions {
377377 // byte ranges. Since `p` and the returned pointer address the
378378 // same byte range, they refer to `UnsafeCell`s at the same byte
379379 // ranges.
380- let c = unsafe { self . cast_unsized ( |p| T :: cast_into_inner ( p) ) } ;
380+ let c = unsafe { self . cast_unsized_unchecked ( |p| T :: cast_into_inner ( p) ) } ;
381381 // SAFETY: By invariant on `TransparentWrapper`, since `self`
382382 // satisfies the alignment invariant `I::Alignment`, `c` (of type
383383 // `T::Inner`) satisfies the given "applied" alignment invariant.
@@ -411,7 +411,7 @@ mod _conversions {
411411 // `UnsafeCell`s at the same locations as `p`.
412412 let ptr = unsafe {
413413 #[ allow( clippy:: as_conversions) ]
414- self . cast_unsized ( |p : * mut T | p as * mut crate :: Unalign < T > )
414+ self . cast_unsized_unchecked ( |p : * mut T | p as * mut crate :: Unalign < T > )
415415 } ;
416416 // SAFETY: `Unalign<T>` promises to have the same bit validity as
417417 // `T`.
@@ -651,13 +651,14 @@ mod _transitions {
651651 /// On error, unsafe code may rely on this method's returned
652652 /// `ValidityError` containing `self`.
653653 #[ inline]
654- pub ( crate ) fn try_into_valid (
654+ pub ( crate ) fn try_into_valid < R > (
655655 mut self ,
656656 ) -> Result < Ptr < ' a , T , I :: WithValidity < Valid > > , ValidityError < Self , T > >
657657 where
658- T : TryFromBytes ,
658+ T : TryFromBytes + Read < I :: Aliasing , R > ,
659659 I :: Aliasing : Reference ,
660660 I : Invariants < Validity = Initialized > ,
661+ R : crate :: pointer:: ReadReason ,
661662 {
662663 // This call may panic. If that happens, it doesn't cause any soundness
663664 // issues, as we have not generated any invalid state which we need to
@@ -685,14 +686,19 @@ mod _transitions {
685686/// Casts of the referent type.
686687mod _casts {
687688 use super :: * ;
688- use crate :: { pointer :: invariant :: aliasing_safety :: * , CastError , SizeError } ;
689+ use crate :: { CastError , SizeError } ;
689690
690691 impl < ' a , T , I > Ptr < ' a , T , I >
691692 where
692693 T : ' a + ?Sized ,
693694 I : Invariants ,
694695 {
695- /// Casts to a different (unsized) target type.
696+ /// Casts to a different (unsized) target type without checking interior
697+ /// mutability.
698+ ///
699+ /// Callers should prefer [`cast_unsized`] where possible.
700+ ///
701+ /// [`cast_unsized`]: Ptr::cast_unsized
696702 ///
697703 /// # Safety
698704 ///
@@ -705,7 +711,7 @@ mod _casts {
705711 /// exist in `*p`
706712 #[ doc( hidden) ]
707713 #[ inline]
708- pub unsafe fn cast_unsized < U : ' a + ?Sized , F : FnOnce ( * mut T ) -> * mut U > (
714+ pub unsafe fn cast_unsized_unchecked < U : ' a + ?Sized , F : FnOnce ( * mut T ) -> * mut U > (
709715 self ,
710716 cast : F ,
711717 ) -> Ptr < ' a , U , ( I :: Aliasing , Any , Any ) > {
@@ -767,6 +773,34 @@ mod _casts {
767773 // 8. `ptr`, trivially, conforms to the validity invariant of `Any`.
768774 unsafe { Ptr :: new ( ptr) }
769775 }
776+
777+ /// Casts to a different (unsized) target type.
778+ ///
779+ /// # Safety
780+ ///
781+ /// The caller promises that `u = cast(p)` is a pointer cast with the
782+ /// following properties:
783+ /// - `u` addresses a subset of the bytes addressed by `p`
784+ /// - `u` has the same provenance as `p`
785+ #[ doc( hidden) ]
786+ #[ inline]
787+ pub unsafe fn cast_unsized < U , F , R , S > ( self , cast : F ) -> Ptr < ' a , U , ( I :: Aliasing , Any , Any ) >
788+ where
789+ T : Read < I :: Aliasing , R > ,
790+ U : ' a + ?Sized + Read < I :: Aliasing , S > ,
791+ R : ReadReason ,
792+ S : ReadReason ,
793+ F : FnOnce ( * mut T ) -> * mut U ,
794+ {
795+ // SAFETY: Because `T` and `U` both implement `Read<I::Aliasing, _>`,
796+ // either:
797+ // - `I::Aliasing` is `Exclusive`
798+ // - `T` and `U` are both `Immutable`, in which case they trivially
799+ // contain `UnsafeCell`s at identical locations
800+ //
801+ // The caller promises all other safety preconditions.
802+ unsafe { self . cast_unsized_unchecked ( cast) }
803+ }
770804 }
771805
772806 impl < ' a , T , I > Ptr < ' a , T , I >
@@ -778,8 +812,9 @@ mod _casts {
778812 #[ allow( clippy:: wrong_self_convention) ]
779813 pub ( crate ) fn as_bytes < R > ( self ) -> Ptr < ' a , [ u8 ] , ( I :: Aliasing , Aligned , Valid ) >
780814 where
781- [ u8 ] : AliasingSafe < T , I :: Aliasing , R > ,
782- R : AliasingSafeReason ,
815+ R : ReadReason ,
816+ T : Read < I :: Aliasing , R > ,
817+ I :: Aliasing : Reference ,
783818 {
784819 let bytes = match T :: size_of_val_raw ( self . as_inner ( ) . as_non_null ( ) ) {
785820 Some ( bytes) => bytes,
@@ -796,10 +831,6 @@ mod _casts {
796831 // pointer's address, and `bytes` is the length of `p`, so the
797832 // returned pointer addresses the same bytes as `p`
798833 // - `slice_from_raw_parts_mut` and `.cast` both preserve provenance
799- // - Because `[u8]: AliasingSafe<T, I::Aliasing, _>`, either:
800- // - `I::Aliasing` is `Exclusive`
801- // - `T` and `[u8]` are both `Immutable`, in which case they
802- // trivially contain `UnsafeCell`s at identical locations
803834 let ptr: Ptr < ' a , [ u8 ] , _ > = unsafe {
804835 self . cast_unsized ( |p : * mut T | {
805836 #[ allow( clippy:: as_conversions) ]
@@ -878,9 +909,9 @@ mod _casts {
878909 CastError < Self , U > ,
879910 >
880911 where
881- R : AliasingSafeReason ,
912+ R : ReadReason ,
882913 I :: Aliasing : Reference ,
883- U : ' a + ?Sized + KnownLayout + AliasingSafe < [ u8 ] , I :: Aliasing , R > ,
914+ U : ' a + ?Sized + KnownLayout + Read < I :: Aliasing , R > ,
884915 {
885916 let ( inner, remainder) =
886917 self . as_inner ( ) . try_cast_into ( cast_type, meta) . map_err ( |err| {
@@ -893,12 +924,13 @@ mod _casts {
893924 } ) ?;
894925
895926 // SAFETY:
896- // 0. Since `U: AliasingSafe<[u8], I::Aliasing, _>`, either:
927+ // 0. Since `U: Read< I::Aliasing, _>`, either:
897928 // - `I::Aliasing` is `Exclusive`, in which case both `src` and
898929 // `ptr` conform to `Exclusive`
899- // - `I::Aliasing` is `Shared` or `Any` and both `U` and `[u8]`
900- // are `Immutable`. In this case, neither pointer permits
901- // mutation, and so `Shared` aliasing is satisfied.
930+ // - `I::Aliasing` is `Shared` or `Any` and `U` is `Immutable`
931+ // (we already know that `[u8]: Immutable`). In this case,
932+ // neither `U` nor `[u8]` permit mutation, and so `Shared`
933+ // aliasing is satisfied.
902934 // 1. `ptr` conforms to the alignment invariant of `Aligned` because
903935 // it is derived from `try_cast_into`, which promises that the
904936 // object described by `target` is validly aligned for `U`.
@@ -939,8 +971,8 @@ mod _casts {
939971 ) -> Result < Ptr < ' a , U , ( I :: Aliasing , Aligned , Initialized ) > , CastError < Self , U > >
940972 where
941973 I :: Aliasing : Reference ,
942- U : ' a + ?Sized + KnownLayout + AliasingSafe < [ u8 ] , I :: Aliasing , R > ,
943- R : AliasingSafeReason ,
974+ U : ' a + ?Sized + KnownLayout + Read < I :: Aliasing , R > ,
975+ R : ReadReason ,
944976 {
945977 match self . try_cast_into ( CastType :: Prefix , meta) {
946978 Ok ( ( slf, remainder) ) => {
@@ -984,11 +1016,8 @@ mod _casts {
9841016 #[ must_use]
9851017 #[ inline( always) ]
9861018 pub fn get_mut ( self ) -> Ptr < ' a , T , I > {
987- // SAFETY:
988- // - The closure uses an `as` cast, which preserves address range
989- // and provenance.
990- // - We require `I: Invariants<Aliasing = Exclusive>`, so we are not
991- // required to uphold `UnsafeCell` equality.
1019+ // SAFETY: The closure uses an `as` cast, which preserves address
1020+ // range and provenance.
9921021 #[ allow( clippy:: as_conversions) ]
9931022 let ptr = unsafe { self . cast_unsized ( |p| p as * mut T ) } ;
9941023
@@ -1034,7 +1063,8 @@ mod _project {
10341063 ///
10351064 /// # Safety
10361065 ///
1037- /// `project` has the same safety preconditions as `cast_unsized`.
1066+ /// `project` has the same safety preconditions as
1067+ /// `cast_unsized_unchecked`.
10381068 #[ doc( hidden) ]
10391069 #[ inline]
10401070 pub unsafe fn project < U : ' a + ?Sized > (
@@ -1046,8 +1076,8 @@ mod _project {
10461076 // `Initialized` pointer, we could remove this method entirely.
10471077
10481078 // SAFETY: This method has the same safety preconditions as
1049- // `cast_unsized `.
1050- let ptr = unsafe { self . cast_unsized ( projector) } ;
1079+ // `cast_unsized_unchecked `.
1080+ let ptr = unsafe { self . cast_unsized_unchecked ( projector) } ;
10511081
10521082 // SAFETY: If all of the bytes of `self` are initialized (as
10531083 // promised by `I: Invariants<Validity = Initialized>`), then any
0 commit comments