@@ -23,6 +23,7 @@ use rustc_middle::ty::{self, TraitRef, Ty, TyS};
23
23
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
24
24
use rustc_span:: source_map:: Span ;
25
25
use rustc_span:: symbol:: { sym, SymbolStr } ;
26
+ use rustc_typeck:: hir_ty_to_ty;
26
27
27
28
use crate :: consts:: { constant, Constant } ;
28
29
use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
@@ -1608,10 +1609,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1608
1609
let item = cx. tcx . hir ( ) . expect_item ( parent) ;
1609
1610
let def_id = cx. tcx . hir ( ) . local_def_id ( item. hir_id ) ;
1610
1611
let self_ty = cx. tcx . type_of ( def_id) ;
1612
+
1613
+ // if this impl block implements a trait, lint in trait definition instead
1614
+ if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = item. kind {
1615
+ return ;
1616
+ }
1617
+
1611
1618
if_chain ! {
1612
1619
if let hir:: ImplItemKind :: Fn ( ref sig, id) = impl_item. kind;
1613
1620
if let Some ( first_arg) = iter_input_pats( & sig. decl, cx. tcx. hir( ) . body( id) ) . next( ) ;
1614
- if let hir:: ItemKind :: Impl { of_trait: None , .. } = item. kind;
1615
1621
1616
1622
let method_def_id = cx. tcx. hir( ) . local_def_id( impl_item. hir_id) ;
1617
1623
let method_sig = cx. tcx. fn_sig( method_def_id) ;
@@ -1682,11 +1688,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1682
1688
}
1683
1689
}
1684
1690
1685
- // if this impl block implements a trait, lint in trait definition instead
1686
- if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = item. kind {
1687
- return ;
1688
- }
1689
-
1690
1691
if let hir:: ImplItemKind :: Fn ( _, _) = impl_item. kind {
1691
1692
let ret_ty = return_ty ( cx, impl_item. hir_id ) ;
1692
1693
@@ -1720,8 +1721,42 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1720
1721
}
1721
1722
1722
1723
fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx TraitItem < ' _ > ) {
1724
+ if in_external_macro ( cx. tcx . sess , item. span ) {
1725
+ return ;
1726
+ }
1727
+
1728
+ if_chain ! {
1729
+ if let TraitItemKind :: Fn ( ref sig, _) = item. kind;
1730
+ if let Some ( first_arg_ty) = sig. decl. inputs. iter( ) . next( ) ;
1731
+ let first_arg_span = first_arg_ty. span;
1732
+ let first_arg_ty = hir_ty_to_ty( cx. tcx, first_arg_ty) ;
1733
+ let self_ty = TraitRef :: identity( cx. tcx, item. hir_id. owner. to_def_id( ) ) . self_ty( ) ;
1734
+
1735
+ then {
1736
+ if let Some ( ( ref conv, self_kinds) ) = & CONVENTIONS
1737
+ . iter( )
1738
+ . find( |( ref conv, _) | conv. check( & item. ident. name. as_str( ) ) )
1739
+ {
1740
+ if !self_kinds. iter( ) . any( |k| k. matches( cx, self_ty, first_arg_ty) ) {
1741
+ span_lint(
1742
+ cx,
1743
+ WRONG_PUB_SELF_CONVENTION ,
1744
+ first_arg_span,
1745
+ & format!( "methods called `{}` usually take {}; consider choosing a less ambiguous name" ,
1746
+ conv,
1747
+ & self_kinds
1748
+ . iter( )
1749
+ . map( |k| k. description( ) )
1750
+ . collect:: <Vec <_>>( )
1751
+ . join( " or " )
1752
+ ) ,
1753
+ ) ;
1754
+ }
1755
+ }
1756
+ }
1757
+ }
1758
+
1723
1759
if_chain ! {
1724
- if !in_external_macro( cx. tcx. sess, item. span) ;
1725
1760
if item. ident. name == sym:: new;
1726
1761
if let TraitItemKind :: Fn ( _, _) = item. kind;
1727
1762
let ret_ty = return_ty( cx, item. hir_id) ;
0 commit comments