@@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
4
4
use rustc_hir:: Expr ;
5
5
use rustc_lint:: LateContext ;
6
6
use rustc_middle:: ty:: subst:: Subst ;
7
- use rustc_middle:: ty:: { self , Ty , TypeAndMut } ;
7
+ use rustc_middle:: ty:: { self , IntTy , Ty , TypeAndMut , UintTy } ;
8
8
use rustc_span:: Span ;
9
9
10
10
#[ allow( clippy:: too_many_lines) ]
@@ -23,7 +23,8 @@ pub(super) fn check<'tcx>(
23
23
unsized_ty,
24
24
to_ty : to_sub_ty,
25
25
} => match reduce_ty ( cx, to_sub_ty) {
26
- ReducedTy :: IntArray | ReducedTy :: TypeErasure => break ,
26
+ ReducedTy :: TypeErasure => break ,
27
+ ReducedTy :: UnorderedFields ( ty) if is_size_pair ( ty) => break ,
27
28
ReducedTy :: Ref ( to_sub_ty) => {
28
29
from_ty = unsized_ty;
29
30
to_ty = to_sub_ty;
@@ -48,7 +49,8 @@ pub(super) fn check<'tcx>(
48
49
unsized_ty,
49
50
from_ty : from_sub_ty,
50
51
} => match reduce_ty ( cx, from_sub_ty) {
51
- ReducedTy :: IntArray | ReducedTy :: TypeErasure => break ,
52
+ ReducedTy :: TypeErasure => break ,
53
+ ReducedTy :: UnorderedFields ( ty) if is_size_pair ( ty) => break ,
52
54
ReducedTy :: Ref ( from_sub_ty) => {
53
55
from_ty = from_sub_ty;
54
56
to_ty = unsized_ty;
@@ -123,8 +125,7 @@ pub(super) fn check<'tcx>(
123
125
from_ty : from_sub_ty,
124
126
to_ty : to_sub_ty,
125
127
} => match ( reduce_ty ( cx, from_sub_ty) , reduce_ty ( cx, to_sub_ty) ) {
126
- ( ReducedTy :: IntArray | ReducedTy :: TypeErasure , _)
127
- | ( _, ReducedTy :: IntArray | ReducedTy :: TypeErasure ) => return false ,
128
+ ( ReducedTy :: TypeErasure , _) | ( _, ReducedTy :: TypeErasure ) => return false ,
128
129
( ReducedTy :: UnorderedFields ( from_ty) , ReducedTy :: UnorderedFields ( to_ty) ) if from_ty != to_ty => {
129
130
span_lint_and_then (
130
131
cx,
@@ -263,9 +264,6 @@ enum ReducedTy<'tcx> {
263
264
UnorderedFields ( Ty < ' tcx > ) ,
264
265
/// The type is a reference to the contained type.
265
266
Ref ( Ty < ' tcx > ) ,
266
- /// The type is an array of a primitive integer type. These can be used as storage for a value
267
- /// of another type.
268
- IntArray ,
269
267
/// Any other type.
270
268
Other ( Ty < ' tcx > ) ,
271
269
}
@@ -275,17 +273,18 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
275
273
loop {
276
274
ty = cx. tcx . try_normalize_erasing_regions ( cx. param_env , ty) . unwrap_or ( ty) ;
277
275
return match * ty. kind ( ) {
278
- ty:: Array ( sub_ty, _) if matches ! ( sub_ty. kind( ) , ty:: Int ( _) | ty:: Uint ( _) ) => ReducedTy :: IntArray ,
276
+ ty:: Array ( sub_ty, _) if matches ! ( sub_ty. kind( ) , ty:: Int ( _) | ty:: Uint ( _) ) => ReducedTy :: TypeErasure ,
279
277
ty:: Array ( sub_ty, _) | ty:: Slice ( sub_ty) => {
280
278
ty = sub_ty;
281
279
continue ;
282
280
} ,
283
281
ty:: Tuple ( args) if args. is_empty ( ) => ReducedTy :: TypeErasure ,
284
282
ty:: Tuple ( args) => {
285
- let Some ( sized_ty) = args. iter ( ) . find ( |& ty| !is_zero_sized_ty ( cx, ty) ) else {
283
+ let mut iter = args. iter ( ) ;
284
+ let Some ( sized_ty) = iter. find ( |& ty| !is_zero_sized_ty ( cx, ty) ) else {
286
285
return ReducedTy :: OrderedFields ( ty) ;
287
286
} ;
288
- if args . iter ( ) . all ( |ty| is_zero_sized_ty ( cx, ty) ) {
287
+ if iter. all ( |ty| is_zero_sized_ty ( cx, ty) ) {
289
288
ty = sized_ty;
290
289
continue ;
291
290
}
@@ -313,6 +312,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
313
312
ty:: Adt ( def, _) if def. is_enum ( ) && ( def. variants ( ) . is_empty ( ) || is_c_void ( cx, ty) ) => {
314
313
ReducedTy :: TypeErasure
315
314
} ,
315
+ // TODO: Check if the conversion to or from at least one of a union's fields is valid.
316
+ ty:: Adt ( def, _) if def. is_union ( ) => ReducedTy :: TypeErasure ,
316
317
ty:: Foreign ( _) => ReducedTy :: TypeErasure ,
317
318
ty:: Ref ( _, ty, _) => ReducedTy :: Ref ( ty) ,
318
319
ty:: RawPtr ( ty) => ReducedTy :: Ref ( ty. ty ) ,
@@ -332,3 +333,14 @@ fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
332
333
}
333
334
}
334
335
}
336
+
337
+ fn is_size_pair ( ty : Ty < ' _ > ) -> bool {
338
+ if let ty:: Tuple ( tys) = * ty. kind ( )
339
+ && let [ ty1, ty2] = & * * tys
340
+ {
341
+ matches ! ( ty1. kind( ) , ty:: Int ( IntTy :: Isize ) | ty:: Uint ( UintTy :: Usize ) )
342
+ && matches ! ( ty2. kind( ) , ty:: Int ( IntTy :: Isize ) | ty:: Uint ( UintTy :: Usize ) )
343
+ } else {
344
+ false
345
+ }
346
+ }
0 commit comments