@@ -4,7 +4,7 @@ use clippy_utils::ty::is_c_void;
44use rustc_hir:: Expr ;
55use rustc_lint:: LateContext ;
66use rustc_middle:: ty:: subst:: Subst ;
7- use rustc_middle:: ty:: { self , Ty , TypeAndMut } ;
7+ use rustc_middle:: ty:: { self , IntTy , Ty , TypeAndMut , UintTy } ;
88use rustc_span:: Span ;
99
1010#[ allow( clippy:: too_many_lines) ]
@@ -23,7 +23,8 @@ pub(super) fn check<'tcx>(
2323 unsized_ty,
2424 to_ty : to_sub_ty,
2525 } => 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 ,
2728 ReducedTy :: Ref ( to_sub_ty) => {
2829 from_ty = unsized_ty;
2930 to_ty = to_sub_ty;
@@ -48,7 +49,8 @@ pub(super) fn check<'tcx>(
4849 unsized_ty,
4950 from_ty : from_sub_ty,
5051 } => 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 ,
5254 ReducedTy :: Ref ( from_sub_ty) => {
5355 from_ty = from_sub_ty;
5456 to_ty = unsized_ty;
@@ -123,8 +125,7 @@ pub(super) fn check<'tcx>(
123125 from_ty : from_sub_ty,
124126 to_ty : to_sub_ty,
125127 } => 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 ,
128129 ( ReducedTy :: UnorderedFields ( from_ty) , ReducedTy :: UnorderedFields ( to_ty) ) if from_ty != to_ty => {
129130 span_lint_and_then (
130131 cx,
@@ -263,9 +264,6 @@ enum ReducedTy<'tcx> {
263264 UnorderedFields ( Ty < ' tcx > ) ,
264265 /// The type is a reference to the contained type.
265266 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 ,
269267 /// Any other type.
270268 Other ( Ty < ' tcx > ) ,
271269}
@@ -275,17 +273,18 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
275273 loop {
276274 ty = cx. tcx . try_normalize_erasing_regions ( cx. param_env , ty) . unwrap_or ( ty) ;
277275 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 ,
279277 ty:: Array ( sub_ty, _) | ty:: Slice ( sub_ty) => {
280278 ty = sub_ty;
281279 continue ;
282280 } ,
283281 ty:: Tuple ( args) if args. is_empty ( ) => ReducedTy :: TypeErasure ,
284282 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 {
286285 return ReducedTy :: OrderedFields ( ty) ;
287286 } ;
288- if args . iter ( ) . all ( |ty| is_zero_sized_ty ( cx, ty) ) {
287+ if iter. all ( |ty| is_zero_sized_ty ( cx, ty) ) {
289288 ty = sized_ty;
290289 continue ;
291290 }
@@ -313,6 +312,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
313312 ty:: Adt ( def, _) if def. is_enum ( ) && ( def. variants ( ) . is_empty ( ) || is_c_void ( cx, ty) ) => {
314313 ReducedTy :: TypeErasure
315314 } ,
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 ,
316317 ty:: Foreign ( _) => ReducedTy :: TypeErasure ,
317318 ty:: Ref ( _, ty, _) => ReducedTy :: Ref ( ty) ,
318319 ty:: RawPtr ( ty) => ReducedTy :: Ref ( ty. ty ) ,
@@ -332,3 +333,14 @@ fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
332333 }
333334 }
334335}
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