@@ -13,6 +13,11 @@ use core::{
1313 ptr:: NonNull ,
1414} ;
1515
16+ use crate :: pointer:: {
17+ invariant:: { Initialized , Shared } ,
18+ SizeEq ,
19+ } ;
20+
1621use super :: * ;
1722
1823// SAFETY: Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a
@@ -105,10 +110,11 @@ assert_unaligned!(bool);
105110// pattern 0x01.
106111const _: ( ) = unsafe {
107112 unsafe_impl ! ( => TryFromBytes for bool ; |byte| {
108- let byte = byte. transmute:: <u8 , invariant:: Valid , _ >( ) ;
113+ let byte = byte. transmute:: <u8 , invariant:: Valid , BecauseImmutable >( ) ;
109114 * byte. unaligned_as_ref( ) < 2
110115 } )
111116} ;
117+ impl_size_eq ! ( ReadOnly <bool >, u8 ) ;
112118impl_size_eq ! ( bool , u8 ) ;
113119
114120// SAFETY:
@@ -134,7 +140,8 @@ const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) };
134140// `char`.
135141const _: ( ) = unsafe {
136142 unsafe_impl ! ( => TryFromBytes for char ; |c| {
137- let c = c. transmute:: <Unalign <u32 >, invariant:: Valid , _>( ) ;
143+ impl_size_eq!( ReadOnly <char >, Unalign <u32 >) ;
144+ let c = c. transmute:: <Unalign <u32 >, invariant:: Valid , BecauseImmutable >( ) ;
138145 let c = c. read_unaligned( ) . into_inner( ) ;
139146 char :: from_u32( c) . is_some( )
140147 } ) ;
@@ -167,7 +174,8 @@ const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unalig
167174// Returns `Err` if the slice is not UTF-8.
168175const _: ( ) = unsafe {
169176 unsafe_impl ! ( => TryFromBytes for str ; |c| {
170- let c = c. transmute:: <[ u8 ] , invariant:: Valid , _>( ) ;
177+ impl_size_eq!( ReadOnly <str >, [ u8 ] ) ;
178+ let c = c. transmute:: <[ u8 ] , invariant:: Valid , BecauseImmutable >( ) ;
171179 let c = c. unaligned_as_ref( ) ;
172180 core:: str :: from_utf8( c) . is_ok( )
173181 } )
@@ -179,9 +187,10 @@ macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
179187 ( $( $nonzero: ident[ $prim: ty] ) ,* ) => {
180188 $(
181189 unsafe_impl!( => TryFromBytes for $nonzero; |n| {
182- impl_size_eq!( $nonzero, Unalign <$prim>) ;
190+ // impl_size_eq!($nonzero, Unalign<$prim>);
191+ impl_size_eq!( ReadOnly <$nonzero>, Unalign <$prim>) ;
183192
184- let n = n. transmute:: <Unalign <$prim>, invariant:: Valid , _ >( ) ;
193+ let n = n. transmute:: <Unalign <$prim>, invariant:: Valid , BecauseImmutable >( ) ;
185194 $nonzero:: new( n. read_unaligned( ) . into_inner( ) ) . is_some( )
186195 } ) ;
187196 ) *
@@ -390,6 +399,9 @@ mod atomics {
390399 macro_rules! impl_traits_for_atomics {
391400 ( $( $atomics: ident [ $primitives: ident] ) ,* $( , ) ?) => {
392401 $(
402+ // impl_transitive_transmute_from!(T => ReadOnly<T> => T => Wrapping<T> => ReadOnly<Wrapping<T>>);
403+ // impl_size_eq!($atomics, ReadOnly<$atomics>);
404+ impl_transitive_transmute_from!( => ReadOnly <$atomics> => $atomics => $primitives => ReadOnly <$primitives>) ;
393405 impl_known_layout!( $atomics) ;
394406 impl_for_transmute_from!( => TryFromBytes for $atomics [ UnsafeCell <$primitives>] ) ;
395407 impl_for_transmute_from!( => FromZeros for $atomics [ UnsafeCell <$primitives>] ) ;
@@ -490,6 +502,7 @@ mod atomics {
490502
491503 impl_known_layout ! ( AtomicBool ) ;
492504
505+ impl_transitive_transmute_from ! ( => ReadOnly <AtomicBool > => AtomicBool => bool => ReadOnly <bool >) ;
493506 impl_for_transmute_from ! ( => TryFromBytes for AtomicBool [ UnsafeCell <bool >] ) ;
494507 impl_for_transmute_from ! ( => FromZeros for AtomicBool [ UnsafeCell <bool >] ) ;
495508 impl_for_transmute_from ! ( => IntoBytes for AtomicBool [ UnsafeCell <bool >] ) ;
@@ -635,6 +648,7 @@ mod atomics {
635648
636649 // FIXME(#170): Implement `FromBytes` and `IntoBytes` once we implement
637650 // those traits for `*mut T`.
651+ impl_transitive_transmute_from ! ( T => ReadOnly <AtomicPtr <T >> => AtomicPtr <T > => * mut T => ReadOnly <* mut T >) ;
638652 impl_for_transmute_from ! ( T => TryFromBytes for AtomicPtr <T > [ UnsafeCell <* mut T >] ) ;
639653 impl_for_transmute_from ! ( T => FromZeros for AtomicPtr <T > [ UnsafeCell <* mut T >] ) ;
640654
@@ -682,6 +696,7 @@ const _: () = unsafe {
682696 assert_unaligned ! ( PhantomData <( ) >, PhantomData <u8 >, PhantomData <u64 >) ;
683697} ;
684698
699+ impl_transitive_transmute_from ! ( T => ReadOnly <T > => T => Wrapping <T > => ReadOnly <Wrapping <T >>) ;
685700impl_for_transmute_from ! ( T : TryFromBytes => TryFromBytes for Wrapping <T >[ <T >] ) ;
686701impl_for_transmute_from ! ( T : FromZeros => FromZeros for Wrapping <T >[ <T >] ) ;
687702impl_for_transmute_from ! ( T : FromBytes => FromBytes for Wrapping <T >[ <T >] ) ;
@@ -755,6 +770,7 @@ assert_unaligned!(CoreMaybeUninit<()>, CoreMaybeUninit<u8>);
755770// [2] https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E
756771const _: ( ) = unsafe { unsafe_impl ! ( T : ?Sized + Immutable => Immutable for ManuallyDrop <T >) } ;
757772
773+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <T > => T => ManuallyDrop <T > => ReadOnly <ManuallyDrop <T >>) ;
758774impl_for_transmute_from ! ( T : ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop <T >[ <T >] ) ;
759775impl_for_transmute_from ! ( T : ?Sized + FromZeros => FromZeros for ManuallyDrop <T >[ <T >] ) ;
760776impl_for_transmute_from ! ( T : ?Sized + FromBytes => FromBytes for ManuallyDrop <T >[ <T >] ) ;
@@ -769,6 +785,7 @@ impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>[
769785const _: ( ) = unsafe { unsafe_impl ! ( T : ?Sized + Unaligned => Unaligned for ManuallyDrop <T >) } ;
770786assert_unaligned ! ( ManuallyDrop <( ) >, ManuallyDrop <u8 >) ;
771787
788+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <T > => T => Cell <T > => ReadOnly <Cell <T >>) ;
772789impl_for_transmute_from ! ( T : ?Sized + TryFromBytes => TryFromBytes for Cell <T >[ UnsafeCell <T >] ) ;
773790impl_for_transmute_from ! ( T : ?Sized + FromZeros => FromZeros for Cell <T >[ UnsafeCell <T >] ) ;
774791impl_for_transmute_from ! ( T : ?Sized + FromBytes => FromBytes for Cell <T >[ UnsafeCell <T >] ) ;
@@ -804,29 +821,16 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
804821 }
805822
806823 #[ 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 ( ) )
824+ fn is_bit_valid ( candidate : Maybe < ' _ , Self > ) -> bool {
825+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <UnsafeCell <T >> => UnsafeCell <T > => T ) ;
826+ impl_transitive_transmute_from ! ( T : ?Sized => ReadOnly <UnsafeCell <T >> => T => ReadOnly <T >) ;
827+ // unsafe { impl_size_eq!(T: ?Sized => ReadOnly<UnsafeCell<T>>, ReadOnly<T>) };
828+ // unsafe impl<T: ?Sized> SizeEq<ReadOnly<UnsafeCell<T>>> for ReadOnly<T> {
829+ // fn cast_from_raw(t: pointer::PtrInner<'_, ReadOnly<UnsafeCell<T>>>) -> pointer::PtrInner<'_, Self> {
830+ // todo!()
831+ // }
832+ // }
833+ T :: is_bit_valid ( candidate. transmute :: < _ , _ , BecauseImmutable > ( ) )
830834 }
831835}
832836
@@ -854,11 +858,14 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
854858const _: ( ) = unsafe {
855859 unsafe_impl ! ( const N : usize , T : Immutable => Immutable for [ T ; N ] ) ;
856860 unsafe_impl ! ( const N : usize , T : TryFromBytes => TryFromBytes for [ T ; N ] ; |c| {
861+ unsafe { impl_size_eq!( T => ReadOnly <[ T ] >, [ ReadOnly <T >] ) } ;
862+ unsafe { impl_size_eq!( const N : usize , T => ReadOnly <[ T ; N ] >, [ ReadOnly <T >; N ] ) } ;
857863 // Note that this call may panic, but it would still be sound even if it
858864 // did. `is_bit_valid` does not promise that it will not panic (in fact,
859865 // it explicitly warns that it's a possibility), and we have not
860866 // violated any safety invariants that we must fix before returning.
861- <[ T ] as TryFromBytes >:: is_bit_valid( c. as_slice( ) )
867+ let c: Ptr <' _, [ ReadOnly <T >; N ] , _> = c. transmute:: <_, _, BecauseImmutable >( ) ;
868+ <[ T ] as TryFromBytes >:: is_bit_valid( c. as_slice( ) . transmute:: <_, _, BecauseImmutable >( ) )
862869 } ) ;
863870 unsafe_impl ! ( const N : usize , T : FromZeros => FromZeros for [ T ; N ] ) ;
864871 unsafe_impl ! ( const N : usize , T : FromBytes => FromBytes for [ T ; N ] ) ;
@@ -887,6 +894,7 @@ const _: () = unsafe {
887894 // not panic (in fact, it explicitly warns that it's a possibility), and
888895 // we have not violated any safety invariants that we must fix before
889896 // returning.
897+ let c: Ptr <' _, [ ReadOnly <T >] , _> = c. transmute:: <_, _, BecauseImmutable >( ) ;
890898 c. iter( ) . all( <T as TryFromBytes >:: is_bit_valid)
891899 } ) ;
892900 unsafe_impl ! ( T : FromZeros => FromZeros for [ T ] ) ;
@@ -1096,12 +1104,12 @@ mod tests {
10961104 // types must implement `TryFromBytesTestable` directly (ie using
10971105 // `impl_try_from_bytes_testable!`).
10981106 trait TryFromBytesTestable {
1099- fn with_passing_test_cases < F : Fn ( Box < Self > ) > ( f : F ) ;
1107+ fn with_passing_test_cases < F : Fn ( Box < ReadOnly < Self > > ) > ( f : F ) ;
11001108 fn with_failing_test_cases < F : Fn ( & mut [ u8 ] ) > ( f : F ) ;
11011109 }
11021110
11031111 impl < T : FromBytes > TryFromBytesTestable for T {
1104- fn with_passing_test_cases < F : Fn ( Box < Self > ) > ( f : F ) {
1112+ fn with_passing_test_cases < F : Fn ( Box < ReadOnly < Self > > ) > ( f : F ) {
11051113 // Test with a zeroed value.
11061114 f ( Self :: new_box_zeroed ( ) . unwrap ( ) ) ;
11071115
@@ -1124,9 +1132,9 @@ mod tests {
11241132 ( $( $tys: ty) ,* ) => {
11251133 $(
11261134 impl TryFromBytesTestable for Option <$tys> {
1127- fn with_passing_test_cases<F : Fn ( Box <Self >) >( f: F ) {
1135+ fn with_passing_test_cases<F : Fn ( Box <ReadOnly < Self > >) >( f: F ) {
11281136 // Test with a zeroed value.
1129- f( Box :: new( None ) ) ;
1137+ f( Box :: new( ReadOnly :: new ( None ) ) ) ;
11301138 }
11311139
11321140 fn with_failing_test_cases<F : Fn ( & mut [ u8 ] ) >( f: F ) {
@@ -1164,7 +1172,7 @@ mod tests {
11641172 // Implements only the methods; caller must invoke this from inside
11651173 // an impl block.
11661174 ( @methods @success $( $success_case: expr) ,* $( , @failure $( $failure_case: expr) ,* ) ?) => {
1167- fn with_passing_test_cases<F : Fn ( Box <Self >) >( _f: F ) {
1175+ fn with_passing_test_cases<F : Fn ( Box <ReadOnly < Self > >) >( _f: F ) {
11681176 $(
11691177 _f( Box :: <Self >:: from( $success_case) ) ;
11701178 ) *
@@ -1266,17 +1274,15 @@ mod tests {
12661274
12671275 pub ( super ) trait TestIsBitValidShared < T : ?Sized > {
12681276 #[ 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 > ;
1277+ fn test_is_bit_valid_shared < ' ptr > ( & self , candidate : Maybe < ' ptr , T > )
1278+ -> Option < bool > ;
12731279 }
12741280
12751281 impl < T : TryFromBytes + Immutable + ?Sized > TestIsBitValidShared < T > for AutorefWrapper < T > {
12761282 #[ allow( clippy:: needless_lifetimes) ]
1277- fn test_is_bit_valid_shared < ' ptr , A : invariant :: Reference > (
1283+ fn test_is_bit_valid_shared < ' ptr > (
12781284 & self ,
1279- candidate : Maybe < ' ptr , T , A > ,
1285+ candidate : Maybe < ' ptr , T > ,
12801286 ) -> Option < bool > {
12811287 Some ( T :: is_bit_valid ( candidate) )
12821288 }
@@ -1330,12 +1336,12 @@ mod tests {
13301336
13311337 pub ( super ) trait TestAsBytes < T : ?Sized > {
13321338 #[ allow( clippy:: needless_lifetimes) ]
1333- fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t T ) -> Option < & ' t [ u8 ] > ;
1339+ fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t ReadOnly < T > ) -> Option < & ' t [ u8 ] > ;
13341340 }
13351341
13361342 impl < T : IntoBytes + Immutable + ?Sized > TestAsBytes < T > for AutorefWrapper < T > {
13371343 #[ allow( clippy:: needless_lifetimes) ]
1338- fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t T ) -> Option < & ' t [ u8 ] > {
1344+ fn test_as_bytes < ' slf , ' t > ( & ' slf self , t : & ' t ReadOnly < T > ) -> Option < & ' t [ u8 ] > {
13391345 Some ( t. as_bytes ( ) )
13401346 }
13411347 }
@@ -1382,9 +1388,9 @@ mod tests {
13821388 #[ allow( unused, non_local_definitions) ]
13831389 impl AutorefWrapper <$ty> {
13841390 #[ allow( clippy:: needless_lifetimes) ]
1385- fn test_is_bit_valid_shared<' ptr, A : invariant :: Reference >(
1391+ fn test_is_bit_valid_shared<' ptr>(
13861392 & mut self ,
1387- candidate: Maybe <' ptr, $ty, A >,
1393+ candidate: Maybe <' ptr, $ty>,
13881394 ) -> Option <bool > {
13891395 assert_on_allowlist!(
13901396 test_is_bit_valid_shared( $ty) :
@@ -1442,7 +1448,7 @@ mod tests {
14421448 None
14431449 }
14441450
1445- fn test_as_bytes( & mut self , _t: & $ty) -> Option <& [ u8 ] > {
1451+ fn test_as_bytes( & mut self , _t: & ReadOnly < $ty> ) -> Option <& [ u8 ] > {
14461452 assert_on_allowlist!(
14471453 test_as_bytes( $ty) :
14481454 Option <& ' static UnsafeCell <NotZerocopy >>,
@@ -1491,6 +1497,7 @@ mod tests {
14911497 // necessarily `IntoBytes`, but that's the corner we've
14921498 // backed ourselves into by using `Ptr::from_ref`.
14931499 let c = unsafe { c. assume_initialized( ) } ;
1500+ let c = unsafe { c. assume_aliasing:: <Shared >( ) } ;
14941501 let res = w. test_is_bit_valid_shared( c) ;
14951502 if let Some ( res) = res {
14961503 assert!( res, "{}::is_bit_valid({:?}) (shared `Ptr`): got false, expected true" , stringify!( $ty) , val) ;
@@ -1502,6 +1509,7 @@ mod tests {
15021509 // necessarily `IntoBytes`, but that's the corner we've
15031510 // backed ourselves into by using `Ptr::from_ref`.
15041511 let c = unsafe { c. assume_initialized( ) } ;
1512+ let c = unsafe { c. assume_aliasing( ) } ;
15051513 let res = <$ty as TryFromBytes >:: is_bit_valid( c) ;
15061514 assert!( res, "{}::is_bit_valid({:?}) (exclusive `Ptr`): got false, expected true" , stringify!( $ty) , val) ;
15071515
0 commit comments