@@ -22,6 +22,7 @@ use rustc_semver::RustcVersion;
2222use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
2323use rustc_span:: source_map:: Span ;
2424use rustc_span:: symbol:: { sym, SymbolStr } ;
25+ use rustc_typeck:: hir_ty_to_ty;
2526
2627use crate :: consts:: { constant, Constant } ;
2728use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
@@ -1623,10 +1624,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16231624 let item = cx. tcx . hir ( ) . expect_item ( parent) ;
16241625 let def_id = cx. tcx . hir ( ) . local_def_id ( item. hir_id ) ;
16251626 let self_ty = cx. tcx . type_of ( def_id) ;
1627+
1628+ // if this impl block implements a trait, lint in trait definition instead
1629+ if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = item. kind {
1630+ return ;
1631+ }
1632+
16261633 if_chain ! {
16271634 if let hir:: ImplItemKind :: Fn ( ref sig, id) = impl_item. kind;
16281635 if let Some ( first_arg) = iter_input_pats( & sig. decl, cx. tcx. hir( ) . body( id) ) . next( ) ;
1629- if let hir:: ItemKind :: Impl { of_trait: None , .. } = item. kind;
16301636
16311637 let method_def_id = cx. tcx. hir( ) . local_def_id( impl_item. hir_id) ;
16321638 let method_sig = cx. tcx. fn_sig( method_def_id) ;
@@ -1697,11 +1703,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16971703 }
16981704 }
16991705
1700- // if this impl block implements a trait, lint in trait definition instead
1701- if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = item. kind {
1702- return ;
1703- }
1704-
17051706 if let hir:: ImplItemKind :: Fn ( _, _) = impl_item. kind {
17061707 let ret_ty = return_ty ( cx, impl_item. hir_id ) ;
17071708
@@ -1735,8 +1736,42 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
17351736 }
17361737
17371738 fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx TraitItem < ' _ > ) {
1739+ if in_external_macro ( cx. tcx . sess , item. span ) {
1740+ return ;
1741+ }
1742+
1743+ if_chain ! {
1744+ if let TraitItemKind :: Fn ( ref sig, _) = item. kind;
1745+ if let Some ( first_arg_ty) = sig. decl. inputs. iter( ) . next( ) ;
1746+ let first_arg_span = first_arg_ty. span;
1747+ let first_arg_ty = hir_ty_to_ty( cx. tcx, first_arg_ty) ;
1748+ let self_ty = TraitRef :: identity( cx. tcx, item. hir_id. owner. to_def_id( ) ) . self_ty( ) ;
1749+
1750+ then {
1751+ if let Some ( ( ref conv, self_kinds) ) = & CONVENTIONS
1752+ . iter( )
1753+ . find( |( ref conv, _) | conv. check( & item. ident. name. as_str( ) ) )
1754+ {
1755+ if !self_kinds. iter( ) . any( |k| k. matches( cx, self_ty, first_arg_ty) ) {
1756+ span_lint(
1757+ cx,
1758+ WRONG_PUB_SELF_CONVENTION ,
1759+ first_arg_span,
1760+ & format!( "methods called `{}` usually take {}; consider choosing a less ambiguous name" ,
1761+ conv,
1762+ & self_kinds
1763+ . iter( )
1764+ . map( |k| k. description( ) )
1765+ . collect:: <Vec <_>>( )
1766+ . join( " or " )
1767+ ) ,
1768+ ) ;
1769+ }
1770+ }
1771+ }
1772+ }
1773+
17381774 if_chain ! {
1739- if !in_external_macro( cx. tcx. sess, item. span) ;
17401775 if item. ident. name == sym:: new;
17411776 if let TraitItemKind :: Fn ( _, _) = item. kind;
17421777 let ret_ty = return_ty( cx, item. hir_id) ;
0 commit comments