@@ -377,7 +377,7 @@ mod _conversions {
377
377
// byte ranges. Since `p` and the returned pointer address the
378
378
// same byte range, they refer to `UnsafeCell`s at the same byte
379
379
// 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) ) } ;
381
381
// SAFETY: By invariant on `TransparentWrapper`, since `self`
382
382
// satisfies the alignment invariant `I::Alignment`, `c` (of type
383
383
// `T::Inner`) satisfies the given "applied" alignment invariant.
@@ -411,7 +411,7 @@ mod _conversions {
411
411
// `UnsafeCell`s at the same locations as `p`.
412
412
let ptr = unsafe {
413
413
#[ 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 > )
415
415
} ;
416
416
// SAFETY: `Unalign<T>` promises to have the same bit validity as
417
417
// `T`.
@@ -651,13 +651,14 @@ mod _transitions {
651
651
/// On error, unsafe code may rely on this method's returned
652
652
/// `ValidityError` containing `self`.
653
653
#[ inline]
654
- pub ( crate ) fn try_into_valid (
654
+ pub ( crate ) fn try_into_valid < R > (
655
655
mut self ,
656
656
) -> Result < Ptr < ' a , T , I :: WithValidity < Valid > > , ValidityError < Self , T > >
657
657
where
658
- T : TryFromBytes ,
658
+ T : TryFromBytes + Read < I :: Aliasing , R > ,
659
659
I :: Aliasing : Reference ,
660
660
I : Invariants < Validity = Initialized > ,
661
+ R : crate :: pointer:: ReadReason ,
661
662
{
662
663
// This call may panic. If that happens, it doesn't cause any soundness
663
664
// issues, as we have not generated any invalid state which we need to
@@ -685,14 +686,19 @@ mod _transitions {
685
686
/// Casts of the referent type.
686
687
mod _casts {
687
688
use super :: * ;
688
- use crate :: { pointer :: invariant :: aliasing_safety :: * , CastError , SizeError } ;
689
+ use crate :: { CastError , SizeError } ;
689
690
690
691
impl < ' a , T , I > Ptr < ' a , T , I >
691
692
where
692
693
T : ' a + ?Sized ,
693
694
I : Invariants ,
694
695
{
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
696
702
///
697
703
/// # Safety
698
704
///
@@ -705,7 +711,7 @@ mod _casts {
705
711
/// exist in `*p`
706
712
#[ doc( hidden) ]
707
713
#[ 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 > (
709
715
self ,
710
716
cast : F ,
711
717
) -> Ptr < ' a , U , ( I :: Aliasing , Any , Any ) > {
@@ -767,6 +773,34 @@ mod _casts {
767
773
// 8. `ptr`, trivially, conforms to the validity invariant of `Any`.
768
774
unsafe { Ptr :: new ( ptr) }
769
775
}
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
+ }
770
804
}
771
805
772
806
impl < ' a , T , I > Ptr < ' a , T , I >
@@ -778,8 +812,9 @@ mod _casts {
778
812
#[ allow( clippy:: wrong_self_convention) ]
779
813
pub ( crate ) fn as_bytes < R > ( self ) -> Ptr < ' a , [ u8 ] , ( I :: Aliasing , Aligned , Valid ) >
780
814
where
781
- [ u8 ] : AliasingSafe < T , I :: Aliasing , R > ,
782
- R : AliasingSafeReason ,
815
+ R : ReadReason ,
816
+ T : Read < I :: Aliasing , R > ,
817
+ I :: Aliasing : Reference ,
783
818
{
784
819
let bytes = match T :: size_of_val_raw ( self . as_inner ( ) . as_non_null ( ) ) {
785
820
Some ( bytes) => bytes,
@@ -796,10 +831,6 @@ mod _casts {
796
831
// pointer's address, and `bytes` is the length of `p`, so the
797
832
// returned pointer addresses the same bytes as `p`
798
833
// - `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
803
834
let ptr: Ptr < ' a , [ u8 ] , _ > = unsafe {
804
835
self . cast_unsized ( |p : * mut T | {
805
836
#[ allow( clippy:: as_conversions) ]
@@ -878,9 +909,9 @@ mod _casts {
878
909
CastError < Self , U > ,
879
910
>
880
911
where
881
- R : AliasingSafeReason ,
912
+ R : ReadReason ,
882
913
I :: Aliasing : Reference ,
883
- U : ' a + ?Sized + KnownLayout + AliasingSafe < [ u8 ] , I :: Aliasing , R > ,
914
+ U : ' a + ?Sized + KnownLayout + Read < I :: Aliasing , R > ,
884
915
{
885
916
let ( inner, remainder) =
886
917
self . as_inner ( ) . try_cast_into ( cast_type, meta) . map_err ( |err| {
@@ -893,12 +924,13 @@ mod _casts {
893
924
} ) ?;
894
925
895
926
// SAFETY:
896
- // 0. Since `U: AliasingSafe<[u8], I::Aliasing, _>`, either:
927
+ // 0. Since `U: Read< I::Aliasing, _>`, either:
897
928
// - `I::Aliasing` is `Exclusive`, in which case both `src` and
898
929
// `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.
902
934
// 1. `ptr` conforms to the alignment invariant of `Aligned` because
903
935
// it is derived from `try_cast_into`, which promises that the
904
936
// object described by `target` is validly aligned for `U`.
@@ -939,8 +971,8 @@ mod _casts {
939
971
) -> Result < Ptr < ' a , U , ( I :: Aliasing , Aligned , Initialized ) > , CastError < Self , U > >
940
972
where
941
973
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 ,
944
976
{
945
977
match self . try_cast_into ( CastType :: Prefix , meta) {
946
978
Ok ( ( slf, remainder) ) => {
@@ -984,11 +1016,8 @@ mod _casts {
984
1016
#[ must_use]
985
1017
#[ inline( always) ]
986
1018
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.
992
1021
#[ allow( clippy:: as_conversions) ]
993
1022
let ptr = unsafe { self . cast_unsized ( |p| p as * mut T ) } ;
994
1023
@@ -1034,7 +1063,8 @@ mod _project {
1034
1063
///
1035
1064
/// # Safety
1036
1065
///
1037
- /// `project` has the same safety preconditions as `cast_unsized`.
1066
+ /// `project` has the same safety preconditions as
1067
+ /// `cast_unsized_unchecked`.
1038
1068
#[ doc( hidden) ]
1039
1069
#[ inline]
1040
1070
pub unsafe fn project < U : ' a + ?Sized > (
@@ -1046,8 +1076,8 @@ mod _project {
1046
1076
// `Initialized` pointer, we could remove this method entirely.
1047
1077
1048
1078
// 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) } ;
1051
1081
1052
1082
// SAFETY: If all of the bytes of `self` are initialized (as
1053
1083
// promised by `I: Invariants<Validity = Initialized>`), then any
0 commit comments