@@ -171,7 +171,10 @@ mod _external {
171
171
/// Methods for converting to and from `Ptr` and Rust's safe reference types.
172
172
mod _conversions {
173
173
use super :: * ;
174
- use crate :: util:: { AlignmentVariance , Covariant , TransparentWrapper , ValidityVariance } ;
174
+ use crate :: {
175
+ pointer:: transmute:: { CastFrom , TransmuteFromAlignment , TransmuteFromPtr } ,
176
+ util:: { AlignmentVariance , Covariant , TransparentWrapper , ValidityVariance } ,
177
+ } ;
175
178
176
179
/// `&'a T` → `Ptr<'a, T>`
177
180
impl < ' a , T : ?Sized > Ptr < ' a , Valid < T > , ( Shared , Aligned ) > {
@@ -337,6 +340,54 @@ mod _conversions {
337
340
}
338
341
}
339
342
343
+ /// `Ptr<'a, T>` → `Ptr<'a, U>`
344
+ impl < ' a , V , I > Ptr < ' a , V , I >
345
+ where
346
+ V : Validity ,
347
+ I : Invariants ,
348
+ {
349
+ /// # Safety
350
+ /// - TODO: `UnsafeCell` agreement
351
+ /// - The caller promises that the returned `Ptr` satisfies alignment
352
+ /// `A`
353
+ /// - The caller promises that the returned `Ptr` satisfies validity `V`
354
+ pub ( crate ) unsafe fn transmute_unchecked < U , A > ( self ) -> Ptr < ' a , U , ( I :: Aliasing , A ) >
355
+ where
356
+ A : Alignment ,
357
+ U : Validity ,
358
+ U :: Inner : CastFrom < V :: Inner > ,
359
+ {
360
+ // SAFETY:
361
+ // - By invariant on `CastFrom::cast_from`:
362
+ // - This cast preserves address and referent size, and thus the
363
+ // returned pointer addresses the same bytes as `p`
364
+ // - This cast preserves provenance
365
+ // - TODO: `UnsafeCell` agreement
366
+ let ptr =
367
+ unsafe { self . cast_unsized_unchecked :: < U :: Inner , _ > ( |p| U :: Inner :: cast_from ( p) ) } ;
368
+ // SAFETY: The caller promises that alignment is satisfied.
369
+ let ptr = unsafe { ptr. assume_alignment ( ) } ;
370
+ // SAFETY: The caller promises that validity is satisfied.
371
+ let ptr = unsafe { ptr. assume_validity :: < U > ( ) } ;
372
+ ptr. unify_validity ( )
373
+ }
374
+
375
+ pub ( crate ) fn transmute < U , A , RT , RA > ( self ) -> Ptr < ' a , U , ( I :: Aliasing , A ) >
376
+ where
377
+ A : Alignment ,
378
+ U : TransmuteFromPtr < V , I :: Aliasing , RT > ,
379
+ U :: Inner : TransmuteFromAlignment < U :: Inner , I :: Alignment , A , RA > + CastFrom < V :: Inner > ,
380
+ {
381
+ // SAFETY:
382
+ // - TODO: `UnsafeCell` agreement
383
+ // - By invariant on `TransmuteFromPtr`, it is sound to treat the
384
+ // resulting pointer as having alignment `A`
385
+ // - By invariant on `TransmuteFromPtr`, it is sound to treat the
386
+ // resulting pointer as having validity `V`
387
+ unsafe { self . transmute_unchecked ( ) }
388
+ }
389
+ }
390
+
340
391
/// `Ptr<'a, T = Wrapper<U>>` → `Ptr<'a, U>`
341
392
impl < ' a , V , I > Ptr < ' a , V , I >
342
393
where
@@ -428,7 +479,10 @@ mod _conversions {
428
479
/// State transitions between invariants.
429
480
mod _transitions {
430
481
use super :: * ;
431
- use crate :: { AlignmentError , TryFromBytes , ValidityError } ;
482
+ use crate :: {
483
+ pointer:: transmute:: { CastFrom , TransmuteFromPtr , TryTransmuteFromPtr } ,
484
+ AlignmentError , TryFromBytes , ValidityError ,
485
+ } ;
432
486
433
487
impl < ' a , V , I > Ptr < ' a , V , I >
434
488
where
@@ -649,6 +703,22 @@ mod _transitions {
649
703
}
650
704
}
651
705
706
+ impl < ' a , V , I > Ptr < ' a , V , I >
707
+ where
708
+ V : Validity ,
709
+ I : Invariants ,
710
+ I :: Aliasing : Reference ,
711
+ {
712
+ /// Forgets that `self` is an `Exclusive` pointer, downgrading it to a
713
+ /// `Shared` pointer.
714
+ #[ doc( hidden) ]
715
+ #[ must_use]
716
+ #[ inline]
717
+ pub const fn forget_exclusive ( self ) -> Ptr < ' a , V , I :: WithAliasing < Shared > > {
718
+ unsafe { self . assume_invariants ( ) }
719
+ }
720
+ }
721
+
652
722
impl < ' a , T , I > Ptr < ' a , Initialized < T > , I >
653
723
where
654
724
T : ?Sized ,
@@ -660,14 +730,12 @@ mod _transitions {
660
730
#[ inline]
661
731
// TODO(#859): Reconsider the name of this method before making it
662
732
// public.
663
- pub const fn bikeshed_recall_valid ( self ) -> Ptr < ' a , Valid < T > , I >
733
+ pub fn bikeshed_recall_valid < R > ( self ) -> Ptr < ' a , Valid < T > , I >
664
734
where
665
- T : crate :: FromBytes ,
735
+ Valid < T > : TransmuteFromPtr < Initialized < T > , I :: Aliasing , R > ,
736
+ <Valid < T > as Validity >:: Inner : CastFrom < T > ,
666
737
{
667
- // SAFETY: The bound `T: FromBytes` ensures that any initialized
668
- // sequence of bytes is bit-valid for `T`. `V = Initialized<T>`
669
- // ensures that all of the referent bytes are initialized.
670
- unsafe { self . assume_valid ( ) }
738
+ self . transmute ( ) . unify_invariants ( )
671
739
}
672
740
673
741
/// Checks that `self`'s referent is validly initialized for `T`,
@@ -687,7 +755,12 @@ mod _transitions {
687
755
mut self ,
688
756
) -> Result < Ptr < ' a , Valid < T > , I > , ValidityError < Self , T > >
689
757
where
690
- T : TryFromBytes + Read < I :: Aliasing , R > ,
758
+ T : TryFromBytes , // + Read<I::Aliasing, R>,
759
+ Valid < T > : TryTransmuteFromPtr < Initialized < T > , I :: Aliasing , R > ,
760
+ // NOTE: This bound ought to be implied, but leaving it out causes
761
+ // Rust to infinite loop during trait solving.
762
+ <Valid < T > as Validity >:: Inner :
763
+ crate :: pointer:: transmute:: CastFrom < <Initialized < T > as Validity >:: Inner > ,
691
764
I :: Aliasing : Reference ,
692
765
{
693
766
// This call may panic. If that happens, it doesn't cause any soundness
@@ -702,12 +775,63 @@ mod _transitions {
702
775
}
703
776
}
704
777
}
778
+
779
+ impl < ' a , V , I > Ptr < ' a , V , I >
780
+ where
781
+ V : Validity ,
782
+ I : Invariants ,
783
+ {
784
+ /// Attempts to transmute a `Ptr<T>` into a `Ptr<U>`.
785
+ ///
786
+ /// # Panics
787
+ ///
788
+ /// This method will panic if
789
+ /// [`U::is_bit_valid`][TryFromBytes::is_bit_valid] panics.
790
+ ///
791
+ /// # Safety
792
+ ///
793
+ /// On success, the returned `Ptr` addresses the same bytes as `self`.
794
+ ///
795
+ /// On error, unsafe code may rely on this method's returned
796
+ /// `ValidityError` containing `self`.
797
+ #[ inline]
798
+ pub ( crate ) fn try_transmute < U , R , RR > (
799
+ mut self ,
800
+ ) -> Result < Ptr < ' a , U , I :: WithAlignment < Unknown > > , ValidityError < Self , U :: Inner > >
801
+ where
802
+ U : Validity + TryTransmuteFromPtr < V , I :: Aliasing , R > ,
803
+ U :: Inner : TryFromBytes + CastFrom < V :: Inner > ,
804
+ Initialized < U :: Inner > : TransmuteFromPtr < V , I :: Aliasing , RR > ,
805
+ // TODO: The `Sized` bound here is only required in order to call
806
+ // `.bikeshed_try_into_aligned`. There are other ways of getting the
807
+ // alignment of a type, and we could use these if we need to drop
808
+ // this bound.
809
+ <Initialized < U :: Inner > as Validity >:: Inner : Sized + CastFrom < V :: Inner > ,
810
+ I :: Aliasing : Reference ,
811
+ {
812
+ let is_bit_valid = {
813
+ let ptr = self . reborrow ( ) ;
814
+ let ptr = ptr. transmute :: < Initialized < U :: Inner > , Unknown , _ , _ > ( ) ;
815
+ // This call may panic. If that happens, it doesn't cause any
816
+ // soundness issues, as we have not generated any invalid state
817
+ // which we need to fix before returning.
818
+ <U :: Inner as TryFromBytes >:: is_bit_valid ( ptr)
819
+ } ;
820
+
821
+ if is_bit_valid {
822
+ let ptr = unsafe { self . transmute_unchecked ( ) } ;
823
+ Ok ( ptr. unify_invariants ( ) )
824
+ } else {
825
+ Err ( ValidityError :: new ( self ) )
826
+ }
827
+ }
828
+ }
705
829
}
706
830
707
831
/// Casts of the referent type.
708
832
mod _casts {
709
833
use super :: * ;
710
- use crate :: { CastError , SizeError } ;
834
+ use crate :: { pointer :: transmute :: BecauseRead , CastError , SizeError } ;
711
835
712
836
impl < ' a , V , I > Ptr < ' a , V , I >
713
837
where
@@ -866,7 +990,7 @@ mod _casts {
866
990
} )
867
991
} ;
868
992
869
- ptr. bikeshed_recall_aligned ( ) . bikeshed_recall_valid ( )
993
+ ptr. bikeshed_recall_aligned ( ) . bikeshed_recall_valid :: < ( BecauseRead , _ ) > ( )
870
994
}
871
995
}
872
996
@@ -1125,6 +1249,7 @@ mod tests {
1125
1249
1126
1250
mod test_ptr_try_cast_into_soundness {
1127
1251
use super :: * ;
1252
+ use crate :: IntoBytes ;
1128
1253
1129
1254
// This test is designed so that if `Ptr::try_cast_into_xxx` are
1130
1255
// buggy, it will manifest as unsoundness that Miri can detect.
@@ -1164,7 +1289,9 @@ mod tests {
1164
1289
} ;
1165
1290
1166
1291
// SAFETY: The bytes in `slf` must be initialized.
1167
- unsafe fn validate_and_get_len < T : ?Sized + KnownLayout + FromBytes > (
1292
+ unsafe fn validate_and_get_len <
1293
+ T : ?Sized + KnownLayout + FromBytes + Immutable ,
1294
+ > (
1168
1295
slf : Ptr < ' _ , Initialized < T > , ( Shared , Aligned ) > ,
1169
1296
) -> usize {
1170
1297
let t = slf. bikeshed_recall_valid ( ) . as_ref ( ) ;
0 commit comments