@@ -16,6 +16,12 @@ use std::fmt::{self, Display};
1616use syntax:: { attr, symbol:: sym} ;
1717use syntax_pos:: Span ;
1818
19+ #[ derive( Copy , Clone , PartialEq ) ]
20+ pub ( crate ) enum MethodKind {
21+ Trait { body : bool } ,
22+ Inherent ,
23+ }
24+
1925#[ derive( Copy , Clone , PartialEq ) ]
2026pub ( crate ) enum Target {
2127 ExternCrate ,
@@ -38,7 +44,7 @@ pub(crate) enum Target {
3844 Expression ,
3945 Statement ,
4046 AssocConst ,
41- Method { body : bool } ,
47+ Method ( MethodKind ) ,
4248 AssocTy ,
4349 ForeignFn ,
4450 ForeignStatic ,
@@ -68,7 +74,7 @@ impl Display for Target {
6874 Target :: Expression => "expression" ,
6975 Target :: Statement => "statement" ,
7076 Target :: AssocConst => "associated const" ,
71- Target :: Method { .. } => "method" ,
77+ Target :: Method ( _ ) => "method" ,
7278 Target :: AssocTy => "associated type" ,
7379 Target :: ForeignFn => "foreign function" ,
7480 Target :: ForeignStatic => "foreign static item" ,
@@ -103,10 +109,10 @@ impl Target {
103109 match trait_item. kind {
104110 TraitItemKind :: Const ( ..) => Target :: AssocConst ,
105111 TraitItemKind :: Method ( _, hir:: TraitMethod :: Required ( _) ) => {
106- Target :: Method { body : false }
112+ Target :: Method ( MethodKind :: Trait { body : false } )
107113 }
108114 TraitItemKind :: Method ( _, hir:: TraitMethod :: Provided ( _) ) => {
109- Target :: Method { body : true }
115+ Target :: Method ( MethodKind :: Trait { body : true } )
110116 }
111117 TraitItemKind :: Type ( ..) => Target :: AssocTy ,
112118 }
@@ -120,10 +126,22 @@ impl Target {
120126 }
121127 }
122128
123- fn from_impl_item ( impl_item : & hir:: ImplItem ) -> Target {
129+ fn from_impl_item < ' tcx > ( tcx : TyCtxt < ' tcx > , impl_item : & hir:: ImplItem ) -> Target {
124130 match impl_item. kind {
125131 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+ }
127145 hir:: ImplItemKind :: TyAlias ( ..) => Target :: TyAlias ,
128146 hir:: ImplItemKind :: OpaqueTy ( ..) => Target :: OpaqueTy ,
129147 }
@@ -176,8 +194,9 @@ impl CheckAttrVisitor<'tcx> {
176194 /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
177195 fn check_inline ( & self , hir_id : HirId , attr : & Attribute , span : & Span , target : Target ) -> bool {
178196 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 => {
181200 self . tcx . struct_span_lint_hir (
182201 UNUSED_ATTRIBUTES ,
183202 hir_id,
@@ -216,8 +235,8 @@ impl CheckAttrVisitor<'tcx> {
216235 ) . emit ( ) ;
217236 false
218237 }
219- Target :: Fn => true ,
220- Target :: Method { .. } => {
238+ Target :: Fn | Target :: Method ( MethodKind :: Inherent ) => true ,
239+ Target :: Method ( _ ) => {
221240 struct_span_err ! (
222241 self . tcx. sess,
223242 * attr_span,
@@ -278,7 +297,8 @@ impl CheckAttrVisitor<'tcx> {
278297 /// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
279298 fn check_target_feature ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
280299 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 ,
282302 _ => {
283303 self . tcx . sess
284304 . struct_span_err ( attr. span , "attribute should be applied to a function" )
@@ -471,7 +491,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
471491 }
472492
473493 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) ;
475495 self . check_attributes ( impl_item. hir_id , & impl_item. attrs , & impl_item. span , target, None ) ;
476496 intravisit:: walk_impl_item ( self , impl_item)
477497 }
0 commit comments