@@ -108,11 +108,11 @@ assert_unaligned!(bool);
108108// pattern 0x01.
109109const _: ( ) = unsafe {
110110 unsafe_impl ! ( => TryFromBytes for bool ; |byte| {
111- let byte = byte. transmute:: <u8 , invariant:: Valid , _ >( ) ;
111+ let byte = byte. transmute:: <u8 , invariant:: Valid , BecauseImmutable >( ) ;
112112 * byte. unaligned_as_ref( ) < 2
113113 } )
114114} ;
115- impl_size_eq ! ( bool , u8 ) ;
115+ impl_size_eq ! ( => bool , u8 ) ;
116116
117117// SAFETY:
118118// - `Immutable`: `char` self-evidently does not contain any `UnsafeCell`s.
@@ -138,13 +138,13 @@ const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) };
138138// `char`.
139139const _: ( ) = unsafe {
140140 unsafe_impl ! ( => TryFromBytes for char ; |c| {
141- let c = c. transmute:: <Unalign <u32 >, invariant:: Valid , _ >( ) ;
141+ let c = c. transmute:: <Unalign <u32 >, invariant:: Valid , BecauseImmutable >( ) ;
142142 let c = c. read_unaligned( ) . into_inner( ) ;
143143 char :: from_u32( c) . is_some( )
144144 } ) ;
145145} ;
146146
147- impl_size_eq ! ( char , Unalign <u32 >) ;
147+ impl_size_eq ! ( => char , Unalign <u32 >) ;
148148
149149// SAFETY: Per the Reference [1], `str` has the same layout as `[u8]`.
150150// - `Immutable`: `[u8]` does not contain any `UnsafeCell`s.
@@ -173,21 +173,21 @@ const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unalig
173173// Returns `Err` if the slice is not UTF-8.
174174const _: ( ) = unsafe {
175175 unsafe_impl ! ( => TryFromBytes for str ; |c| {
176- let c = c. transmute:: <[ u8 ] , invariant:: Valid , _ >( ) ;
176+ let c = c. transmute:: <[ u8 ] , invariant:: Valid , BecauseImmutable >( ) ;
177177 let c = c. unaligned_as_ref( ) ;
178178 core:: str :: from_utf8( c) . is_ok( )
179179 } )
180180} ;
181181
182- impl_size_eq ! ( str , [ u8 ] ) ;
182+ impl_size_eq ! ( => str , [ u8 ] ) ;
183183
184184macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
185185 ( $( $nonzero: ident[ $prim: ty] ) ,* ) => {
186186 $(
187187 unsafe_impl!( => TryFromBytes for $nonzero; |n| {
188- impl_size_eq!( $nonzero, Unalign <$prim>) ;
188+ impl_size_eq!( => $nonzero, Unalign <$prim>) ;
189189
190- let n = n. transmute:: <Unalign <$prim>, invariant:: Valid , _ >( ) ;
190+ let n = n. transmute:: <Unalign <$prim>, invariant:: Valid , BecauseImmutable >( ) ;
191191 $nonzero:: new( n. read_unaligned( ) . into_inner( ) ) . is_some( )
192192 } ) ;
193193 ) *
@@ -403,13 +403,23 @@ const _: () = unsafe {
403403mod atomics {
404404 use super :: * ;
405405
406- macro_rules! impl_traits_for_atomics {
407- ( $( $atomics: ident [ $primitives: ident] ) ,* $( , ) ?) => {
406+ macro_rules! impl_layout_traits_for_atomics {
407+ ( $( $( $tyvar: ident) ? => $atomics: ty [ $primitives: ty] ) ,* $( , ) ?) => {
408+ $(
409+ impl_known_layout!( $( $tyvar => ) ? $atomics) ;
410+
411+ impl_size_eq!( $( $tyvar) ? => $atomics, $primitives) ;
412+ impl_size_eq!( $( $tyvar) ? => $atomics, UnsafeCell <$primitives>) ;
413+ ) *
414+ } ;
415+ }
416+
417+ macro_rules! impl_validity_traits_for_atomics {
418+ ( $( $atomics: tt [ $primitives: ty] ) ,* $( , ) ?) => {
408419 $(
409- impl_known_layout!( $atomics) ;
410- impl_for_transmute_from!( => TryFromBytes for $atomics [ UnsafeCell <$primitives>] ) ;
411420 impl_for_transmute_from!( => FromZeros for $atomics [ UnsafeCell <$primitives>] ) ;
412421 impl_for_transmute_from!( => FromBytes for $atomics [ UnsafeCell <$primitives>] ) ;
422+ impl_for_transmute_from!( => TryFromBytes for $atomics [ UnsafeCell <$primitives>] ) ;
413423 impl_for_transmute_from!( => IntoBytes for $atomics [ UnsafeCell <$primitives>] ) ;
414424 ) *
415425 } ;
@@ -425,8 +435,7 @@ mod atomics {
425435 ( $( $( $tyvar: ident) ? => $atomic: ty [ $prim: ty] ) ,* ) => { {
426436 crate :: util:: macros:: __unsafe( ) ;
427437
428- use core:: cell:: UnsafeCell ;
429- use crate :: pointer:: { SizeEq , TransmuteFrom , invariant:: Valid } ;
438+ use crate :: pointer:: { TransmuteFrom , invariant:: Valid } ;
430439
431440 $(
432441 // SAFETY: The caller promised that `$atomic` and `$prim` have
@@ -436,18 +445,18 @@ mod atomics {
436445 // the same size and bit validity.
437446 unsafe impl <$( $tyvar) ?> TransmuteFrom <$prim, Valid , Valid > for $atomic { }
438447
439- impl <$( $tyvar) ?> SizeEq <$atomic> for $prim {
440- type CastFrom = $crate:: pointer:: cast:: CastSizedExact ;
441- }
442- impl <$( $tyvar) ?> SizeEq <$prim> for $atomic {
443- type CastFrom = $crate:: pointer:: cast:: CastSizedExact ;
444- }
445- impl <$( $tyvar) ?> SizeEq <$atomic> for UnsafeCell <$prim> {
446- type CastFrom = $crate:: pointer:: cast:: CastSizedExact ;
447- }
448- impl <$( $tyvar) ?> SizeEq <UnsafeCell <$prim>> for $atomic {
449- type CastFrom = $crate:: pointer:: cast:: CastSizedExact ;
450- }
448+ // impl<$($tyvar)?> SizeEq<$atomic> for $prim {
449+ // type CastFrom = $crate::pointer::cast::CastSizedExact;
450+ // }
451+ // impl<$($tyvar)?> SizeEq<$prim> for $atomic {
452+ // type CastFrom = $crate::pointer::cast::CastSizedExact;
453+ // }
454+ // impl<$($tyvar)?> SizeEq<$atomic> for UnsafeCell<$prim> {
455+ // type CastFrom = $crate::pointer::cast::CastSizedExact;
456+ // }
457+ // impl<$($tyvar)?> SizeEq<UnsafeCell<$prim>> for $atomic {
458+ // type CastFrom = $crate::pointer::cast::CastSizedExact;
459+ // }
451460
452461 // SAFETY: The caller promised that `$atomic` and `$prim` have
453462 // the same bit validity. `UnsafeCell<T>` has the same bit
@@ -472,12 +481,11 @@ mod atomics {
472481
473482 use super :: * ;
474483
475- impl_traits_for_atomics ! ( AtomicU8 [ u8 ] , AtomicI8 [ i8 ] ) ;
476-
477- impl_known_layout ! ( AtomicBool ) ;
484+ impl_layout_traits_for_atomics ! ( => AtomicBool [ bool ] , => AtomicU8 [ u8 ] , => AtomicI8 [ i8 ] ) ;
485+ impl_validity_traits_for_atomics ! ( AtomicU8 [ u8 ] , AtomicI8 [ i8 ] ) ;
478486
479- impl_for_transmute_from ! ( => TryFromBytes for AtomicBool [ UnsafeCell <bool >] ) ;
480487 impl_for_transmute_from ! ( => FromZeros for AtomicBool [ UnsafeCell <bool >] ) ;
488+ impl_for_transmute_from ! ( => TryFromBytes for AtomicBool [ UnsafeCell <bool >] ) ;
481489 impl_for_transmute_from ! ( => IntoBytes for AtomicBool [ UnsafeCell <bool >] ) ;
482490
483491 // SAFETY: Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the
@@ -539,7 +547,8 @@ mod atomics {
539547
540548 use super :: * ;
541549
542- impl_traits_for_atomics ! ( AtomicU16 [ u16 ] , AtomicI16 [ i16 ] ) ;
550+ impl_layout_traits_for_atomics ! ( => AtomicU16 [ u16 ] , => AtomicI16 [ i16 ] ) ;
551+ impl_validity_traits_for_atomics ! ( AtomicU16 [ u16 ] , AtomicI16 [ i16 ] ) ;
543552
544553 // SAFETY: `AtomicU16` and `AtomicI16` have the same size and bit
545554 // validity as `u16` and `i16` respectively [1][2].
@@ -566,7 +575,8 @@ mod atomics {
566575
567576 use super :: * ;
568577
569- impl_traits_for_atomics ! ( AtomicU32 [ u32 ] , AtomicI32 [ i32 ] ) ;
578+ impl_layout_traits_for_atomics ! ( => AtomicU32 [ u32 ] , => AtomicI32 [ i32 ] ) ;
579+ impl_validity_traits_for_atomics ! ( AtomicU32 [ u32 ] , AtomicI32 [ i32 ] ) ;
570580
571581 // SAFETY: `AtomicU32` and `AtomicI32` have the same size and bit
572582 // validity as `u32` and `i32` respectively [1][2].
@@ -593,7 +603,8 @@ mod atomics {
593603
594604 use super :: * ;
595605
596- impl_traits_for_atomics ! ( AtomicU64 [ u64 ] , AtomicI64 [ i64 ] ) ;
606+ impl_layout_traits_for_atomics ! ( => AtomicU64 [ u64 ] , => AtomicI64 [ i64 ] ) ;
607+ impl_validity_traits_for_atomics ! ( AtomicU64 [ u64 ] , AtomicI64 [ i64 ] ) ;
597608
598609 // SAFETY: `AtomicU64` and `AtomicI64` have the same size and bit
599610 // validity as `u64` and `i64` respectively [1][2].
@@ -620,9 +631,8 @@ mod atomics {
620631
621632 use super :: * ;
622633
623- impl_traits_for_atomics ! ( AtomicUsize [ usize ] , AtomicIsize [ isize ] ) ;
624-
625- impl_known_layout ! ( T => AtomicPtr <T >) ;
634+ impl_layout_traits_for_atomics ! ( T => AtomicPtr <T > [ * mut T ] , => AtomicUsize [ usize ] , => AtomicIsize [ isize ] ) ;
635+ impl_validity_traits_for_atomics ! ( AtomicUsize [ usize ] , AtomicIsize [ isize ] ) ;
626636
627637 // FIXME(#170): Implement `FromBytes` and `IntoBytes` once we implement
628638 // those traits for `*mut T`.
@@ -851,29 +861,30 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
851861 }
852862
853863 #[ inline]
854- fn is_bit_valid < A : invariant:: Reference > ( candidate : Maybe < ' _ , Self , A > ) -> bool {
855- // The only way to implement this function is using an exclusive-aliased
856- // pointer. `UnsafeCell`s cannot be read via shared-aliased pointers
857- // (other than by using `unsafe` code, which we can't use since we can't
858- // guarantee how our users are accessing or modifying the `UnsafeCell`).
859- //
860- // `is_bit_valid` is documented as panicking or failing to monomorphize
861- // if called with a shared-aliased pointer on a type containing an
862- // `UnsafeCell`. In practice, it will always be a monomorphization error.
863- // Since `is_bit_valid` is `#[doc(hidden)]` and only called directly
864- // from this crate, we only need to worry about our own code incorrectly
865- // calling `UnsafeCell::is_bit_valid`. The post-monomorphization error
866- // makes it easier to test that this is truly the case, and also means
867- // that if we make a mistake, it will cause downstream code to fail to
868- // compile, which will immediately surface the mistake and give us a
869- // chance to fix it quickly.
870- let c = candidate. into_exclusive_or_pme ( ) ;
871-
872- // SAFETY: Since `UnsafeCell<T>` and `T` have the same layout and bit
873- // validity, `UnsafeCell<T>` is bit-valid exactly when its wrapped `T`
874- // is. Thus, this is a sound implementation of
875- // `UnsafeCell::is_bit_valid`.
876- T :: is_bit_valid ( c. get_mut ( ) )
864+ fn is_bit_valid ( candidate : Maybe < ' _ , Self > ) -> bool {
865+ T :: is_bit_valid ( candidate. transmute :: < _ , _ , BecauseImmutable > ( ) )
866+ // // The only way to implement this function is using an exclusive-aliased
867+ // // pointer. `UnsafeCell`s cannot be read via shared-aliased pointers
868+ // // (other than by using `unsafe` code, which we can't use since we can't
869+ // // guarantee how our users are accessing or modifying the `UnsafeCell`).
870+ // //
871+ // // `is_bit_valid` is documented as panicking or failing to monomorphize
872+ // // if called with a shared-aliased pointer on a type containing an
873+ // // `UnsafeCell`. In practice, it will always be a monomorphization error.
874+ // // Since `is_bit_valid` is `#[doc(hidden)]` and only called directly
875+ // // from this crate, we only need to worry about our own code incorrectly
876+ // // calling `UnsafeCell::is_bit_valid`. The post-monomorphization error
877+ // // makes it easier to test that this is truly the case, and also means
878+ // // that if we make a mistake, it will cause downstream code to fail to
879+ // // compile, which will immediately surface the mistake and give us a
880+ // // chance to fix it quickly.
881+ // let c = candidate.into_exclusive_or_pme();
882+
883+ // // SAFETY: Since `UnsafeCell<T>` and `T` have the same layout and bit
884+ // // validity, `UnsafeCell<T>` is bit-valid exactly when its wrapped `T`
885+ // // is. Thus, this is a sound implementation of
886+ // // `UnsafeCell::is_bit_valid`.
887+ // T::is_bit_valid(c.get_mut())
877888 }
878889}
879890
@@ -902,11 +913,15 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
902913const _: ( ) = unsafe {
903914 unsafe_impl ! ( const N : usize , T : Immutable => Immutable for [ T ; N ] ) ;
904915 unsafe_impl ! ( const N : usize , T : TryFromBytes => TryFromBytes for [ T ; N ] ; |c| {
916+ let c: Ptr <' _, [ ReadOnly <T >; N ] , _> = c. cast:: <_, crate :: pointer:: cast:: CastSized , _>( ) ;
917+ let c: Ptr <' _, [ ReadOnly <T >] , _> = c. as_slice( ) ;
918+ let c: Ptr <' _, ReadOnly <[ T ] >, _> = c. cast:: <_, crate :: pointer:: cast:: CastUnsized , _>( ) ;
919+
905920 // Note that this call may panic, but it would still be sound even if it
906921 // did. `is_bit_valid` does not promise that it will not panic (in fact,
907922 // it explicitly warns that it's a possibility), and we have not
908923 // violated any safety invariants that we must fix before returning.
909- <[ T ] as TryFromBytes >:: is_bit_valid( c. as_slice ( ) )
924+ <[ T ] as TryFromBytes >:: is_bit_valid( c)
910925 } ) ;
911926 unsafe_impl ! ( const N : usize , T : FromZeros => FromZeros for [ T ; N ] ) ;
912927 unsafe_impl ! ( const N : usize , T : FromBytes => FromBytes for [ T ; N ] ) ;
@@ -915,6 +930,8 @@ const _: () = unsafe {
915930 assert_unaligned ! ( [ ( ) ; 0 ] , [ ( ) ; 1 ] , [ u8 ; 0 ] , [ u8 ; 1 ] ) ;
916931 unsafe_impl ! ( T : Immutable => Immutable for [ T ] ) ;
917932 unsafe_impl ! ( T : TryFromBytes => TryFromBytes for [ T ] ; |c| {
933+ let c: Ptr <' _, [ ReadOnly <T >] , _> = c. cast:: <_, crate :: pointer:: cast:: CastUnsized , _>( ) ;
934+
918935 // SAFETY: Per the reference [1]:
919936 //
920937 // An array of `[T; N]` has a size of `size_of::<T>() * N` and the
@@ -1146,6 +1163,7 @@ mod tests {
11461163 use super :: * ;
11471164 use crate :: pointer:: invariant;
11481165
1166+ #[ cfg( never) ]
11491167 #[ test]
11501168 fn test_impls ( ) {
11511169 // A type that can supply test cases for testing
0 commit comments