@@ -22,6 +22,7 @@ use rustc_semver::RustcVersion;
22
22
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
23
23
use rustc_span:: source_map:: Span ;
24
24
use rustc_span:: symbol:: { sym, SymbolStr } ;
25
+ use rustc_typeck:: hir_ty_to_ty;
25
26
26
27
use crate :: consts:: { constant, Constant } ;
27
28
use crate :: utils:: eager_or_lazy:: is_lazyness_candidate;
@@ -1623,10 +1624,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1623
1624
let item = cx. tcx . hir ( ) . expect_item ( parent) ;
1624
1625
let def_id = cx. tcx . hir ( ) . local_def_id ( item. hir_id ) ;
1625
1626
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
+
1626
1633
if_chain ! {
1627
1634
if let hir:: ImplItemKind :: Fn ( ref sig, id) = impl_item. kind;
1628
1635
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;
1630
1636
1631
1637
let method_def_id = cx. tcx. hir( ) . local_def_id( impl_item. hir_id) ;
1632
1638
let method_sig = cx. tcx. fn_sig( method_def_id) ;
@@ -1697,11 +1703,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1697
1703
}
1698
1704
}
1699
1705
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
-
1705
1706
if let hir:: ImplItemKind :: Fn ( _, _) = impl_item. kind {
1706
1707
let ret_ty = return_ty ( cx, impl_item. hir_id ) ;
1707
1708
@@ -1735,8 +1736,42 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
1735
1736
}
1736
1737
1737
1738
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
+
1738
1774
if_chain ! {
1739
- if !in_external_macro( cx. tcx. sess, item. span) ;
1740
1775
if item. ident. name == sym:: new;
1741
1776
if let TraitItemKind :: Fn ( _, _) = item. kind;
1742
1777
let ret_ty = return_ty( cx, item. hir_id) ;
0 commit comments