11use  clippy_utils:: diagnostics:: span_lint_and_help; 
22use  clippy_utils:: { is_bool,  sym} ; 
33use  rustc_abi:: ExternAbi ; 
4- use  rustc_hir as  hir; 
5- use  rustc_hir:: { FnSig ,  ImplItem } ; 
4+ use  rustc_hir:: { self  as  hir,  FnRetTy ,  FnSig ,  GenericParamKind ,  ImplItem ,  LifetimeParamKind } ; 
65use  rustc_lint:: LateContext ; 
76use  rustc_middle:: ty:: Ty ; 
87use  rustc_span:: edition:: Edition :: { self ,  Edition2015 ,  Edition2021 } ; 
@@ -20,51 +19,43 @@ pub(super) fn check_impl_item<'tcx>(
2019    sig :  & FnSig < ' _ > , 
2120)  { 
2221    // if this impl block implements a trait, lint in trait definition instead 
23-     if  !impl_implements_trait && cx. effective_visibilities . is_exported ( impl_item. owner_id . def_id )   { 
22+     if  !impl_implements_trait && cx. effective_visibilities . is_exported ( impl_item. owner_id . def_id ) 
2423        // check missing trait implementations 
25-         for   method_config  in   & TRAIT_METHODS   { 
26-              if  impl_item . ident . name  == method_config. method_name 
27-                  && sig. decl . inputs . len ( )  == method_config . param_count 
28-                 && method_config . output_type . matches ( & sig . decl . output ) 
29-                  // in case there is no first arg, since we already have checked the number of arguments  
30-                  // it's should be always true 
31-                 && first_arg_ty_opt 
32-                      . is_none_or ( |first_arg_ty| method_config . self_kind . matches ( cx ,  self_ty ,  first_arg_ty ) ) 
33-                  && fn_header_equals ( method_config . fn_header ,   sig. header ) 
34-                  && method_config . lifetime_param_cond ( impl_item ) 
35-                  && method_config . in_prelude_since  <= cx . tcx . sess . edition ( ) 
36-              { 
37-                  span_lint_and_help ( 
38-                     cx , 
39-                      SHOULD_IMPLEMENT_TRAIT , 
40-                     impl_item . span , 
41-                      format ! ( 
42-                          "method `{}` can be confused for the standard trait method `{}::{}`" , 
43-                         method_config . method_name ,  method_config . trait_name ,  method_config . method_name 
44-                      ) , 
45-                      None , 
46-                      format ! ( 
47-                          "consider implementing the trait `{}` or choosing a less ambiguous method name" , 
48-                         method_config . trait_name 
49-                      ) , 
50-                 ) ; 
51-             } 
52-         } 
24+         &&  let   Some ( method_config)  =  TRAIT_METHODS . iter ( ) . find ( |case| case . method_name  == impl_item . ident . name ) 
25+         && sig . decl . inputs . len ( )  == method_config. param_count 
26+         && method_config . output_type . matches ( & sig. decl . output ) 
27+         // in case there is no first arg, since we already have checked the number of arguments 
28+         // it's should be always true  
29+         && first_arg_ty_opt 
30+             . is_none_or ( |first_arg_ty| method_config . self_kind . matches ( cx ,  self_ty ,  first_arg_ty ) ) 
31+         && sig . header . is_safe ( ) 
32+         && ! sig. header . is_const ( ) 
33+         && !sig . header . is_async ( ) 
34+         && sig . header . abi  ==  ExternAbi :: Rust 
35+         && method_config . lifetime_param_cond ( impl_item ) 
36+         && method_config . in_prelude_since  <= cx . tcx . sess . edition ( ) 
37+     { 
38+         span_lint_and_help ( 
39+             cx , 
40+             SHOULD_IMPLEMENT_TRAIT , 
41+             impl_item . span , 
42+             format ! ( 
43+                 "method `{}` can be confused for the standard trait method `{}::{}`" , 
44+                 method_config . method_name ,  method_config . trait_name ,  method_config . method_name 
45+             ) , 
46+             None , 
47+             format ! ( 
48+                 "consider implementing the trait `{}` or choosing a less ambiguous method name" , 
49+                 method_config . trait_name 
50+             ) , 
51+         ) ; 
5352    } 
5453} 
5554
56- const  FN_HEADER :  hir:: FnHeader  = hir:: FnHeader  { 
57-     safety :  hir:: HeaderSafety :: Normal ( hir:: Safety :: Safe ) , 
58-     constness :  hir:: Constness :: NotConst , 
59-     asyncness :  hir:: IsAsync :: NotAsync , 
60-     abi :  ExternAbi :: Rust , 
61- } ; 
62- 
6355struct  ShouldImplTraitCase  { 
6456    trait_name :  & ' static  str , 
6557    method_name :  Symbol , 
6658    param_count :  usize , 
67-     fn_header :  hir:: FnHeader , 
6859    // implicit self kind expected (none, self, &self, ...) 
6960    self_kind :  SelfKind , 
7061    // checks against the output type 
@@ -73,13 +64,12 @@ struct ShouldImplTraitCase {
7364    lint_explicit_lifetime :  bool , 
7465    in_prelude_since :  Edition , 
7566} 
67+ 
7668impl  ShouldImplTraitCase  { 
77-     #[ expect( clippy:: too_many_arguments) ]  
7869    const  fn  new ( 
7970        trait_name :  & ' static  str , 
8071        method_name :  Symbol , 
8172        param_count :  usize , 
82-         fn_header :  hir:: FnHeader , 
8373        self_kind :  SelfKind , 
8474        output_type :  OutType , 
8575        lint_explicit_lifetime :  bool , 
@@ -89,7 +79,6 @@ impl ShouldImplTraitCase {
8979            trait_name, 
9080            method_name, 
9181            param_count, 
92-             fn_header, 
9382            self_kind, 
9483            output_type, 
9584            lint_explicit_lifetime, 
@@ -102,8 +91,8 @@ impl ShouldImplTraitCase {
10291            || !impl_item. generics . params . iter ( ) . any ( |p| { 
10392                matches ! ( 
10493                    p. kind, 
105-                     hir :: GenericParamKind :: Lifetime  { 
106-                         kind:  hir :: LifetimeParamKind :: Explicit 
94+                     GenericParamKind :: Lifetime  { 
95+                         kind:  LifetimeParamKind :: Explicit 
10796                    } 
10897                ) 
10998            } ) 
@@ -112,36 +101,36 @@ impl ShouldImplTraitCase {
112101
113102#[ rustfmt:: skip]  
114103const  TRAIT_METHODS :  [ ShouldImplTraitCase ;  30 ]  = [ 
115-     ShouldImplTraitCase :: new ( "std::ops::Add" ,            sym:: add,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
116-     ShouldImplTraitCase :: new ( "std::convert::AsMut" ,      sym:: as_mut,      1 ,   FN_HEADER ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
117-     ShouldImplTraitCase :: new ( "std::convert::AsRef" ,      sym:: as_ref,      1 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
118-     ShouldImplTraitCase :: new ( "std::ops::BitAnd" ,         sym:: bitand,      2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
119-     ShouldImplTraitCase :: new ( "std::ops::BitOr" ,          sym:: bitor,       2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
120-     ShouldImplTraitCase :: new ( "std::ops::BitXor" ,         sym:: bitxor,      2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
121-     ShouldImplTraitCase :: new ( "std::borrow::Borrow" ,      sym:: borrow,      1 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
122-     ShouldImplTraitCase :: new ( "std::borrow::BorrowMut" ,   sym:: borrow_mut,  1 ,   FN_HEADER ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
123-     ShouldImplTraitCase :: new ( "std::clone::Clone" ,        sym:: clone,       1 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Any ,   true ,   Edition2015 ) , 
124-     ShouldImplTraitCase :: new ( "std::cmp::Ord" ,            sym:: cmp,         2 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Any ,   true ,   Edition2015 ) , 
125-     ShouldImplTraitCase :: new ( "std::default::Default" ,    kw:: Default ,      0 ,   FN_HEADER ,   SelfKind :: No ,      OutType :: Any ,   true ,   Edition2015 ) , 
126-     ShouldImplTraitCase :: new ( "std::ops::Deref" ,          sym:: deref,       1 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
127-     ShouldImplTraitCase :: new ( "std::ops::DerefMut" ,       sym:: deref_mut,   1 ,   FN_HEADER ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
128-     ShouldImplTraitCase :: new ( "std::ops::Div" ,            sym:: div,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
129-     ShouldImplTraitCase :: new ( "std::ops::Drop" ,           sym:: drop,        1 ,   FN_HEADER ,   SelfKind :: RefMut ,  OutType :: Unit ,  true ,   Edition2015 ) , 
130-     ShouldImplTraitCase :: new ( "std::cmp::PartialEq" ,      sym:: eq,          2 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Bool ,  true ,   Edition2015 ) , 
131-     ShouldImplTraitCase :: new ( "std::iter::FromIterator" ,  sym:: from_iter,   1 ,   FN_HEADER ,   SelfKind :: No ,      OutType :: Any ,   true ,   Edition2021 ) , 
132-     ShouldImplTraitCase :: new ( "std::str::FromStr" ,        sym:: from_str,    1 ,   FN_HEADER ,   SelfKind :: No ,      OutType :: Any ,   true ,   Edition2015 ) , 
133-     ShouldImplTraitCase :: new ( "std::hash::Hash" ,          sym:: hash,        2 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Unit ,  true ,   Edition2015 ) , 
134-     ShouldImplTraitCase :: new ( "std::ops::Index" ,          sym:: index,       2 ,   FN_HEADER ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
135-     ShouldImplTraitCase :: new ( "std::ops::IndexMut" ,       sym:: index_mut,   2 ,   FN_HEADER ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
136-     ShouldImplTraitCase :: new ( "std::iter::IntoIterator" ,  sym:: into_iter,   1 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
137-     ShouldImplTraitCase :: new ( "std::ops::Mul" ,            sym:: mul,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
138-     ShouldImplTraitCase :: new ( "std::ops::Neg" ,            sym:: neg,         1 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
139-     ShouldImplTraitCase :: new ( "std::iter::Iterator" ,      sym:: next,        1 ,   FN_HEADER ,   SelfKind :: RefMut ,  OutType :: Any ,   false ,  Edition2015 ) , 
140-     ShouldImplTraitCase :: new ( "std::ops::Not" ,            sym:: not,         1 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
141-     ShouldImplTraitCase :: new ( "std::ops::Rem" ,            sym:: rem,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
142-     ShouldImplTraitCase :: new ( "std::ops::Shl" ,            sym:: shl,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
143-     ShouldImplTraitCase :: new ( "std::ops::Shr" ,            sym:: shr,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
144-     ShouldImplTraitCase :: new ( "std::ops::Sub" ,            sym:: sub,         2 ,   FN_HEADER ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
104+     ShouldImplTraitCase :: new ( "std::ops::Add" ,            sym:: add,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
105+     ShouldImplTraitCase :: new ( "std::convert::AsMut" ,      sym:: as_mut,      1 ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
106+     ShouldImplTraitCase :: new ( "std::convert::AsRef" ,      sym:: as_ref,      1 ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
107+     ShouldImplTraitCase :: new ( "std::ops::BitAnd" ,         sym:: bitand,      2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
108+     ShouldImplTraitCase :: new ( "std::ops::BitOr" ,          sym:: bitor,       2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
109+     ShouldImplTraitCase :: new ( "std::ops::BitXor" ,         sym:: bitxor,      2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
110+     ShouldImplTraitCase :: new ( "std::borrow::Borrow" ,      sym:: borrow,      1 ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
111+     ShouldImplTraitCase :: new ( "std::borrow::BorrowMut" ,   sym:: borrow_mut,  1 ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
112+     ShouldImplTraitCase :: new ( "std::clone::Clone" ,        sym:: clone,       1 ,   SelfKind :: Ref ,     OutType :: Any ,   true ,   Edition2015 ) , 
113+     ShouldImplTraitCase :: new ( "std::cmp::Ord" ,            sym:: cmp,         2 ,   SelfKind :: Ref ,     OutType :: Any ,   true ,   Edition2015 ) , 
114+     ShouldImplTraitCase :: new ( "std::default::Default" ,    kw:: Default ,      0 ,   SelfKind :: No ,      OutType :: Any ,   true ,   Edition2015 ) , 
115+     ShouldImplTraitCase :: new ( "std::ops::Deref" ,          sym:: deref,       1 ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
116+     ShouldImplTraitCase :: new ( "std::ops::DerefMut" ,       sym:: deref_mut,   1 ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
117+     ShouldImplTraitCase :: new ( "std::ops::Div" ,            sym:: div,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
118+     ShouldImplTraitCase :: new ( "std::ops::Drop" ,           sym:: drop,        1 ,   SelfKind :: RefMut ,  OutType :: Unit ,  true ,   Edition2015 ) , 
119+     ShouldImplTraitCase :: new ( "std::cmp::PartialEq" ,      sym:: eq,          2 ,   SelfKind :: Ref ,     OutType :: Bool ,  true ,   Edition2015 ) , 
120+     ShouldImplTraitCase :: new ( "std::iter::FromIterator" ,  sym:: from_iter,   1 ,   SelfKind :: No ,      OutType :: Any ,   true ,   Edition2021 ) , 
121+     ShouldImplTraitCase :: new ( "std::str::FromStr" ,        sym:: from_str,    1 ,   SelfKind :: No ,      OutType :: Any ,   true ,   Edition2015 ) , 
122+     ShouldImplTraitCase :: new ( "std::hash::Hash" ,          sym:: hash,        2 ,   SelfKind :: Ref ,     OutType :: Unit ,  true ,   Edition2015 ) , 
123+     ShouldImplTraitCase :: new ( "std::ops::Index" ,          sym:: index,       2 ,   SelfKind :: Ref ,     OutType :: Ref ,   true ,   Edition2015 ) , 
124+     ShouldImplTraitCase :: new ( "std::ops::IndexMut" ,       sym:: index_mut,   2 ,   SelfKind :: RefMut ,  OutType :: Ref ,   true ,   Edition2015 ) , 
125+     ShouldImplTraitCase :: new ( "std::iter::IntoIterator" ,  sym:: into_iter,   1 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
126+     ShouldImplTraitCase :: new ( "std::ops::Mul" ,            sym:: mul,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
127+     ShouldImplTraitCase :: new ( "std::ops::Neg" ,            sym:: neg,         1 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
128+     ShouldImplTraitCase :: new ( "std::iter::Iterator" ,      sym:: next,        1 ,   SelfKind :: RefMut ,  OutType :: Any ,   false ,  Edition2015 ) , 
129+     ShouldImplTraitCase :: new ( "std::ops::Not" ,            sym:: not,         1 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
130+     ShouldImplTraitCase :: new ( "std::ops::Rem" ,            sym:: rem,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
131+     ShouldImplTraitCase :: new ( "std::ops::Shl" ,            sym:: shl,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
132+     ShouldImplTraitCase :: new ( "std::ops::Shr" ,            sym:: shr,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
133+     ShouldImplTraitCase :: new ( "std::ops::Sub" ,            sym:: sub,         2 ,   SelfKind :: Value ,   OutType :: Any ,   true ,   Edition2015 ) , 
145134] ; 
146135
147136#[ derive( Clone ,  Copy ) ]  
@@ -153,19 +142,15 @@ enum OutType {
153142} 
154143
155144impl  OutType  { 
156-     fn  matches ( self ,  ty :  & hir :: FnRetTy < ' _ > )  -> bool  { 
145+     fn  matches ( self ,  ty :  & FnRetTy < ' _ > )  -> bool  { 
157146        let  is_unit = |ty :  & hir:: Ty < ' _ > | matches ! ( ty. kind,  hir:: TyKind :: Tup ( & [ ] ) ) ; 
158147        match  ( self ,  ty)  { 
159-             ( Self :: Unit ,  & hir :: FnRetTy :: DefaultReturn ( _) )  => true , 
160-             ( Self :: Unit ,  & hir :: FnRetTy :: Return ( ty) )  if  is_unit ( ty)  => true , 
161-             ( Self :: Bool ,  & hir :: FnRetTy :: Return ( ty) )  if  is_bool ( ty)  => true , 
162-             ( Self :: Any ,  & hir :: FnRetTy :: Return ( ty) )  if  !is_unit ( ty)  => true , 
163-             ( Self :: Ref ,  & hir :: FnRetTy :: Return ( ty) )  => matches ! ( ty. kind,  hir:: TyKind :: Ref ( _,  _) ) , 
148+             ( Self :: Unit ,  & FnRetTy :: DefaultReturn ( _) )  => true , 
149+             ( Self :: Unit ,  & FnRetTy :: Return ( ty) )  if  is_unit ( ty)  => true , 
150+             ( Self :: Bool ,  & FnRetTy :: Return ( ty) )  if  is_bool ( ty)  => true , 
151+             ( Self :: Any ,  & FnRetTy :: Return ( ty) )  if  !is_unit ( ty)  => true , 
152+             ( Self :: Ref ,  & FnRetTy :: Return ( ty) )  => matches ! ( ty. kind,  hir:: TyKind :: Ref ( _,  _) ) , 
164153            _ => false , 
165154        } 
166155    } 
167156} 
168- 
169- fn  fn_header_equals ( expected :  hir:: FnHeader ,  actual :  hir:: FnHeader )  -> bool  { 
170-     expected. constness  == actual. constness  && expected. safety  == actual. safety  && expected. asyncness  == actual. asyncness 
171- } 
0 commit comments