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} ;
22use 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 } ;
45use rustc_lint:: { LateContext , LateLintPass } ;
56use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
67
@@ -45,11 +46,15 @@ declare_clippy_lint! {
4546#[ derive( Default ) ]
4647pub struct ToStringInDisplay {
4748 in_display_impl : bool ,
49+ self_hir_id : Option < HirId > ,
4850}
4951
5052impl ToStringInDisplay {
5153 pub fn new ( ) -> Self {
52- Self { in_display_impl : false }
54+ Self {
55+ in_display_impl : false ,
56+ self_hir_id : None ,
57+ }
5358 }
5459}
5560
@@ -65,16 +70,33 @@ impl LateLintPass<'_> for ToStringInDisplay {
6570 fn check_item_post ( & mut self , cx : & LateContext < ' _ > , item : & Item < ' _ > ) {
6671 if is_display_impl ( cx, item) {
6772 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+ }
6887 }
6988 }
7089
7190 fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
7291 if_chain ! {
73- if let ExprKind :: MethodCall ( ref path, _, _ , _) = expr. kind;
92+ if let ExprKind :: MethodCall ( ref path, _, args , _) = expr. kind;
7493 if path. ident. name == sym!( to_string) ;
7594 if match_trait_method( cx, expr, & paths:: TO_STRING ) ;
7695 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;
78100 then {
79101 span_lint(
80102 cx,
0 commit comments