@@ -164,9 +164,18 @@ pub(super) fn check<'tcx>(
164
164
) ;
165
165
return true ;
166
166
} ,
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
+ } ,
167
176
(
168
177
ReducedTy :: UnorderedFields ( from_ty) ,
169
- ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( _ ) | ReducedTy :: Ref ( _) ,
178
+ ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( .. ) | ReducedTy :: Ref ( _) ,
170
179
) => {
171
180
span_lint_and_then (
172
181
cx,
@@ -182,7 +191,7 @@ pub(super) fn check<'tcx>(
182
191
return true ;
183
192
} ,
184
193
(
185
- ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( _ ) | ReducedTy :: Ref ( _) ,
194
+ ReducedTy :: Other ( _) | ReducedTy :: OrderedFields ( .. ) | ReducedTy :: Ref ( _) ,
186
195
ReducedTy :: UnorderedFields ( to_ty) ,
187
196
) => {
188
197
span_lint_and_then (
@@ -198,14 +207,9 @@ pub(super) fn check<'tcx>(
198
207
) ;
199
208
return true ;
200
209
} ,
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
- } ,
206
210
(
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 ,
209
213
)
210
214
| (
211
215
ReducedTy :: UnorderedFields ( _) | ReducedTy :: Param ,
@@ -269,7 +273,8 @@ enum ReducedTy<'tcx> {
269
273
TypeErasure ,
270
274
/// The type is a struct containing either zero non-zero sized fields, or multiple non-zero
271
275
/// 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 > > ) ,
273
278
/// The type is a struct containing multiple non-zero sized fields with no defined order.
274
279
UnorderedFields ( Ty < ' tcx > ) ,
275
280
/// 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>
294
299
ty:: Tuple ( args) => {
295
300
let mut iter = args. iter ( ) ;
296
301
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 ) ;
298
303
} ;
299
304
if iter. all ( |ty| is_zero_sized_ty ( cx, ty) ) {
300
305
ty = sized_ty;
@@ -316,7 +321,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
316
321
continue ;
317
322
}
318
323
if def. repr ( ) . inhibit_struct_field_reordering_opt ( ) {
319
- ReducedTy :: OrderedFields ( ty)
324
+ ReducedTy :: OrderedFields ( ty, Some ( sized_ty ) )
320
325
} else {
321
326
ReducedTy :: UnorderedFields ( ty)
322
327
}
0 commit comments