1
- use crate :: utils:: { match_def_path, match_trait_method, paths, span_lint} ;
1
+ use crate :: utils:: { match_def_path, match_trait_method, paths, qpath_res , span_lint} ;
2
2
use if_chain:: if_chain;
3
- use rustc_hir:: { Expr , ExprKind , Item , ItemKind } ;
3
+ use rustc_hir:: def:: Res ;
4
+ use rustc_hir:: { Expr , ExprKind , HirId , ImplItem , ImplItemKind , Item , ItemKind } ;
4
5
use rustc_lint:: { LateContext , LateLintPass } ;
5
6
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
6
7
@@ -45,11 +46,15 @@ declare_clippy_lint! {
45
46
#[ derive( Default ) ]
46
47
pub struct ToStringInDisplay {
47
48
in_display_impl : bool ,
49
+ self_hir_id : Option < HirId > ,
48
50
}
49
51
50
52
impl ToStringInDisplay {
51
53
pub fn new ( ) -> Self {
52
- Self { in_display_impl : false }
54
+ Self {
55
+ in_display_impl : false ,
56
+ self_hir_id : None ,
57
+ }
53
58
}
54
59
}
55
60
@@ -65,16 +70,33 @@ impl LateLintPass<'_> for ToStringInDisplay {
65
70
fn check_item_post ( & mut self , cx : & LateContext < ' _ > , item : & Item < ' _ > ) {
66
71
if is_display_impl ( cx, item) {
67
72
self . in_display_impl = false ;
73
+ self . self_hir_id = None ;
74
+ }
75
+ }
76
+
77
+ fn check_impl_item ( & mut self , cx : & LateContext < ' _ > , impl_item : & ImplItem < ' _ > ) {
78
+ if_chain ! {
79
+ if self . in_display_impl;
80
+ if let ImplItemKind :: Fn ( .., body_id) = & impl_item. kind;
81
+ let body = cx. tcx. hir( ) . body( * body_id) ;
82
+ if !body. params. is_empty( ) ;
83
+ then {
84
+ let self_param = & body. params[ 0 ] ;
85
+ self . self_hir_id = Some ( self_param. pat. hir_id) ;
86
+ }
68
87
}
69
88
}
70
89
71
90
fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
72
91
if_chain ! {
73
- if let ExprKind :: MethodCall ( ref path, _, _ , _) = expr. kind;
92
+ if let ExprKind :: MethodCall ( ref path, _, args , _) = expr. kind;
74
93
if path. ident. name == sym!( to_string) ;
75
94
if match_trait_method( cx, expr, & paths:: TO_STRING ) ;
76
95
if self . in_display_impl;
77
-
96
+ if let ExprKind :: Path ( ref qpath) = args[ 0 ] . kind;
97
+ if let Res :: Local ( hir_id) = qpath_res( cx, qpath, args[ 0 ] . hir_id) ;
98
+ if let Some ( self_hir_id) = self . self_hir_id;
99
+ if hir_id == self_hir_id;
78
100
then {
79
101
span_lint(
80
102
cx,
0 commit comments