@@ -2,11 +2,11 @@ use std::iter::once;
22
33use clippy_utils:: diagnostics:: span_lint_and_sugg;
44use clippy_utils:: source:: snippet;
5+ use clippy_utils:: ty:: { ExprFnSig , expr_sig, ty_sig} ;
56use clippy_utils:: { get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core, sym} ;
67
78use rustc_errors:: Applicability ;
89use rustc_hir:: LangItem :: { OptionNone , OptionSome } ;
9- use rustc_hir:: def_id:: DefId ;
1010use rustc_hir:: hir_id:: HirId ;
1111use rustc_hir:: { Expr , ExprKind , Node } ;
1212use rustc_lint:: LateContext ;
@@ -32,24 +32,34 @@ impl IterType {
3232
3333fn is_arg_ty_unified_in_fn < ' tcx > (
3434 cx : & LateContext < ' tcx > ,
35- fn_id : DefId ,
35+ fn_sig : ExprFnSig < ' tcx > ,
3636 arg_id : HirId ,
3737 args : impl IntoIterator < Item = & ' tcx Expr < ' tcx > > ,
38+ is_method : bool ,
3839) -> bool {
39- let fn_sig = cx. tcx . fn_sig ( fn_id) . instantiate_identity ( ) ;
4040 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 ( ) ;
41+ let Some ( arg_ty_in_args) = fn_sig. input ( arg_id_in_args) . map ( |binder| binder. skip_binder ( ) ) else {
42+ return false ;
43+ } ;
4244
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) ) )
45+ fn_sig
46+ . predicates_id ( )
47+ . map ( |def_id| cx. tcx . predicates_of ( def_id) )
48+ . is_some_and ( |generics| {
49+ generics. predicates . iter ( ) . any ( |( clause, _) | {
50+ clause
51+ . as_projection_clause ( )
52+ . and_then ( |p| p. map_bound ( |p| p. term . as_type ( ) ) . transpose ( ) )
53+ . is_some_and ( |ty| ty. skip_binder ( ) == arg_ty_in_args)
54+ } )
55+ } )
56+ || ( !is_method
57+ && fn_sig. input ( arg_id_in_args) . is_some_and ( |binder| {
58+ binder
59+ . skip_binder ( )
60+ . walk ( )
61+ . any ( |arg| arg. as_type ( ) == Some ( arg_ty_in_args) )
62+ } ) )
5363}
5464
5565pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > , method_name : Symbol , recv : & ' tcx Expr < ' tcx > ) {
@@ -70,25 +80,16 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method
7080 let is_unified = match get_expr_use_or_unification_node ( cx. tcx , expr) {
7181 Some ( ( Node :: Expr ( parent) , child_id) ) => match parent. kind {
7282 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
83+ ExprKind :: Call ( recv, args) => {
84+ expr_sig ( cx, recv) . is_some_and ( |fn_sig| is_arg_ty_unified_in_fn ( cx, fn_sig, child_id, args, false ) )
85+ } ,
86+ ExprKind :: MethodCall ( _name, recv, args, _span) => cx
8187 . 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- ) ,
88+ . type_dependent_def_id ( parent. hir_id )
89+ . and_then ( |def_id| ty_sig ( cx, cx. tcx . type_of ( def_id) . instantiate_identity ( ) ) )
90+ . is_some_and ( |fn_sig| {
91+ is_arg_ty_unified_in_fn ( cx, fn_sig, child_id, once ( recv) . chain ( args. iter ( ) ) , true )
92+ } ) ,
9293 ExprKind :: If ( _, _, _)
9394 | ExprKind :: Match ( _, _, _)
9495 | ExprKind :: Closure ( _)
0 commit comments