@@ -182,22 +182,15 @@ macro_rules! transmute_ref {
182182            // this macro expression is `&U` where `U: 'u + Sized + FromBytes + 
183183            // Immutable`, and that `'t` outlives `'u`. 
184184
185-             struct  AssertSrcIsSized <' a,  T :  :: core:: marker:: Sized >( & ' a T ) ; 
186185            struct  AssertSrcIsIntoBytes <' a,  T :  ?:: core:: marker:: Sized  + $crate:: IntoBytes >( & ' a T ) ; 
187186            struct  AssertSrcIsImmutable <' a,  T :  ?:: core:: marker:: Sized  + $crate:: Immutable >( & ' a T ) ; 
188-             struct  AssertDstIsSized <' a,  T :  :: core:: marker:: Sized >( & ' a T ) ; 
189187            struct  AssertDstIsFromBytes <' a,  U :  ?:: core:: marker:: Sized  + $crate:: FromBytes >( & ' a U ) ; 
190188            struct  AssertDstIsImmutable <' a,  T :  ?:: core:: marker:: Sized  + $crate:: Immutable >( & ' a T ) ; 
191189
192-             let  _ = AssertSrcIsSized ( e) ; 
193190            let  _ = AssertSrcIsIntoBytes ( e) ; 
194191            let  _ = AssertSrcIsImmutable ( e) ; 
195192
196193            if  true  { 
197-                 #[ allow( unused,  unreachable_code) ] 
198-                 let  u = AssertDstIsSized ( loop  { } ) ; 
199-                 u. 0 
200-             }  else if  true  { 
201194                #[ allow( unused,  unreachable_code) ] 
202195                let  u = AssertDstIsFromBytes ( loop  { } ) ; 
203196                u. 0 
@@ -206,36 +199,13 @@ macro_rules! transmute_ref {
206199                let  u = AssertDstIsImmutable ( loop  { } ) ; 
207200                u. 0 
208201            } 
209-         }  else if  false  { 
210-             // This branch, though never taken, ensures that `size_of::<T>() == 
211-             // size_of::<U>()` and that that `align_of::<T>() >= 
212-             // align_of::<U>()`. 
213- 
214-             // `t` is inferred to have type `T` because it's assigned to `e` (of 
215-             // type `&T`) as `&t`. 
216-             let  mut  t = loop  { } ; 
217-             e = & t; 
218- 
219-             // `u` is inferred to have type `U` because it's used as `&u` as the 
220-             // value returned from this branch. 
221-             let  u; 
222- 
223-             $crate:: assert_size_eq!( t,  u) ; 
224-             $crate:: assert_align_gt_eq!( t,  u) ; 
225- 
226-             & u
227202        }  else { 
228-             // SAFETY: For source type `Src` and destination type `Dst`: 
229-             // - We know that `Src: IntoBytes + Immutable` and `Dst: FromBytes + 
230-             //   Immutable` thanks to the uses of `AssertSrcIsIntoBytes`, 
231-             //   `AssertSrcIsImmutable`, `AssertDstIsFromBytes`, and 
232-             //   `AssertDstIsImmutable` above. 
233-             // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to 
234-             //   the use of `assert_size_eq!` above. 
235-             // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to 
236-             //   the use of `assert_align_gt_eq!` above. 
237-             let  u = unsafe  {  $crate:: util:: macro_util:: transmute_ref( e)  } ; 
238-             $crate:: util:: macro_util:: must_use( u) 
203+             use  $crate:: util:: macro_util:: TransmuteRefDst ; 
204+             let  t = $crate:: util:: macro_util:: Wrap ( e) ; 
205+             // SAFETY: todo 
206+             unsafe  { 
207+                 t. transmute_ref( ) 
208+             } 
239209        } 
240210    } } 
241211} 
@@ -334,26 +304,18 @@ macro_rules! transmute_mut {
334304            // writing, mutable references are banned), the error message 
335305            // appears to originate in the user's code rather than in the 
336306            // internals of this macro. 
337-             struct  AssertSrcIsSized <' a,  T :  :: core:: marker:: Sized >( & ' a T ) ; 
338307            struct  AssertSrcIsFromBytes <' a,  T :  ?:: core:: marker:: Sized  + $crate:: FromBytes >( & ' a T ) ; 
339308            struct  AssertSrcIsIntoBytes <' a,  T :  ?:: core:: marker:: Sized  + $crate:: IntoBytes >( & ' a T ) ; 
340-             struct  AssertDstIsSized <' a,  T :  :: core:: marker:: Sized >( & ' a T ) ; 
341309            struct  AssertDstIsFromBytes <' a,  T :  ?:: core:: marker:: Sized  + $crate:: FromBytes >( & ' a T ) ; 
342310            struct  AssertDstIsIntoBytes <' a,  T :  ?:: core:: marker:: Sized  + $crate:: IntoBytes >( & ' a T ) ; 
343311
344312            if  true  { 
345-                 let  _ = AssertSrcIsSized ( & * e) ; 
346-             }  else if  true  { 
347313                let  _ = AssertSrcIsFromBytes ( & * e) ; 
348314            }  else { 
349315                let  _ = AssertSrcIsIntoBytes ( & * e) ; 
350316            } 
351317
352318            if  true  { 
353-                 #[ allow( unused,  unreachable_code) ] 
354-                 let  u = AssertDstIsSized ( loop  { } ) ; 
355-                 & mut  * u. 0 
356-             }  else if  true  { 
357319                #[ allow( unused,  unreachable_code) ] 
358320                let  u = AssertDstIsFromBytes ( loop  { } ) ; 
359321                & mut  * u. 0 
@@ -362,32 +324,13 @@ macro_rules! transmute_mut {
362324                let  u = AssertDstIsIntoBytes ( loop  { } ) ; 
363325                & mut  * u. 0 
364326            } 
365-         }  else if  false  { 
366-             // This branch, though never taken, ensures that `size_of::<T>() == 
367-             // size_of::<U>()` and that that `align_of::<T>() >= 
368-             // align_of::<U>()`. 
369- 
370-             // `t` is inferred to have type `T` because it's assigned to `e` (of 
371-             // type `&mut T`) as `&mut t`. 
372-             let  mut  t = loop  { } ; 
373-             e = & mut  t; 
374- 
375-             // `u` is inferred to have type `U` because it's used as `&mut u` as 
376-             // the value returned from this branch. 
377-             let  u; 
378- 
379-             $crate:: assert_size_eq!( t,  u) ; 
380-             $crate:: assert_align_gt_eq!( t,  u) ; 
381- 
382-             & mut  u
383327        }  else { 
384-             // SAFETY: For source type `Src` and destination type `Dst`: 
385-             // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to 
386-             //   the use of `assert_size_eq!` above. 
387-             // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to 
388-             //   the use of `assert_align_gt_eq!` above. 
389-             let  u = unsafe  {  $crate:: util:: macro_util:: transmute_mut( e)  } ; 
390-             $crate:: util:: macro_util:: must_use( u) 
328+             use  $crate:: util:: macro_util:: TransmuteMutDst ; 
329+             let  t = $crate:: util:: macro_util:: Wrap ( e) ; 
330+             // SAFETY: todo 
331+             unsafe  { 
332+                 t. transmute_mut( ) 
333+             } 
391334        } 
392335    } } 
393336} 
@@ -1038,6 +981,18 @@ mod tests {
1038981        assert_eq ! ( x. into_inner( ) ,  1 ) ; 
1039982    } 
1040983
984+     // A `Sized` type which doesn't implement `KnownLayout` (it is "not 
985+     // `KnownLayout`", or `Nkl`). 
986+     // 
987+     // This permits us to test that `transmute_ref!` and `transmute_mut!` work 
988+     // for types which are `Sized + !KnownLayout`. When we added support for 
989+     // slice DSTs in #1924, this new support relied on `KnownLayout`, but we 
990+     // need to make sure to remain backwards-compatible with code which ueses 
991+     // these macros with types which are `!KnownLayout`. 
992+     #[ derive( FromBytes ,  IntoBytes ,  Immutable ,  PartialEq ,  Eq ,  Debug ) ]  
993+     #[ repr( transparent) ]  
994+     struct  Nkl < T > ( T ) ; 
995+ 
1041996    #[ test]  
1042997    fn  test_transmute_ref ( )  { 
1043998        // Test that memory is transmuted as expected. 
@@ -1055,6 +1010,49 @@ mod tests {
10551010        const  X :  & ' static  [ [ u8 ;  2 ] ;  4 ]  = transmute_ref ! ( & ARRAY_OF_U8S ) ; 
10561011        assert_eq ! ( * X ,  ARRAY_OF_ARRAYS ) ; 
10571012
1013+         // Call through a generic function to make sure our autoref 
1014+         // specialization trick works even when types are generic. 
1015+         const  fn  transmute_ref < T ,  U > ( t :  & T )  -> & U 
1016+         where 
1017+             T :  IntoBytes  + Immutable , 
1018+             U :  FromBytes  + Immutable , 
1019+         { 
1020+             transmute_ref ! ( t) 
1021+         } 
1022+ 
1023+         // Test that `transmute_ref!` supports non-`KnownLayout` `Sized` types. 
1024+         const  ARRAY_OF_NKL_U8S :  Nkl < [ u8 ;  8 ] >  = Nkl ( [ 0u8 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ] ) ; 
1025+         const  ARRAY_OF_NKL_ARRAYS :  Nkl < [ [ u8 ;  2 ] ;  4 ] >  = Nkl ( [ [ 0 ,  1 ] ,  [ 2 ,  3 ] ,  [ 4 ,  5 ] ,  [ 6 ,  7 ] ] ) ; 
1026+         const  X_NKL :  & Nkl < [ [ u8 ;  2 ] ;  4 ] >  = transmute_ref ( & ARRAY_OF_NKL_U8S ) ; 
1027+         assert_eq ! ( * X_NKL ,  ARRAY_OF_NKL_ARRAYS ) ; 
1028+ 
1029+         // Test that `transmute_ref!` works on slice DSTs in and that memory is 
1030+         // transmuted as expected. 
1031+         #[ derive( KnownLayout ,  Immutable ,  FromBytes ,  IntoBytes ,  PartialEq ,  Debug ) ]  
1032+         #[ repr( C ) ]  
1033+         struct  SliceDst < T >  { 
1034+             a :  U16 , 
1035+             b :  [ T ] , 
1036+         } 
1037+ 
1038+         use  crate :: byteorder:: native_endian:: U16 ; 
1039+         let  slice_dst_of_u8s =
1040+             SliceDst :: < [ u8 ;  2 ] > :: ref_from_bytes ( & [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ] [ ..] ) . unwrap ( ) ; 
1041+         let  slice_dst_of_u16s = SliceDst :: < U16 > :: ref_from_bytes ( & [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ] [ ..] ) . unwrap ( ) ; 
1042+         let  x:  & SliceDst < U16 >  = transmute_ref ! ( slice_dst_of_u8s) ; 
1043+         assert_eq ! ( x,  slice_dst_of_u16s) ; 
1044+ 
1045+         let  slice_dst_of_u8s = SliceDst :: < u8 > :: ref_from_bytes ( & [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ] [ ..] ) . unwrap ( ) ; 
1046+         let  x:  & [ u8 ]  = transmute_ref ! ( slice_dst_of_u8s) ; 
1047+         assert_eq ! ( x,  [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ] ) ; 
1048+ 
1049+         let  x:  & [ u8 ]  = transmute_ref ! ( slice_dst_of_u16s) ; 
1050+         assert_eq ! ( x,  [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ] ) ; 
1051+ 
1052+         let  x:  & [ U16 ]  = transmute_ref ! ( slice_dst_of_u16s) ; 
1053+         let  slice_of_u16s:  & [ U16 ]  = <[ U16 ] >:: ref_from_bytes ( & [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ] [ ..] ) . unwrap ( ) ; 
1054+         assert_eq ! ( x,  slice_of_u16s) ; 
1055+ 
10581056        // Test that it's legal to transmute a reference while shrinking the 
10591057        // lifetime (note that `X` has the lifetime `'static`). 
10601058        let  x:  & [ u8 ;  8 ]  = transmute_ref ! ( X ) ; 
@@ -1198,6 +1196,15 @@ mod tests {
11981196            let  x:  & mut  [ u8 ;  8 ]  = transmute_mut ! ( & mut  array_of_arrays) ; 
11991197            assert_eq ! ( * x,  array_of_u8s) ; 
12001198        } 
1199+ 
1200+         // Test that `transmute_mut!` supports non-`KnownLayout` types. 
1201+         let  mut  array_of_u8s = Nkl ( [ 0u8 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ] ) ; 
1202+         let  mut  array_of_arrays = Nkl ( [ [ 0 ,  1 ] ,  [ 2 ,  3 ] ,  [ 4 ,  5 ] ,  [ 6 ,  7 ] ] ) ; 
1203+         let  x:  & mut  Nkl < [ [ u8 ;  2 ] ;  4 ] >  = transmute_mut ! ( & mut  array_of_u8s) ; 
1204+         assert_eq ! ( * x,  array_of_arrays) ; 
1205+         let  x:  & mut  Nkl < [ u8 ;  8 ] >  = transmute_mut ! ( & mut  array_of_arrays) ; 
1206+         assert_eq ! ( * x,  array_of_u8s) ; 
1207+ 
12011208        // Test that `transmute_mut!` supports decreasing alignment. 
12021209        let  mut  u = AU64 ( 0 ) ; 
12031210        let  array = [ 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] ; 
@@ -1209,6 +1216,30 @@ mod tests {
12091216        #[ allow( clippy:: useless_transmute) ]  
12101217        let  y:  & u8  = transmute_mut ! ( & mut  x) ; 
12111218        assert_eq ! ( * y,  0 ) ; 
1219+ 
1220+         // Test that `transmute_mut!` works on slice DSTs in and that memory is 
1221+         // transmuted as expected. 
1222+         #[ derive( KnownLayout ,  Immutable ,  FromBytes ,  IntoBytes ,  PartialEq ,  Debug ) ]  
1223+         #[ repr( C ) ]  
1224+         struct  SliceDst < T >  { 
1225+             a :  u8 , 
1226+             b :  [ T ] , 
1227+         } 
1228+ 
1229+         use  crate :: byteorder:: native_endian:: U16 ; 
1230+         let  mut  bytes = [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ] ; 
1231+         let  slice_dst_of_u8s = SliceDst :: < [ u8 ;  2 ] > :: mut_from_bytes ( & mut  bytes[ ..] ) . unwrap ( ) ; 
1232+         let  mut  bytes = [ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ] ; 
1233+         let  slice_dst_of_u16s = SliceDst :: < U16 > :: mut_from_bytes ( & mut  bytes[ ..] ) . unwrap ( ) ; 
1234+         let  x:  & mut  SliceDst < U16 >  = transmute_mut ! ( slice_dst_of_u8s) ; 
1235+         assert_eq ! ( x,  slice_dst_of_u16s) ; 
1236+ 
1237+         // Test that `transmute_mut!` works on slices that memory is transmuted 
1238+         // as expected. 
1239+         let  array_of_u16s:  & mut  [ u16 ]  = & mut  [ 0u16 ,  1 ,  2 ] ; 
1240+         let  array_of_i16s:  & mut  [ i16 ]  = & mut  [ 0i16 ,  1 ,  2 ] ; 
1241+         let  x:  & mut  [ i16 ]  = transmute_mut ! ( array_of_u16s) ; 
1242+         assert_eq ! ( x,  array_of_i16s) ; 
12121243    } 
12131244
12141245    #[ test]  
0 commit comments