@@ -4,19 +4,18 @@ use rustc_hir::def::{DefKind, Res};
4
4
use rustc_hir:: { Crate , Impl , ItemKind , Node , Path , QPath , TraitRef , TyKind } ;
5
5
use rustc_lint:: { LateContext , LateLintPass } ;
6
6
use rustc_middle:: ty:: AssocKind ;
7
- use rustc_session:: { declare_tool_lint, impl_lint_pass } ;
7
+ use rustc_session:: { declare_tool_lint, declare_lint_pass } ;
8
8
use rustc_span:: symbol:: SymbolStr ;
9
9
use rustc_span:: Span ;
10
10
use std:: collections:: { BTreeMap , BTreeSet } ;
11
11
12
12
declare_clippy_lint ! {
13
13
/// ### What it does
14
- /// it lints if a struct has two method with same time:
15
- /// one from trait, another not from trait.
16
- ///
14
+ /// It lints if a struct has two method with same time:
15
+ /// one from a trait, another not from trait.
17
16
///
18
17
/// ### Why is this bad?
19
- /// confusing .
18
+ /// Confusing .
20
19
///
21
20
/// ### Example
22
21
/// ```rust
@@ -33,16 +32,13 @@ declare_clippy_lint! {
33
32
/// impl S {
34
33
/// fn foo(&self) {}
35
34
/// }
36
- ///
37
35
/// ```
38
36
pub SAME_NAME_METHOD ,
39
37
style,
40
38
"two method with same name"
41
39
}
42
40
43
- impl_lint_pass ! ( SameNameMethod => [ SAME_NAME_METHOD ] ) ;
44
-
45
- pub struct SameNameMethod ;
41
+ declare_lint_pass ! ( SameNameMethod => [ SAME_NAME_METHOD ] ) ;
46
42
47
43
struct S {
48
44
impl_methods : BTreeMap < SymbolStr , Span > ,
@@ -76,13 +72,13 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
76
72
match of_trait {
77
73
Some ( trait_ref) => {
78
74
let mut methods_in_trait: BTreeSet < SymbolStr > = if_chain ! {
79
- if let Some ( Node :: TraitRef ( TraitRef { path, .. } ) ) = cx. tcx. hir( ) . find( trait_ref. hir_ref_id) ;
75
+ if let Some ( Node :: TraitRef ( TraitRef { path, .. } ) ) =
76
+ cx. tcx. hir( ) . find( trait_ref. hir_ref_id) ;
80
77
if let Res :: Def ( DefKind :: Trait , did) = path. res;
81
78
then{
82
79
// FIXME: if
83
80
// `rustc_middle::ty::assoc::AssocItems::items` is public,
84
- // we can iterate the keys, it's more
85
- // efficient
81
+ // we can iterate its keys, which's more efficient
86
82
cx. tcx
87
83
. associated_items( did)
88
84
. in_definition_order( )
@@ -96,48 +92,36 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
96
92
}
97
93
} ;
98
94
99
- for impl_item_ref in ( * items) . iter ( ) . filter ( |impl_item_ref| {
100
- matches ! ( impl_item_ref. kind, rustc_hir:: AssocItemKind :: Fn { .. } )
101
- } ) {
102
- let method_name = impl_item_ref. ident . as_str ( ) ;
103
- methods_in_trait. remove ( & method_name) ;
104
- let trait_span = impl_item_ref. span ;
95
+ let mut check_trait_method = |method_name : SymbolStr , trait_method_span| {
105
96
if let Some ( impl_span) = s. impl_methods . get ( & method_name) {
106
97
span_lint_and_then (
107
98
cx,
108
99
SAME_NAME_METHOD ,
109
100
* impl_span,
110
101
"binding's name is same to an existing binding" ,
111
102
|diag| {
112
- diag. span_note ( trait_span , "existing binding defined here" ) ;
103
+ diag. span_note ( trait_method_span , "existing binding defined here" ) ;
113
104
} ,
114
105
) ;
115
106
}
116
107
if let Some ( v) = s. trait_methods . get_mut ( & method_name) {
117
- v. push ( trait_span ) ;
108
+ v. push ( trait_method_span ) ;
118
109
} else {
119
- s. trait_methods . insert ( method_name, vec ! [ trait_span ] ) ;
110
+ s. trait_methods . insert ( method_name, vec ! [ trait_method_span ] ) ;
120
111
}
112
+ } ;
113
+
114
+ for impl_item_ref in ( * items) . iter ( ) . filter ( |impl_item_ref| {
115
+ matches ! ( impl_item_ref. kind, rustc_hir:: AssocItemKind :: Fn { .. } )
116
+ } ) {
117
+ let method_name = impl_item_ref. ident . as_str ( ) ;
118
+ methods_in_trait. remove ( & method_name) ;
119
+ check_trait_method ( method_name, impl_item_ref. span ) ;
121
120
}
122
121
123
122
let trait_span = item. span ;
124
123
for method_name in methods_in_trait {
125
- if let Some ( impl_span) = s. impl_methods . get ( & method_name) {
126
- span_lint_and_then (
127
- cx,
128
- SAME_NAME_METHOD ,
129
- * impl_span,
130
- "binding's name is same to an existing binding" ,
131
- |diag| {
132
- diag. span_note ( trait_span, "existing binding defined here" ) ;
133
- } ,
134
- ) ;
135
- }
136
- if let Some ( v) = s. trait_methods . get_mut ( & method_name) {
137
- v. push ( trait_span) ;
138
- } else {
139
- s. trait_methods . insert ( method_name, vec ! [ trait_span] ) ;
140
- }
124
+ check_trait_method ( method_name, trait_span) ;
141
125
}
142
126
} ,
143
127
None => {
@@ -154,6 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
154
138
"binding's name is same to an existing binding" ,
155
139
|diag| {
156
140
// TODO should we `span_note` on every trait?
141
+ // iterate on trait_spans?
157
142
diag. span_note ( trait_spans[ 0 ] , "existing binding defined here" ) ;
158
143
} ,
159
144
) ;
0 commit comments