1
+ use std:: iter:: once;
2
+
1
3
use clippy_utils:: diagnostics:: span_lint_and_sugg;
2
4
use clippy_utils:: source:: snippet;
3
5
use clippy_utils:: { get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core} ;
4
6
5
7
use rustc_errors:: Applicability ;
8
+ use rustc_hir:: def_id:: DefId ;
9
+ use rustc_hir:: hir_id:: HirId ;
6
10
use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
7
11
use rustc_hir:: { Expr , ExprKind , Node } ;
8
12
use rustc_lint:: LateContext ;
@@ -25,7 +29,29 @@ impl IterType {
25
29
}
26
30
}
27
31
28
- pub ( super ) fn check ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , method_name : & str , recv : & Expr < ' _ > ) {
32
+ fn is_arg_ty_unified_in_fn < ' tcx > (
33
+ cx : & LateContext < ' tcx > ,
34
+ fn_id : DefId ,
35
+ arg_id : HirId ,
36
+ args : impl IntoIterator < Item = & ' tcx Expr < ' tcx > > ,
37
+ ) -> bool {
38
+ let fn_sig = cx. tcx . fn_sig ( fn_id) . instantiate_identity ( ) ;
39
+ let arg_id_in_args = args. into_iter ( ) . position ( |e| e. hir_id == arg_id) . unwrap ( ) ;
40
+ let arg_ty_in_args = fn_sig. input ( arg_id_in_args) . skip_binder ( ) ;
41
+
42
+ cx. tcx . predicates_of ( fn_id) . predicates . iter ( ) . any ( |( clause, _) | {
43
+ clause
44
+ . as_projection_clause ( )
45
+ . and_then ( |p| p. map_bound ( |p| p. term . ty ( ) ) . transpose ( ) )
46
+ . is_some_and ( |ty| ty. skip_binder ( ) == arg_ty_in_args)
47
+ } ) || fn_sig
48
+ . inputs ( )
49
+ . iter ( )
50
+ . enumerate ( )
51
+ . any ( |( i, ty) | i != arg_id_in_args && ty. skip_binder ( ) . walk ( ) . any ( |arg| arg. as_type ( ) == Some ( arg_ty_in_args) ) )
52
+ }
53
+
54
+ pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > , method_name : & str , recv : & ' tcx Expr < ' tcx > ) {
29
55
let item = match recv. kind {
30
56
ExprKind :: Array ( [ ] ) => None ,
31
57
ExprKind :: Array ( [ e] ) => Some ( e) ,
@@ -43,6 +69,25 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re
43
69
let is_unified = match get_expr_use_or_unification_node ( cx. tcx , expr) {
44
70
Some ( ( Node :: Expr ( parent) , child_id) ) => match parent. kind {
45
71
ExprKind :: If ( e, _, _) | ExprKind :: Match ( e, _, _) if e. hir_id == child_id => false ,
72
+ ExprKind :: Call (
73
+ Expr {
74
+ kind : ExprKind :: Path ( path) ,
75
+ hir_id,
76
+ ..
77
+ } ,
78
+ args,
79
+ ) => cx
80
+ . typeck_results ( )
81
+ . qpath_res ( path, * hir_id)
82
+ . opt_def_id ( )
83
+ . filter ( |fn_id| cx. tcx . def_kind ( fn_id) . is_fn_like ( ) )
84
+ . is_some_and ( |fn_id| is_arg_ty_unified_in_fn ( cx, fn_id, child_id, args) ) ,
85
+ ExprKind :: MethodCall ( _name, recv, args, _span) => is_arg_ty_unified_in_fn (
86
+ cx,
87
+ cx. typeck_results ( ) . type_dependent_def_id ( parent. hir_id ) . unwrap ( ) ,
88
+ child_id,
89
+ once ( recv) . chain ( args. iter ( ) ) ,
90
+ ) ,
46
91
ExprKind :: If ( _, _, _)
47
92
| ExprKind :: Match ( _, _, _)
48
93
| ExprKind :: Closure ( _)
0 commit comments