@@ -16,6 +16,12 @@ use std::fmt::{self, Display};
16
16
use syntax:: { attr, symbol:: sym} ;
17
17
use syntax_pos:: Span ;
18
18
19
+ #[ derive( Copy , Clone , PartialEq ) ]
20
+ pub ( crate ) enum MethodKind {
21
+ Trait { body : bool } ,
22
+ Inherent ,
23
+ }
24
+
19
25
#[ derive( Copy , Clone , PartialEq ) ]
20
26
pub ( crate ) enum Target {
21
27
ExternCrate ,
@@ -38,7 +44,7 @@ pub(crate) enum Target {
38
44
Expression ,
39
45
Statement ,
40
46
AssocConst ,
41
- Method { body : bool } ,
47
+ Method ( MethodKind ) ,
42
48
AssocTy ,
43
49
ForeignFn ,
44
50
ForeignStatic ,
@@ -68,7 +74,7 @@ impl Display for Target {
68
74
Target :: Expression => "expression" ,
69
75
Target :: Statement => "statement" ,
70
76
Target :: AssocConst => "associated const" ,
71
- Target :: Method { .. } => "method" ,
77
+ Target :: Method ( _ ) => "method" ,
72
78
Target :: AssocTy => "associated type" ,
73
79
Target :: ForeignFn => "foreign function" ,
74
80
Target :: ForeignStatic => "foreign static item" ,
@@ -103,10 +109,10 @@ impl Target {
103
109
match trait_item. kind {
104
110
TraitItemKind :: Const ( ..) => Target :: AssocConst ,
105
111
TraitItemKind :: Method ( _, hir:: TraitMethod :: Required ( _) ) => {
106
- Target :: Method { body : false }
112
+ Target :: Method ( MethodKind :: Trait { body : false } )
107
113
}
108
114
TraitItemKind :: Method ( _, hir:: TraitMethod :: Provided ( _) ) => {
109
- Target :: Method { body : true }
115
+ Target :: Method ( MethodKind :: Trait { body : true } )
110
116
}
111
117
TraitItemKind :: Type ( ..) => Target :: AssocTy ,
112
118
}
@@ -120,10 +126,22 @@ impl Target {
120
126
}
121
127
}
122
128
123
- fn from_impl_item ( impl_item : & hir:: ImplItem ) -> Target {
129
+ fn from_impl_item < ' tcx > ( tcx : TyCtxt < ' tcx > , impl_item : & hir:: ImplItem ) -> Target {
124
130
match impl_item. kind {
125
131
hir:: ImplItemKind :: Const ( ..) => Target :: Const ,
126
- hir:: ImplItemKind :: Method ( ..) => Target :: Method { body : true } ,
132
+ hir:: ImplItemKind :: Method ( ..) => {
133
+ let parent_hir_id = tcx. hir ( ) . get_parent_item ( impl_item. hir_id ) ;
134
+ let containing_item = tcx. hir ( ) . expect_item ( parent_hir_id) ;
135
+ let containing_impl_is_for_trait = match & containing_item. kind {
136
+ hir:: ItemKind :: Impl ( _, _, _, _, tr, _, _) => tr. is_some ( ) ,
137
+ _ => bug ! ( "parent of an ImplItem must be an Impl" ) ,
138
+ } ;
139
+ if containing_impl_is_for_trait {
140
+ Target :: Method ( MethodKind :: Trait { body : true } )
141
+ } else {
142
+ Target :: Method ( MethodKind :: Inherent )
143
+ }
144
+ }
127
145
hir:: ImplItemKind :: TyAlias ( ..) => Target :: TyAlias ,
128
146
hir:: ImplItemKind :: OpaqueTy ( ..) => Target :: OpaqueTy ,
129
147
}
@@ -176,8 +194,9 @@ impl CheckAttrVisitor<'tcx> {
176
194
/// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
177
195
fn check_inline ( & self , hir_id : HirId , attr : & Attribute , span : & Span , target : Target ) -> bool {
178
196
match target {
179
- Target :: Fn | Target :: Closure | Target :: Method { body : true } => true ,
180
- Target :: Method { body : false } | Target :: ForeignFn => {
197
+ Target :: Fn | Target :: Closure | Target :: Method ( MethodKind :: Trait { body : true } )
198
+ | Target :: Method ( MethodKind :: Inherent ) => true ,
199
+ Target :: Method ( MethodKind :: Trait { body : false } ) | Target :: ForeignFn => {
181
200
self . tcx . struct_span_lint_hir (
182
201
UNUSED_ATTRIBUTES ,
183
202
hir_id,
@@ -216,8 +235,8 @@ impl CheckAttrVisitor<'tcx> {
216
235
) . emit ( ) ;
217
236
false
218
237
}
219
- Target :: Fn => true ,
220
- Target :: Method { .. } => {
238
+ Target :: Fn | Target :: Method ( MethodKind :: Inherent ) => true ,
239
+ Target :: Method ( _ ) => {
221
240
struct_span_err ! (
222
241
self . tcx. sess,
223
242
* attr_span,
@@ -278,7 +297,8 @@ impl CheckAttrVisitor<'tcx> {
278
297
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
279
298
fn check_target_feature ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
280
299
match target {
281
- Target :: Fn | Target :: Method { body : true } => true ,
300
+ Target :: Fn | Target :: Method ( MethodKind :: Trait { body : true } )
301
+ | Target :: Method ( MethodKind :: Inherent ) => true ,
282
302
_ => {
283
303
self . tcx . sess
284
304
. struct_span_err ( attr. span , "attribute should be applied to a function" )
@@ -471,7 +491,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
471
491
}
472
492
473
493
fn visit_impl_item ( & mut self , impl_item : & ' tcx hir:: ImplItem ) {
474
- let target = Target :: from_impl_item ( impl_item) ;
494
+ let target = Target :: from_impl_item ( self . tcx , impl_item) ;
475
495
self . check_attributes ( impl_item. hir_id , & impl_item. attrs , & impl_item. span , target, None ) ;
476
496
intravisit:: walk_impl_item ( self , impl_item)
477
497
}
0 commit comments