@@ -12,9 +12,12 @@ use core::{
12
12
ptr:: NonNull ,
13
13
} ;
14
14
15
- use super :: { inner:: PtrInner , invariant:: * } ;
16
15
use crate :: {
17
- util:: { AlignmentVariance , Covariant , TransparentWrapper , ValidityVariance } ,
16
+ pointer:: {
17
+ inner:: PtrInner ,
18
+ invariant:: * ,
19
+ transmute:: { MutationCompatible , TransmuteFromPtr } ,
20
+ } ,
18
21
AlignmentError , CastError , CastType , KnownLayout , SizeError , TryFromBytes , ValidityError ,
19
22
} ;
20
23
@@ -383,53 +386,31 @@ mod _conversions {
383
386
}
384
387
}
385
388
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
-
428
389
/// `Ptr<'a, T>` → `Ptr<'a, U>`
429
390
impl < ' a , T : ?Sized , I > Ptr < ' a , T , I >
430
391
where
431
392
I : Invariants ,
432
393
{
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
+
433
414
/// Casts to a different (unsized) target type without checking interior
434
415
/// mutability.
435
416
///
@@ -460,14 +441,9 @@ mod _conversions {
460
441
) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , V ) >
461
442
where
462
443
V : Validity ,
463
- F : FnOnce ( * mut T ) -> * mut U ,
444
+ F : FnOnce ( NonNull < T > ) -> NonNull < U > ,
464
445
{
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 ( ) ) ;
471
447
472
448
// SAFETY:
473
449
//
@@ -552,7 +528,7 @@ mod _conversions {
552
528
// validity of the other.
553
529
let ptr = unsafe {
554
530
#[ 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 > > )
556
532
} ;
557
533
ptr. bikeshed_recall_aligned ( )
558
534
}
@@ -561,6 +537,8 @@ mod _conversions {
561
537
562
538
/// State transitions between invariants.
563
539
mod _transitions {
540
+ use crate :: pointer:: transmute:: TryTransmuteFromPtr ;
541
+
564
542
use super :: * ;
565
543
566
544
impl < ' a , T , I > Ptr < ' a , T , I >
@@ -819,14 +797,11 @@ mod _transitions {
819
797
#[ inline]
820
798
// TODO(#859): Reconsider the name of this method before making it
821
799
// 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 ) >
823
801
where
824
- T : crate :: FromBytes ,
802
+ T : crate :: FromBytes + TryTransmuteFromPtr < T , I :: Aliasing , I :: Validity , Valid , R > ,
825
803
I : Invariants < Validity = Initialized > ,
826
804
{
827
- // TODO(#1866): Fix this unsoundness.
828
-
829
- // SAFETY: This is unsound!
830
805
unsafe { self . assume_valid ( ) }
831
806
}
832
807
@@ -843,24 +818,24 @@ mod _transitions {
843
818
/// On error, unsafe code may rely on this method's returned
844
819
/// `ValidityError` containing `self`.
845
820
#[ inline]
846
- pub ( crate ) fn try_into_valid < R > (
821
+ pub ( crate ) fn try_into_valid < R , S > (
847
822
mut self ,
848
823
) -> Result < Ptr < ' a , T , ( I :: Aliasing , I :: Alignment , Valid ) > , ValidityError < Self , T > >
849
824
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 > ,
851
828
I :: Aliasing : Reference ,
852
829
I : Invariants < Validity = Initialized > ,
853
830
{
854
831
// This call may panic. If that happens, it doesn't cause any soundness
855
832
// issues, as we have not generated any invalid state which we need to
856
833
// fix before returning.
857
834
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.
860
836
//
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`.
864
839
Ok ( unsafe { self . assume_valid ( ) } )
865
840
} else {
866
841
Err ( ValidityError :: new ( self ) )
@@ -902,9 +877,10 @@ mod _casts {
902
877
/// - `u` has the same provenance as `p`
903
878
/// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist
904
879
/// at ranges identical to those at which `UnsafeCell`s exist in `*p`
880
+ /// TODO: UnsafeCell compatibility
905
881
#[ doc( hidden) ]
906
882
#[ 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 > > (
908
884
self ,
909
885
cast : F ,
910
886
) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , I :: Validity ) >
@@ -940,20 +916,28 @@ mod _casts {
940
916
/// - `u` has the same provenance as `p`
941
917
#[ doc( hidden) ]
942
918
#[ inline]
943
- pub unsafe fn cast_unsized < U , F , R , S > (
919
+ pub unsafe fn cast_unsized < U , F , R > (
944
920
self ,
945
921
cast : F ,
946
922
) -> Ptr < ' a , U , ( I :: Aliasing , Unaligned , I :: Validity ) >
947
923
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 > ,
951
927
{
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).
957
941
//
958
942
// The caller promises all other safety preconditions.
959
943
unsafe { self . cast_unsized_unchecked ( cast) }
@@ -988,9 +972,8 @@ mod _casts {
988
972
// returned pointer addresses the same bytes as `p`
989
973
// - `slice_from_raw_parts_mut` and `.cast` both preserve provenance
990
974
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)
994
977
} )
995
978
} ;
996
979
@@ -1214,7 +1197,7 @@ mod _casts {
1214
1197
// inner type `T`. A consequence of this guarantee is that it is
1215
1198
// possible to convert between `T` and `UnsafeCell<T>`.
1216
1199
#[ allow( clippy:: as_conversions) ]
1217
- let ptr = unsafe { self . transmute_unchecked ( |p| p as * mut T ) } ;
1200
+ let ptr = unsafe { self . transmute_unchecked ( cast ! ( ) ) } ;
1218
1201
1219
1202
// SAFETY: `UnsafeCell<T>` has the same alignment as `T` [1],
1220
1203
// and so if `self` is guaranteed to be aligned, then so is the
@@ -1321,10 +1304,12 @@ mod tests {
1321
1304
} ;
1322
1305
1323
1306
// 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
+ > (
1325
1310
slf : Ptr < ' _ , T , ( Shared , Aligned , Initialized ) > ,
1326
1311
) -> usize {
1327
- let t = slf. bikeshed_recall_valid ( ) . as_ref ( ) ;
1312
+ let t = slf. bikeshed_recall_valid :: < BecauseImmutable > ( ) . as_ref ( ) ;
1328
1313
1329
1314
let bytes = {
1330
1315
let len = mem:: size_of_val ( t) ;
0 commit comments