@@ -164,9 +164,18 @@ pub(super) fn check<'tcx>(
164164 ) ;
165165 return true ;
166166 } ,
167+ // `Repr(C)` <-> unordered type.
168+ // If the first field of the `Repr(C)` type matches then the transmute is ok
169+ ( ReducedTy :: OrderedFields ( _, Some ( from_sub_ty) ) , ReducedTy :: UnorderedFields ( to_sub_ty) )
170+ | ( ReducedTy :: UnorderedFields ( from_sub_ty) , ReducedTy :: OrderedFields ( _, Some ( to_sub_ty) ) )
171+ | ( ReducedTy :: Ref ( from_sub_ty) , ReducedTy :: Ref ( to_sub_ty) ) => {
172+ from_ty = from_sub_ty;
173+ to_ty = to_sub_ty;
174+ continue ;
175+ } ,
167176 (
168177 ReducedTy :: UnorderedFields ( from_ty) ,
169- ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( _ ) | ReducedTy :: Ref ( _) ,
178+ ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( .. ) | ReducedTy :: Ref ( _) ,
170179 ) => {
171180 span_lint_and_then (
172181 cx,
@@ -182,7 +191,7 @@ pub(super) fn check<'tcx>(
182191 return true ;
183192 } ,
184193 (
185- ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( _ ) | ReducedTy :: Ref ( _) ,
194+ ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( .. ) | ReducedTy :: Ref ( _) ,
186195 ReducedTy :: UnorderedFields ( to_ty) ,
187196 ) => {
188197 span_lint_and_then (
@@ -198,14 +207,9 @@ pub(super) fn check<'tcx>(
198207 ) ;
199208 return true ;
200209 } ,
201- ( ReducedTy :: Ref ( from_sub_ty) , ReducedTy :: Ref ( to_sub_ty) ) => {
202- from_ty = from_sub_ty;
203- to_ty = to_sub_ty;
204- continue ;
205- } ,
206210 (
207- ReducedTy :: OrderedFields ( _ ) | ReducedTy :: Ref ( _) | ReducedTy :: Other ( _) | ReducedTy :: Param ,
208- ReducedTy :: OrderedFields ( _ ) | ReducedTy :: Ref ( _) | ReducedTy :: Other ( _) | ReducedTy :: Param ,
211+ ReducedTy :: OrderedFields ( .. ) | ReducedTy :: Ref ( _) | ReducedTy :: Other ( _) | ReducedTy :: Param ,
212+ ReducedTy :: OrderedFields ( .. ) | ReducedTy :: Ref ( _) | ReducedTy :: Other ( _) | ReducedTy :: Param ,
209213 )
210214 | (
211215 ReducedTy :: UnorderedFields ( _) | ReducedTy :: Param ,
@@ -269,7 +273,8 @@ enum ReducedTy<'tcx> {
269273 TypeErasure ,
270274 /// The type is a struct containing either zero non-zero sized fields, or multiple non-zero
271275 /// sized fields with a defined order.
272- OrderedFields ( Ty < ' tcx > ) ,
276+ /// The second value is the first non-zero sized type.
277+ OrderedFields ( Ty < ' tcx > , Option < Ty < ' tcx > > ) ,
273278 /// The type is a struct containing multiple non-zero sized fields with no defined order.
274279 UnorderedFields ( Ty < ' tcx > ) ,
275280 /// The type is a reference to the contained type.
@@ -294,7 +299,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
294299 ty:: Tuple ( args) => {
295300 let mut iter = args. iter ( ) ;
296301 let Some ( sized_ty) = iter. find ( |& ty| !is_zero_sized_ty ( cx, ty) ) else {
297- return ReducedTy :: OrderedFields ( ty) ;
302+ return ReducedTy :: OrderedFields ( ty, None ) ;
298303 } ;
299304 if iter. all ( |ty| is_zero_sized_ty ( cx, ty) ) {
300305 ty = sized_ty;
@@ -316,7 +321,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
316321 continue ;
317322 }
318323 if def. repr ( ) . inhibit_struct_field_reordering_opt ( ) {
319- ReducedTy :: OrderedFields ( ty)
324+ ReducedTy :: OrderedFields ( ty, Some ( sized_ty ) )
320325 } else {
321326 ReducedTy :: UnorderedFields ( ty)
322327 }
0 commit comments