@@ -12,9 +12,12 @@ use core::{
1212 ptr:: NonNull ,
1313} ;
1414
15- use super :: { inner:: PtrInner , invariant:: * } ;
1615use crate :: {
17- util:: { AlignmentVariance , Covariant , TransparentWrapper , ValidityVariance } ,
16+ pointer:: {
17+ inner:: PtrInner ,
18+ invariant:: * ,
19+ transmute:: { MutationCompatible , TransmuteFromPtr } ,
20+ } ,
1821 AlignmentError , CastError , CastType , KnownLayout , SizeError , TryFromBytes , ValidityError ,
1922} ;
2023
@@ -383,53 +386,31 @@ mod _conversions {
383386 }
384387 }
385388
386- /// `Ptr<'a, T = Wrapper<U>>` → `Ptr<'a, U>`
387- impl < ' a , T , I > Ptr < ' a , T , I >
388- where
389- T : ' a + TransparentWrapper < I , UnsafeCellVariance = Covariant > + ?Sized ,
390- I : Invariants ,
391- {
392- /// Converts `self` to a transparent wrapper type into a `Ptr` to the
393- /// wrapped inner type.
394- pub ( crate ) fn transparent_wrapper_into_inner (
395- self ,
396- ) -> Ptr <
397- ' a ,
398- T :: Inner ,
399- (
400- I :: Aliasing ,
401- <T :: AlignmentVariance as AlignmentVariance < I :: Alignment > >:: Applied ,
402- <T :: ValidityVariance as ValidityVariance < I :: Validity > >:: Applied ,
403- ) ,
404- > {
405- // SAFETY:
406- // - By invariant on `TransparentWrapper::cast_into_inner`:
407- // - This cast preserves address and referent size, and thus the
408- // returned pointer addresses the same bytes as `p`
409- // - This cast preserves provenance
410- // - By invariant on `TransparentWrapper<UnsafeCellVariance =
411- // Covariant>`, `T` and `T::Inner` have `UnsafeCell`s at the same
412- // byte ranges. Since `p` and the returned pointer address the
413- // same byte range, they refer to `UnsafeCell`s at the same byte
414- // ranges.
415- // - By invariant on `TransparentWrapper`, since `self` satisfies
416- // the validity invariant `I::Validity`, the returned pointer (of
417- // type `T::Inner`) satisfies the given "applied" validity
418- // invariant.
419- let ptr = unsafe { self . transmute_unchecked ( |p| T :: cast_into_inner ( p) ) } ;
420- // SAFETY: By invariant on `TransparentWrapper`, since `self`
421- // satisfies the alignment invariant `I::Alignment`, the returned
422- // pointer (of type `T::Inner`) satisfies the given "applied"
423- // alignment invariant.
424- unsafe { ptr. assume_alignment ( ) }
425- }
426- }
427-
428389 /// `Ptr<'a, T>` → `Ptr<'a, U>`
429390 impl < ' a , T : ?Sized , I > Ptr < ' a , T , I >
430391 where
431392 I : Invariants ,
432393 {
394+ pub ( crate ) fn transmute < U , V , R > ( self ) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , V ) >
395+ where
396+ T : KnownLayout ,
397+ V : Validity ,
398+ U : TransmuteFromPtr < T , I :: Aliasing , I :: Validity , V , R >
399+ + KnownLayout < PointerMetadata = T :: PointerMetadata >
400+ + ?Sized ,
401+ {
402+ unsafe { self . transmute_unchecked ( |t : NonNull < T > | U :: cast_from_raw ( t) ) }
403+ }
404+
405+ pub ( crate ) fn transmute_sized < U , V , R > ( self ) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , V ) >
406+ where
407+ T : Sized ,
408+ V : Validity ,
409+ U : TransmuteFromPtr < T , I :: Aliasing , I :: Validity , V , R > ,
410+ {
411+ unsafe { self . transmute_unchecked ( cast ! ( ) ) }
412+ }
413+
433414 /// Casts to a different (unsized) target type without checking interior
434415 /// mutability.
435416 ///
@@ -460,14 +441,9 @@ mod _conversions {
460441 ) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , V ) >
461442 where
462443 V : Validity ,
463- F : FnOnce ( * mut T ) -> * mut U ,
444+ F : FnOnce ( NonNull < T > ) -> NonNull < U > ,
464445 {
465- let ptr = cast ( self . as_inner ( ) . as_non_null ( ) . as_ptr ( ) ) ;
466-
467- // SAFETY: Caller promises that `cast` returns a pointer whose
468- // address is in the range of `self.as_inner().as_non_null()`'s referent. By
469- // invariant, none of these addresses are null.
470- let ptr = unsafe { NonNull :: new_unchecked ( ptr) } ;
446+ let ptr = cast ( self . as_inner ( ) . as_non_null ( ) ) ;
471447
472448 // SAFETY:
473449 //
@@ -552,7 +528,7 @@ mod _conversions {
552528 // validity of the other.
553529 let ptr = unsafe {
554530 #[ allow( clippy:: as_conversions) ]
555- self . transmute_unchecked ( | p : * mut T | p as * mut crate :: Unalign < T > )
531+ self . transmute_unchecked ( NonNull :: cast :: < crate :: Unalign < T > > )
556532 } ;
557533 ptr. bikeshed_recall_aligned ( )
558534 }
@@ -561,6 +537,8 @@ mod _conversions {
561537
562538/// State transitions between invariants.
563539mod _transitions {
540+ use crate :: pointer:: transmute:: TryTransmuteFromPtr ;
541+
564542 use super :: * ;
565543
566544 impl < ' a , T , I > Ptr < ' a , T , I >
@@ -819,14 +797,11 @@ mod _transitions {
819797 #[ inline]
820798 // TODO(#859): Reconsider the name of this method before making it
821799 // public.
822- pub fn bikeshed_recall_valid ( self ) -> Ptr < ' a , T , ( I :: Aliasing , I :: Alignment , Valid ) >
800+ pub fn bikeshed_recall_valid < R > ( self ) -> Ptr < ' a , T , ( I :: Aliasing , I :: Alignment , Valid ) >
823801 where
824- T : crate :: FromBytes ,
802+ T : crate :: FromBytes + TryTransmuteFromPtr < T , I :: Aliasing , I :: Validity , Valid , R > ,
825803 I : Invariants < Validity = Initialized > ,
826804 {
827- // TODO(#1866): Fix this unsoundness.
828-
829- // SAFETY: This is unsound!
830805 unsafe { self . assume_valid ( ) }
831806 }
832807
@@ -843,24 +818,24 @@ mod _transitions {
843818 /// On error, unsafe code may rely on this method's returned
844819 /// `ValidityError` containing `self`.
845820 #[ inline]
846- pub ( crate ) fn try_into_valid < R > (
821+ pub ( crate ) fn try_into_valid < R , S > (
847822 mut self ,
848823 ) -> Result < Ptr < ' a , T , ( I :: Aliasing , I :: Alignment , Valid ) > , ValidityError < Self , T > >
849824 where
850- T : TryFromBytes + Read < I :: Aliasing , R > ,
825+ T : TryFromBytes
826+ + Read < I :: Aliasing , R >
827+ + TryTransmuteFromPtr < T , I :: Aliasing , I :: Validity , Valid , S > ,
851828 I :: Aliasing : Reference ,
852829 I : Invariants < Validity = Initialized > ,
853830 {
854831 // This call may panic. If that happens, it doesn't cause any soundness
855832 // issues, as we have not generated any invalid state which we need to
856833 // fix before returning.
857834 if T :: is_bit_valid ( self . reborrow ( ) . forget_aligned ( ) ) {
858- // SAFETY: If `T::is_bit_valid`, code may assume that `self`
859- // contains a bit-valid instance of `Self`.
835+ // TODO: Complete this safety comment.
860836 //
861- // TODO(#1866): This is unsound! The returned `Ptr` may permit
862- // writing referents which do not satisfy the `Initialized`
863- // validity invariant of `self`.
837+ // If `T::is_bit_valid`, code may assume that `self` contains a
838+ // bit-valid instance of `Self`.
864839 Ok ( unsafe { self . assume_valid ( ) } )
865840 } else {
866841 Err ( ValidityError :: new ( self ) )
@@ -902,9 +877,10 @@ mod _casts {
902877 /// - `u` has the same provenance as `p`
903878 /// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist
904879 /// at ranges identical to those at which `UnsafeCell`s exist in `*p`
880+ /// TODO: UnsafeCell compatibility
905881 #[ doc( hidden) ]
906882 #[ inline]
907- pub unsafe fn cast_unsized_unchecked < U , F : FnOnce ( * mut T ) -> * mut U > (
883+ pub ( crate ) unsafe fn cast_unsized_unchecked < U , F : FnOnce ( NonNull < T > ) -> NonNull < U > > (
908884 self ,
909885 cast : F ,
910886 ) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , I :: Validity ) >
@@ -940,20 +916,28 @@ mod _casts {
940916 /// - `u` has the same provenance as `p`
941917 #[ doc( hidden) ]
942918 #[ inline]
943- pub unsafe fn cast_unsized < U , F , R , S > (
919+ pub unsafe fn cast_unsized < U , F , R > (
944920 self ,
945921 cast : F ,
946922 ) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , I :: Validity ) >
947923 where
948- T : Read < I :: Aliasing , R > ,
949- U : ' a + ?Sized + Read < I :: Aliasing , S > + CastableFrom < T , I :: Validity , I :: Validity > ,
950- F : FnOnce ( * mut T ) -> * mut U ,
924+ T : MutationCompatible < U , I :: Aliasing , I :: Validity , I :: Validity , R > ,
925+ U : ' a + ?Sized + CastableFrom < T , I :: Validity , I :: Validity > ,
926+ F : FnOnce ( NonNull < T > ) -> NonNull < U > ,
951927 {
952- // SAFETY: Because `T` and `U` both implement `Read<I::Aliasing, _>`,
953- // either:
954- // - `I::Aliasing` is `Exclusive`
955- // - `T` and `U` are both `Immutable`, in which case they trivially
956- // contain `UnsafeCell`s at identical locations
928+ // SAFETY: Because `T: MutationCompatible<U, I::Aliasing, R>`, one
929+ // of the following holds:
930+ // - `T: Read<I::Aliasing>` and `U: Read<I::Aliasing>`, in which
931+ // case one of the following holds:
932+ // - `I::Aliasing` is `Exclusive`
933+ // - `T` and `U` are both `Immutable`
934+ // - `T` and `U` contain `UnsafeCell`s at identical locations
935+ // TODO: This should also promise UnsafeCell compatibility
936+ //
937+ // In the first case, `I::Aliasing` is `Exclusive`, and in the
938+ // second and third case, `T` and `U` contain `UnsafeCell`s at
939+ // identical locations (in the second case, this is because `T` and
940+ // `U` contain no `UnsafeCell`s at all).
957941 //
958942 // The caller promises all other safety preconditions.
959943 unsafe { self . cast_unsized_unchecked ( cast) }
@@ -988,9 +972,8 @@ mod _casts {
988972 // returned pointer addresses the same bytes as `p`
989973 // - `slice_from_raw_parts_mut` and `.cast` both preserve provenance
990974 let ptr: Ptr < ' a , [ u8 ] , _ > = unsafe {
991- self . cast_unsized ( |p : * mut T | {
992- #[ allow( clippy:: as_conversions) ]
993- core:: ptr:: slice_from_raw_parts_mut ( p. cast :: < u8 > ( ) , bytes)
975+ self . cast_unsized ( |p : NonNull < T > | {
976+ core:: ptr:: NonNull :: slice_from_raw_parts ( p. cast :: < u8 > ( ) , bytes)
994977 } )
995978 } ;
996979
@@ -1214,7 +1197,7 @@ mod _casts {
12141197 // inner type `T`. A consequence of this guarantee is that it is
12151198 // possible to convert between `T` and `UnsafeCell<T>`.
12161199 #[ allow( clippy:: as_conversions) ]
1217- let ptr = unsafe { self . transmute_unchecked ( |p| p as * mut T ) } ;
1200+ let ptr = unsafe { self . transmute_unchecked ( cast ! ( ) ) } ;
12181201
12191202 // SAFETY: `UnsafeCell<T>` has the same alignment as `T` [1],
12201203 // and so if `self` is guaranteed to be aligned, then so is the
@@ -1321,10 +1304,12 @@ mod tests {
13211304 } ;
13221305
13231306 // SAFETY: The bytes in `slf` must be initialized.
1324- unsafe fn validate_and_get_len < T : ?Sized + KnownLayout + FromBytes > (
1307+ unsafe fn validate_and_get_len <
1308+ T : ?Sized + KnownLayout + FromBytes + Immutable ,
1309+ > (
13251310 slf : Ptr < ' _ , T , ( Shared , Aligned , Initialized ) > ,
13261311 ) -> usize {
1327- let t = slf. bikeshed_recall_valid ( ) . as_ref ( ) ;
1312+ let t = slf. bikeshed_recall_valid :: < BecauseImmutable > ( ) . as_ref ( ) ;
13281313
13291314 let bytes = {
13301315 let len = mem:: size_of_val ( t) ;
0 commit comments