@@ -14,6 +14,10 @@ use core::{
1414} ;
1515
1616use super :: * ;
17+ use crate :: pointer:: {
18+ invariant:: { Initialized , Shared } ,
19+ SizeEq ,
20+ } ;
1721
1822// SAFETY: Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a
1923// zero-sized type to have a size of 0 and an alignment of 1."
@@ -105,10 +109,11 @@ assert_unaligned!(bool);
105109// pattern 0x01.
106110const _: ( ) = unsafe {
107111 unsafe_impl ! ( => TryFromBytes for bool ; |byte| {
108- let byte = byte. transmute:: <u8 , invariant:: Valid , _ >( ) ;
112+ let byte = byte. transmute:: <u8 , invariant:: Valid , BecauseImmutable >( ) ;
109113 * byte. unaligned_as_ref( ) < 2
110114 } )
111115} ;
116+ impl_size_eq ! ( ReadOnly <bool >, u8 ) ;
112117impl_size_eq ! ( bool , u8 ) ;
113118
114119// SAFETY:
@@ -134,7 +139,8 @@ const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) };
134139// `char`.
135140const _: ( ) = unsafe {
136141 unsafe_impl ! ( => TryFromBytes for char ; |c| {
137- let c = c. transmute:: <Unalign <u32 >, invariant:: Valid , _>( ) ;
142+ impl_size_eq!( ReadOnly <char >, Unalign <u32 >) ;
143+ let c = c. transmute:: <Unalign <u32 >, invariant:: Valid , BecauseImmutable >( ) ;
138144 let c = c. read_unaligned( ) . into_inner( ) ;
139145 char :: from_u32( c) . is_some( )
140146 } ) ;
@@ -167,7 +173,8 @@ const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unalig
167173// Returns `Err` if the slice is not UTF-8.
168174const _: ( ) = unsafe {
169175 unsafe_impl ! ( => TryFromBytes for str ; |c| {
170- let c = c. transmute:: <[ u8 ] , invariant:: Valid , _>( ) ;
176+ impl_size_eq!( ReadOnly <str >, [ u8 ] ) ;
177+ let c = c. transmute:: <[ u8 ] , invariant:: Valid , BecauseImmutable >( ) ;
171178 let c = c. unaligned_as_ref( ) ;
172179 core:: str :: from_utf8( c) . is_ok( )
173180 } )
@@ -179,9 +186,10 @@ macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
179186 ( $( $nonzero: ident[ $prim: ty] ) ,* ) => {
180187 $(
181188 unsafe_impl!( => TryFromBytes for $nonzero; |n| {
182- impl_size_eq!( $nonzero, Unalign <$prim>) ;
189+ // impl_size_eq!($nonzero, Unalign<$prim>);
190+ impl_size_eq!( ReadOnly <$nonzero>, Unalign <$prim>) ;
183191
184- let n = n. transmute:: <Unalign <$prim>, invariant:: Valid , _ >( ) ;
192+ let n = n. transmute:: <Unalign <$prim>, invariant:: Valid , BecauseImmutable >( ) ;
185193 $nonzero:: new( n. read_unaligned( ) . into_inner( ) ) . is_some( )
186194 } ) ;
187195 ) *
@@ -390,6 +398,9 @@ mod atomics {
390398 macro_rules! impl_traits_for_atomics {
391399 ( $( $atomics: ident [ $primitives: ident] ) ,* $( , ) ?) => {
392400 $(
401+ // impl_transitive_transmute_from!(T => ReadOnly<T> => T => Wrapping<T> => ReadOnly<Wrapping<T>>);
402+ // impl_size_eq!($atomics, ReadOnly<$atomics>);
403+ impl_transitive_transmute_from!( => ReadOnly <$atomics> => $atomics => $primitives => ReadOnly <$primitives>) ;
393404 impl_known_layout!( $atomics) ;
394405 impl_for_transmute_from!( => TryFromBytes for $atomics [ UnsafeCell <$primitives>] ) ;
395406 impl_for_transmute_from!( => FromZeros for $atomics [ UnsafeCell <$primitives>] ) ;
@@ -490,6 +501,7 @@ mod atomics {
490501
491502 impl_known_layout ! ( AtomicBool ) ;
492503
504+ impl_transitive_transmute_from ! ( => ReadOnly <AtomicBool > => AtomicBool => bool => ReadOnly <bool >) ;
493505 impl_for_transmute_from ! ( => TryFromBytes for AtomicBool [ UnsafeCell <bool >] ) ;
494506 impl_for_transmute_from ! ( => FromZeros for AtomicBool [ UnsafeCell <bool >] ) ;
495507 impl_for_transmute_from ! ( => IntoBytes for AtomicBool [ UnsafeCell <bool >] ) ;
@@ -635,6 +647,7 @@ mod atomics {
635647
636648 // FIXME(#170): Implement `FromBytes` and `IntoBytes` once we implement
637649 // those traits for `*mut T`.
650+ impl_transitive_transmute_from ! ( T => ReadOnly <AtomicPtr <T >> => AtomicPtr <T > => * mut T => ReadOnly <* mut T >) ;
638651 impl_for_transmute_from ! ( T => TryFromBytes for AtomicPtr <T > [ UnsafeCell <* mut T >] ) ;
639652 impl_for_transmute_from ! ( T => FromZeros for AtomicPtr <T > [ UnsafeCell <* mut T >] ) ;
640653
@@ -682,6 +695,7 @@ const _: () = unsafe {
682695 assert_unaligned ! ( PhantomData <( ) >, PhantomData <u8 >, PhantomData <u64 >) ;
683696} ;
684697
698+ impl_transitive_transmute_from ! ( T => ReadOnly <T > => T => Wrapping <T > => ReadOnly <Wrapping <T >>) ;
685699impl_for_transmute_from ! ( T : TryFromBytes => TryFromBytes for Wrapping <T >[ <T >] ) ;
686700impl_for_transmute_from ! ( T : FromZeros => FromZeros for Wrapping <T >[ <T >] ) ;
687701impl_for_transmute_from ! ( T : FromBytes => FromBytes for Wrapping <T >[ <T >] ) ;
@@ -755,6 +769,7 @@ assert_unaligned!(CoreMaybeUninit<()>, CoreMaybeUninit<u8>);
755769// [2] https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E
756770const _: ( ) = unsafe { unsafe_impl ! ( T : ?Sized + Immutable => Immutable for ManuallyDrop <T >) } ;
757771
772+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <T > => T => ManuallyDrop <T > => ReadOnly <ManuallyDrop <T >>) ;
758773impl_for_transmute_from ! ( T : ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop <T >[ <T >] ) ;
759774impl_for_transmute_from ! ( T : ?Sized + FromZeros => FromZeros for ManuallyDrop <T >[ <T >] ) ;
760775impl_for_transmute_from ! ( T : ?Sized + FromBytes => FromBytes for ManuallyDrop <T >[ <T >] ) ;
@@ -769,6 +784,7 @@ impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>[
769784const _: ( ) = unsafe { unsafe_impl ! ( T : ?Sized + Unaligned => Unaligned for ManuallyDrop <T >) } ;
770785assert_unaligned ! ( ManuallyDrop <( ) >, ManuallyDrop <u8 >) ;
771786
787+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <T > => T => Cell <T > => ReadOnly <Cell <T >>) ;
772788impl_for_transmute_from ! ( T : ?Sized + TryFromBytes => TryFromBytes for Cell <T >[ UnsafeCell <T >] ) ;
773789impl_for_transmute_from ! ( T : ?Sized + FromZeros => FromZeros for Cell <T >[ UnsafeCell <T >] ) ;
774790impl_for_transmute_from ! ( T : ?Sized + FromBytes => FromBytes for Cell <T >[ UnsafeCell <T >] ) ;
@@ -804,29 +820,9 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
804820 }
805821
806822 #[ inline]
807- fn is_bit_valid < A : invariant:: Reference > ( candidate : Maybe < ' _ , Self , A > ) -> bool {
808- // The only way to implement this function is using an exclusive-aliased
809- // pointer. `UnsafeCell`s cannot be read via shared-aliased pointers
810- // (other than by using `unsafe` code, which we can't use since we can't
811- // guarantee how our users are accessing or modifying the `UnsafeCell`).
812- //
813- // `is_bit_valid` is documented as panicking or failing to monomorphize
814- // if called with a shared-aliased pointer on a type containing an
815- // `UnsafeCell`. In practice, it will always be a monorphization error.
816- // Since `is_bit_valid` is `#[doc(hidden)]` and only called directly
817- // from this crate, we only need to worry about our own code incorrectly
818- // calling `UnsafeCell::is_bit_valid`. The post-monomorphization error
819- // makes it easier to test that this is truly the case, and also means
820- // that if we make a mistake, it will cause downstream code to fail to
821- // compile, which will immediately surface the mistake and give us a
822- // chance to fix it quickly.
823- let c = candidate. into_exclusive_or_pme ( ) ;
824-
825- // SAFETY: Since `UnsafeCell<T>` and `T` have the same layout and bit
826- // validity, `UnsafeCell<T>` is bit-valid exactly when its wrapped `T`
827- // is. Thus, this is a sound implementation of
828- // `UnsafeCell::is_bit_valid`.
829- T :: is_bit_valid ( c. get_mut ( ) )
823+ fn is_bit_valid ( candidate : Maybe < ' _ , Self > ) -> bool {
824+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <UnsafeCell <T >> => UnsafeCell <T > => T => ReadOnly <T >) ;
825+ T :: is_bit_valid ( candidate. transmute :: < _ , _ , BecauseImmutable > ( ) )
830826 }
831827}
832828
@@ -854,11 +850,14 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
854850const _: ( ) = unsafe {
855851 unsafe_impl ! ( const N : usize , T : Immutable => Immutable for [ T ; N ] ) ;
856852 unsafe_impl ! ( const N : usize , T : TryFromBytes => TryFromBytes for [ T ; N ] ; |c| {
853+ unsafe { impl_size_eq!( T => ReadOnly <[ T ] >, [ ReadOnly <T >] ) } ;
854+ unsafe { impl_size_eq!( const N : usize , T => ReadOnly <[ T ; N ] >, [ ReadOnly <T >; N ] ) } ;
857855 // Note that this call may panic, but it would still be sound even if it
858856 // did. `is_bit_valid` does not promise that it will not panic (in fact,
859857 // it explicitly warns that it's a possibility), and we have not
860858 // violated any safety invariants that we must fix before returning.
861- <[ T ] as TryFromBytes >:: is_bit_valid( c. as_slice( ) )
859+ let c: Ptr <' _, [ ReadOnly <T >; N ] , _> = c. transmute:: <_, _, BecauseImmutable >( ) ;
860+ <[ T ] as TryFromBytes >:: is_bit_valid( c. as_slice( ) . transmute:: <_, _, BecauseImmutable >( ) )
862861 } ) ;
863862 unsafe_impl ! ( const N : usize , T : FromZeros => FromZeros for [ T ; N ] ) ;
864863 unsafe_impl ! ( const N : usize , T : FromBytes => FromBytes for [ T ; N ] ) ;
@@ -887,6 +886,7 @@ const _: () = unsafe {
887886 // not panic (in fact, it explicitly warns that it's a possibility), and
888887 // we have not violated any safety invariants that we must fix before
889888 // returning.
889+ let c: Ptr <' _, [ ReadOnly <T >] , _> = c. transmute:: <_, _, BecauseImmutable >( ) ;
890890 c. iter( ) . all( <T as TryFromBytes >:: is_bit_valid)
891891 } ) ;
892892 unsafe_impl ! ( T : FromZeros => FromZeros for [ T ] ) ;
@@ -1096,12 +1096,12 @@ mod tests {
10961096 // types must implement `TryFromBytesTestable` directly (ie using
10971097 // `impl_try_from_bytes_testable!`).
10981098 trait TryFromBytesTestable {
1099- fn with_passing_test_cases < F : Fn ( Box < Self > ) > ( f : F ) ;
1099+ fn with_passing_test_cases < F : Fn ( Box < ReadOnly < Self > > ) > ( f : F ) ;
11001100 fn with_failing_test_cases < F : Fn ( & mut [ u8 ] ) > ( f : F ) ;
11011101 }
11021102
11031103 impl < T : FromBytes > TryFromBytesTestable for T {
1104- fn with_passing_test_cases < F : Fn ( Box < Self > ) > ( f : F ) {
1104+ fn with_passing_test_cases < F : Fn ( Box < ReadOnly < Self > > ) > ( f : F ) {
11051105 // Test with a zeroed value.
11061106 f ( Self :: new_box_zeroed ( ) . unwrap ( ) ) ;
11071107
@@ -1124,9 +1124,9 @@ mod tests {
11241124 ( $( $tys: ty) ,* ) => {
11251125 $(
11261126 impl TryFromBytesTestable for Option <$tys> {
1127- fn with_passing_test_cases<F : Fn ( Box <Self >) >( f: F ) {
1127+ fn with_passing_test_cases<F : Fn ( Box <ReadOnly < Self > >) >( f: F ) {
11281128 // Test with a zeroed value.
1129- f( Box :: new( None ) ) ;
1129+ f( Box :: new( ReadOnly :: new ( None ) ) ) ;
11301130 }
11311131
11321132 fn with_failing_test_cases<F : Fn ( & mut [ u8 ] ) >( f: F ) {
@@ -1164,7 +1164,7 @@ mod tests {
11641164 // Implements only the methods; caller must invoke this from inside
11651165 // an impl block.
11661166 ( @methods @success $( $success_case: expr) ,* $( , @failure $( $failure_case: expr) ,* ) ?) => {
1167- fn with_passing_test_cases<F : Fn ( Box <Self >) >( _f: F ) {
1167+ fn with_passing_test_cases<F : Fn ( Box <ReadOnly < Self > >) >( _f: F ) {
11681168 $(
11691169 _f( Box :: <Self >:: from( $success_case) ) ;
11701170 ) *
@@ -1266,17 +1266,15 @@ mod tests {
12661266
12671267 pub ( super ) trait TestIsBitValidShared < T : ?Sized > {
12681268 #[ allow( clippy:: needless_lifetimes) ]
1269- fn test_is_bit_valid_shared < ' ptr , A : invariant:: Reference > (
1270- & self ,
1271- candidate : Maybe < ' ptr , T , A > ,
1272- ) -> Option < bool > ;
1269+ fn test_is_bit_valid_shared < ' ptr > ( & self , candidate : Maybe < ' ptr , T > )
1270+ -> Option < bool > ;
12731271 }
12741272
12751273 impl < T : TryFromBytes + Immutable + ?Sized > TestIsBitValidShared < T > for AutorefWrapper < T > {
12761274 #[ allow( clippy:: needless_lifetimes) ]
1277- fn test_is_bit_valid_shared < ' ptr , A : invariant :: Reference > (
1275+ fn test_is_bit_valid_shared < ' ptr > (
12781276 & self ,
1279- candidate : Maybe < ' ptr , T , A > ,
1277+ candidate : Maybe < ' ptr , T > ,
12801278 ) -> Option < bool > {
12811279 Some ( T :: is_bit_valid ( candidate) )
12821280 }
@@ -1330,12 +1328,12 @@ mod tests {
13301328
13311329 pub ( super ) trait TestAsBytes < T : ?Sized > {
13321330 #[ allow( clippy:: needless_lifetimes) ]
1333- fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t T ) -> Option < & ' t [ u8 ] > ;
1331+ fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t ReadOnly < T > ) -> Option < & ' t [ u8 ] > ;
13341332 }
13351333
13361334 impl < T : IntoBytes + Immutable + ?Sized > TestAsBytes < T > for AutorefWrapper < T > {
13371335 #[ allow( clippy:: needless_lifetimes) ]
1338- fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t T ) -> Option < & ' t [ u8 ] > {
1336+ fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t ReadOnly < T > ) -> Option < & ' t [ u8 ] > {
13391337 Some ( t. as_bytes ( ) )
13401338 }
13411339 }
@@ -1382,9 +1380,9 @@ mod tests {
13821380 #[ allow( unused, non_local_definitions) ]
13831381 impl AutorefWrapper <$ty> {
13841382 #[ allow( clippy:: needless_lifetimes) ]
1385- fn test_is_bit_valid_shared<' ptr, A : invariant :: Reference >(
1383+ fn test_is_bit_valid_shared<' ptr>(
13861384 & mut self ,
1387- candidate: Maybe <' ptr, $ty, A >,
1385+ candidate: Maybe <' ptr, $ty>,
13881386 ) -> Option <bool > {
13891387 assert_on_allowlist!(
13901388 test_is_bit_valid_shared( $ty) :
@@ -1442,7 +1440,7 @@ mod tests {
14421440 None
14431441 }
14441442
1445- fn test_as_bytes( & mut self , _t: & $ty) -> Option <& [ u8 ] > {
1443+ fn test_as_bytes( & mut self , _t: & ReadOnly < $ty> ) -> Option <& [ u8 ] > {
14461444 assert_on_allowlist!(
14471445 test_as_bytes( $ty) :
14481446 Option <& ' static UnsafeCell <NotZerocopy >>,
@@ -1491,6 +1489,7 @@ mod tests {
14911489 // necessarily `IntoBytes`, but that's the corner we've
14921490 // backed ourselves into by using `Ptr::from_ref`.
14931491 let c = unsafe { c. assume_initialized( ) } ;
1492+ let c = unsafe { c. assume_aliasing:: <Shared >( ) } ;
14941493 let res = w. test_is_bit_valid_shared( c) ;
14951494 if let Some ( res) = res {
14961495 assert!( res, "{}::is_bit_valid({:?}) (shared `Ptr`): got false, expected true" , stringify!( $ty) , val) ;
@@ -1502,6 +1501,7 @@ mod tests {
15021501 // necessarily `IntoBytes`, but that's the corner we've
15031502 // backed ourselves into by using `Ptr::from_ref`.
15041503 let c = unsafe { c. assume_initialized( ) } ;
1504+ let c = unsafe { c. assume_aliasing( ) } ;
15051505 let res = <$ty as TryFromBytes >:: is_bit_valid( c) ;
15061506 assert!( res, "{}::is_bit_valid({:?}) (exclusive `Ptr`): got false, expected true" , stringify!( $ty) , val) ;
15071507
0 commit comments