@@ -3,6 +3,7 @@ use clippy_utils::path_res;
33use clippy_utils:: source:: snippet;
44use clippy_utils:: ty:: implements_trait;
55use rustc_errors:: Applicability ;
6+ use rustc_hir:: def:: { DefKind , Res } ;
67use rustc_hir:: { Expr , ExprKind , QPath } ;
78use rustc_lint:: { LateContext , LateLintPass } ;
89use rustc_middle:: ty:: { self , List , Ty } ;
@@ -39,59 +40,51 @@ declare_lint_pass!(NeedlessPathNew => [NEEDLESS_PATH_NEW]);
3940
4041impl < ' tcx > LateLintPass < ' tcx > for NeedlessPathNew {
4142 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) {
42- match e. kind {
43- ExprKind :: Call ( fn_expr, args) => {
44- check_arguments ( cx, & mut args. iter ( ) , cx. typeck_results ( ) . expr_ty ( fn_expr) ) ;
43+ let tcx = cx. tcx ;
44+
45+ let ( fn_did, arguments) = match e. kind {
46+ ExprKind :: Call ( callee, args)
47+ if let Res :: Def ( DefKind :: Fn | DefKind :: AssocFn , did) = path_res ( cx, callee) =>
48+ {
49+ ( did, args)
4550 } ,
46- ExprKind :: MethodCall ( _, _, arguments , _)
47- if let Some ( def_id ) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id ) =>
51+ ExprKind :: MethodCall ( _, _, args , _)
52+ if let Some ( did ) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id ) =>
4853 {
49- let args = cx. typeck_results ( ) . node_args ( e. hir_id ) ;
50- let method_type = cx. tcx . type_of ( def_id) . instantiate ( cx. tcx , args) ;
51- check_arguments ( cx, & mut arguments. iter ( ) , method_type) ;
54+ ( did, args)
5255 } ,
53- _ => ( ) ,
54- }
55- }
56- }
56+ _ => return ,
57+ } ;
5758
58- fn check_arguments < ' tcx > (
59- cx : & LateContext < ' tcx > ,
60- arguments : & mut dyn Iterator < Item = & ' tcx Expr < ' tcx > > ,
61- type_definition : Ty < ' tcx > ,
62- ) {
63- let tcx = cx. tcx ;
64- // whether `func` is `Path::new`
65- let is_path_new = |func : & Expr < ' _ > | {
66- if let ExprKind :: Path ( ref qpath) = func. kind
67- && let QPath :: TypeRelative ( ty, path) = qpath
68- && let Some ( did) = path_res ( cx, * ty) . opt_def_id ( )
69- && tcx. is_diagnostic_item ( sym:: Path , did)
70- && path. ident . name == sym:: new
71- {
72- true
73- } else {
74- false
75- }
76- } ;
59+ let sig = tcx. fn_sig ( fn_did) . skip_binder ( ) . skip_binder ( ) ;
7760
78- let path_ty = {
79- let Some ( path_def_id) = tcx. get_diagnostic_item ( sym:: Path ) else {
80- return ;
61+ // whether `func` is `Path::new`
62+ let is_path_new = |func : & Expr < ' _ > | {
63+ if let ExprKind :: Path ( ref qpath) = func. kind
64+ && let QPath :: TypeRelative ( ty, path) = qpath
65+ && let Some ( did) = path_res ( cx, * ty) . opt_def_id ( )
66+ && tcx. is_diagnostic_item ( sym:: Path , did)
67+ && path. ident . name == sym:: new
68+ {
69+ true
70+ } else {
71+ false
72+ }
8173 } ;
82- Ty :: new_adt ( tcx, tcx. adt_def ( path_def_id) , List :: empty ( ) )
83- } ;
8474
85- let Some ( asref_def_id) = tcx. get_diagnostic_item ( sym:: AsRef ) else {
86- return ;
87- } ;
75+ let path_ty = {
76+ let Some ( path_def_id) = tcx. get_diagnostic_item ( sym:: Path ) else {
77+ return ;
78+ } ;
79+ Ty :: new_adt ( tcx, tcx. adt_def ( path_def_id) , List :: empty ( ) )
80+ } ;
81+
82+ let Some ( asref_def_id) = tcx. get_diagnostic_item ( sym:: AsRef ) else {
83+ return ;
84+ } ;
8885
89- let implements_asref_path = |arg| implements_trait ( cx, arg, asref_def_id, & [ path_ty. into ( ) ] ) ;
86+ let implements_asref_path = |arg| implements_trait ( cx, arg, asref_def_id, & [ path_ty. into ( ) ] ) ;
9087
91- if let ty:: FnDef ( def_id, generic_args) = type_definition. kind ( )
92- // if there are any bound vars, just give up... we might be able to be smarter here
93- && let Some ( sig) = type_definition. sig ( tcx) . no_bound_vars ( )
94- {
9588 let parameters = sig. inputs ( ) ;
9689
9790 let _bounds = tcx. param_env ( def_id) . caller_bounds ( ) ;
0 commit comments