@@ -2,14 +2,15 @@ use std::iter::once;
2
2
3
3
use clippy_utils:: diagnostics:: span_lint_and_sugg;
4
4
use clippy_utils:: source:: snippet;
5
+ use clippy_utils:: ty:: { ExprFnSig , expr_sig, ty_sig} ;
5
6
use clippy_utils:: { get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core, sym} ;
6
7
7
8
use rustc_errors:: Applicability ;
8
9
use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
9
- use rustc_hir:: def_id:: DefId ;
10
10
use rustc_hir:: hir_id:: HirId ;
11
11
use rustc_hir:: { Expr , ExprKind , Node } ;
12
12
use rustc_lint:: LateContext ;
13
+ use rustc_middle:: ty:: Binder ;
13
14
use rustc_span:: Symbol ;
14
15
15
16
use super :: { ITER_ON_EMPTY_COLLECTIONS , ITER_ON_SINGLE_ITEMS } ;
@@ -32,24 +33,34 @@ impl IterType {
32
33
33
34
fn is_arg_ty_unified_in_fn < ' tcx > (
34
35
cx : & LateContext < ' tcx > ,
35
- fn_id : DefId ,
36
+ fn_sig : ExprFnSig < ' tcx > ,
36
37
arg_id : HirId ,
37
38
args : impl IntoIterator < Item = & ' tcx Expr < ' tcx > > ,
39
+ is_method : bool ,
38
40
) -> bool {
39
- let fn_sig = cx. tcx . fn_sig ( fn_id) . instantiate_identity ( ) ;
40
41
let arg_id_in_args = args. into_iter ( ) . position ( |e| e. hir_id == arg_id) . unwrap ( ) ;
41
- let arg_ty_in_args = fn_sig. input ( arg_id_in_args) . skip_binder ( ) ;
42
+ let Some ( arg_ty_in_args) = fn_sig. input ( arg_id_in_args) . map ( Binder :: skip_binder) else {
43
+ return false ;
44
+ } ;
42
45
43
- cx. tcx . predicates_of ( fn_id) . predicates . iter ( ) . any ( |( clause, _) | {
44
- clause
45
- . as_projection_clause ( )
46
- . and_then ( |p| p. map_bound ( |p| p. term . as_type ( ) ) . transpose ( ) )
47
- . is_some_and ( |ty| ty. skip_binder ( ) == arg_ty_in_args)
48
- } ) || fn_sig
49
- . inputs ( )
50
- . iter ( )
51
- . enumerate ( )
52
- . any ( |( i, ty) | i != arg_id_in_args && ty. skip_binder ( ) . walk ( ) . any ( |arg| arg. as_type ( ) == Some ( arg_ty_in_args) ) )
46
+ fn_sig
47
+ . predicates_id ( )
48
+ . map ( |def_id| cx. tcx . predicates_of ( def_id) )
49
+ . is_some_and ( |generics| {
50
+ generics. predicates . iter ( ) . any ( |( clause, _) | {
51
+ clause
52
+ . as_projection_clause ( )
53
+ . and_then ( |p| p. map_bound ( |p| p. term . as_type ( ) ) . transpose ( ) )
54
+ . is_some_and ( |ty| ty. skip_binder ( ) == arg_ty_in_args)
55
+ } )
56
+ } )
57
+ || ( !is_method
58
+ && fn_sig. input ( arg_id_in_args) . is_some_and ( |binder| {
59
+ binder
60
+ . skip_binder ( )
61
+ . walk ( )
62
+ . any ( |arg| arg. as_type ( ) == Some ( arg_ty_in_args) )
63
+ } ) )
53
64
}
54
65
55
66
pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > , method_name : Symbol , recv : & ' tcx Expr < ' tcx > ) {
@@ -70,33 +81,25 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method
70
81
let is_unified = match get_expr_use_or_unification_node ( cx. tcx , expr) {
71
82
Some ( ( Node :: Expr ( parent) , child_id) ) => match parent. kind {
72
83
ExprKind :: If ( e, _, _) | ExprKind :: Match ( e, _, _) if e. hir_id == child_id => false ,
73
- ExprKind :: Call (
74
- Expr {
75
- kind : ExprKind :: Path ( path) ,
76
- hir_id,
77
- ..
78
- } ,
79
- args,
80
- ) => cx
84
+ ExprKind :: Call ( recv, args) => {
85
+ expr_sig ( cx, recv) . is_some_and ( |fn_sig| is_arg_ty_unified_in_fn ( cx, fn_sig, child_id, args, false ) )
86
+ } ,
87
+ ExprKind :: MethodCall ( _name, recv, args, _span) => cx
81
88
. typeck_results ( )
82
- . qpath_res ( path, * hir_id)
83
- . opt_def_id ( )
84
- . filter ( |fn_id| cx. tcx . def_kind ( fn_id) . is_fn_like ( ) )
85
- . is_some_and ( |fn_id| is_arg_ty_unified_in_fn ( cx, fn_id, child_id, args) ) ,
86
- ExprKind :: MethodCall ( _name, recv, args, _span) => is_arg_ty_unified_in_fn (
87
- cx,
88
- cx. typeck_results ( ) . type_dependent_def_id ( parent. hir_id ) . unwrap ( ) ,
89
- child_id,
90
- once ( recv) . chain ( args. iter ( ) ) ,
91
- ) ,
89
+ . type_dependent_def_id ( parent. hir_id )
90
+ . and_then ( |def_id| ty_sig ( cx, cx. tcx . type_of ( def_id) . instantiate_identity ( ) ) )
91
+ . is_some_and ( |fn_sig| {
92
+ is_arg_ty_unified_in_fn ( cx, fn_sig, child_id, once ( recv) . chain ( args. iter ( ) ) , true )
93
+ } ) ,
92
94
ExprKind :: If ( _, _, _)
93
95
| ExprKind :: Match ( _, _, _)
94
96
| ExprKind :: Closure ( _)
95
97
| ExprKind :: Ret ( _)
96
98
| ExprKind :: Break ( _, _) => true ,
97
99
_ => false ,
98
100
} ,
99
- Some ( ( Node :: Stmt ( _) | Node :: LetStmt ( _) , _) ) => false ,
101
+ Some ( ( Node :: LetStmt ( let_stmt) , _) ) => let_stmt. ty . is_some ( ) ,
102
+ Some ( ( Node :: Stmt ( _) , _) ) => false ,
100
103
_ => true ,
101
104
} ;
102
105
0 commit comments