@@ -2,14 +2,15 @@ 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 ;
13+ use rustc_middle:: ty:: Binder ;
1314use rustc_span:: Symbol ;
1415
1516use super :: { ITER_ON_EMPTY_COLLECTIONS , ITER_ON_SINGLE_ITEMS } ;
@@ -32,24 +33,34 @@ impl IterType {
3233
3334fn is_arg_ty_unified_in_fn < ' tcx > (
3435 cx : & LateContext < ' tcx > ,
35- fn_id : DefId ,
36+ fn_sig : ExprFnSig < ' tcx > ,
3637 arg_id : HirId ,
3738 args : impl IntoIterator < Item = & ' tcx Expr < ' tcx > > ,
39+ is_method : bool ,
3840) -> bool {
39- let fn_sig = cx. tcx . fn_sig ( fn_id) . instantiate_identity ( ) ;
4041 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+ } ;
4245
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+ } ) )
5364}
5465
5566pub ( 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
7081 let is_unified = match get_expr_use_or_unification_node ( cx. tcx , expr) {
7182 Some ( ( Node :: Expr ( parent) , child_id) ) => match parent. kind {
7283 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
8188 . 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+ } ) ,
9294 ExprKind :: If ( _, _, _)
9395 | ExprKind :: Match ( _, _, _)
9496 | ExprKind :: Closure ( _)
9597 | ExprKind :: Ret ( _)
9698 | ExprKind :: Break ( _, _) => true ,
9799 _ => false ,
98100 } ,
99- Some ( ( Node :: Stmt ( _) | Node :: LetStmt ( _) , _) ) => false ,
101+ Some ( ( Node :: LetStmt ( let_stmt) , _) ) => let_stmt. ty . is_some ( ) ,
102+ Some ( ( Node :: Stmt ( _) , _) ) => false ,
100103 _ => true ,
101104 } ;
102105
0 commit comments