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