@@ -3,6 +3,7 @@ use clippy_utils::path_res;
3
3
use clippy_utils:: source:: snippet;
4
4
use clippy_utils:: ty:: implements_trait;
5
5
use rustc_errors:: Applicability ;
6
+ use rustc_hir:: def:: { DefKind , Res } ;
6
7
use rustc_hir:: { Expr , ExprKind , QPath } ;
7
8
use rustc_lint:: { LateContext , LateLintPass } ;
8
9
use rustc_middle:: ty:: { self , List , Ty } ;
@@ -39,59 +40,51 @@ declare_lint_pass!(NeedlessPathNew => [NEEDLESS_PATH_NEW]);
39
40
40
41
impl < ' tcx > LateLintPass < ' tcx > for NeedlessPathNew {
41
42
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)
45
50
} ,
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 ) =>
48
53
{
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)
52
55
} ,
53
- _ => ( ) ,
54
- }
55
- }
56
- }
56
+ _ => return ,
57
+ } ;
57
58
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 ( ) ;
77
60
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
+ }
81
73
} ;
82
- Ty :: new_adt ( tcx, tcx. adt_def ( path_def_id) , List :: empty ( ) )
83
- } ;
84
74
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
+ } ;
88
85
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 ( ) ] ) ;
90
87
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
- {
95
88
let parameters = sig. inputs ( ) ;
96
89
97
90
let _bounds = tcx. param_env ( def_id) . caller_bounds ( ) ;
0 commit comments