44//! conflicts between multiple such attributes attached to the same
55//! item.
66
7- use crate :: hir;
7+ use crate :: hir:: { self , HirId , HirVec , Attribute , Item , ItemKind , TraitItem , TraitItemKind } ;
8+ use crate :: hir:: DUMMY_HIR_ID ;
89use crate :: hir:: def_id:: DefId ;
910use crate :: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
1011use crate :: ty:: TyCtxt ;
@@ -64,24 +65,26 @@ impl Display for Target {
6465}
6566
6667impl Target {
67- pub ( crate ) fn from_item ( item : & hir :: Item ) -> Target {
68+ pub ( crate ) fn from_item ( item : & Item ) -> Target {
6869 match item. kind {
69- hir:: ItemKind :: ExternCrate ( ..) => Target :: ExternCrate ,
70- hir:: ItemKind :: Use ( ..) => Target :: Use ,
71- hir:: ItemKind :: Static ( ..) => Target :: Static ,
72- hir:: ItemKind :: Const ( ..) => Target :: Const ,
73- hir:: ItemKind :: Fn ( ..) => Target :: Fn ,
74- hir:: ItemKind :: Mod ( ..) => Target :: Mod ,
75- hir:: ItemKind :: ForeignMod ( ..) => Target :: ForeignMod ,
76- hir:: ItemKind :: GlobalAsm ( ..) => Target :: GlobalAsm ,
77- hir:: ItemKind :: TyAlias ( ..) => Target :: TyAlias ,
78- hir:: ItemKind :: OpaqueTy ( ..) => Target :: OpaqueTy ,
79- hir:: ItemKind :: Enum ( ..) => Target :: Enum ,
80- hir:: ItemKind :: Struct ( ..) => Target :: Struct ,
81- hir:: ItemKind :: Union ( ..) => Target :: Union ,
82- hir:: ItemKind :: Trait ( ..) => Target :: Trait ,
83- hir:: ItemKind :: TraitAlias ( ..) => Target :: TraitAlias ,
84- hir:: ItemKind :: Impl ( ..) => Target :: Impl ,
70+ ItemKind :: ExternCrate ( ..) => Target :: ExternCrate ,
71+ ItemKind :: Use ( ..) => Target :: Use ,
72+ ItemKind :: Static ( ..) => Target :: Static ,
73+ ItemKind :: Const ( ..) => Target :: Const ,
74+ ItemKind :: Fn ( ..) => Target :: Fn ,
75+ ItemKind :: Mod ( ..) => Target :: Mod ,
76+ ItemKind :: ForeignMod ( ..) => Target :: ForeignMod ,
77+ ItemKind :: GlobalAsm ( ..) => Target :: GlobalAsm ,
78+ ItemKind :: TyAlias ( ..) => Target :: TyAlias ,
79+ ItemKind :: OpaqueTy ( ..) => Target :: OpaqueTy ,
80+ ItemKind :: Enum ( ..) => Target :: Enum ,
81+ ItemKind :: Struct ( ..) => Target :: Struct ,
82+ ItemKind :: Union ( ..) => Target :: Union ,
83+ ItemKind :: Trait ( ..) => Target :: Trait ,
84+ ItemKind :: TraitAlias ( ..) => Target :: TraitAlias ,
85+ ItemKind :: Impl ( ..) => Target :: Impl ,
86+ }
87+ }
8588 }
8689 }
8790}
@@ -92,17 +95,24 @@ struct CheckAttrVisitor<'tcx> {
9295
9396impl CheckAttrVisitor < ' tcx > {
9497 /// Checks any attribute.
95- fn check_attributes ( & self , item : & hir:: Item , target : Target ) {
98+ fn check_attributes (
99+ & self ,
100+ hir_id : HirId ,
101+ attrs : & HirVec < Attribute > ,
102+ span : & Span ,
103+ target : Target ,
104+ item : Option < & Item > ,
105+ ) {
96106 let mut is_valid = true ;
97- for attr in & item . attrs {
107+ for attr in attrs {
98108 is_valid &= if attr. check_name ( sym:: inline) {
99- self . check_inline ( attr, & item . span , target)
109+ self . check_inline ( hir_id , attr, span, target)
100110 } else if attr. check_name ( sym:: non_exhaustive) {
101- self . check_non_exhaustive ( attr, item , target)
111+ self . check_non_exhaustive ( attr, span , target)
102112 } else if attr. check_name ( sym:: marker) {
103- self . check_marker ( attr, item , target)
113+ self . check_marker ( attr, span , target)
104114 } else if attr. check_name ( sym:: target_feature) {
105- self . check_target_feature ( attr, item , target)
115+ self . check_target_feature ( attr, span , target)
106116 } else if attr. check_name ( sym:: track_caller) {
107117 self . check_track_caller ( attr, & item, target)
108118 } else {
@@ -115,25 +125,26 @@ impl CheckAttrVisitor<'tcx> {
115125 }
116126
117127 if target == Target :: Fn {
118- self . tcx . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( item . hir_id ) ) ;
128+ self . tcx . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( hir_id) ) ;
119129 }
120130
121- self . check_repr ( item , target) ;
122- self . check_used ( item , target) ;
131+ self . check_repr ( attrs , span , target, item ) ;
132+ self . check_used ( attrs , target) ;
123133 }
124134
125135 /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
126- fn check_inline ( & self , attr : & hir:: Attribute , span : & Span , target : Target ) -> bool {
127- if target != Target :: Fn && target != Target :: Closure {
128- struct_span_err ! ( self . tcx. sess,
129- attr. span,
130- E0518 ,
131- "attribute should be applied to function or closure" )
132- . span_label ( * span, "not a function or closure" )
133- . emit ( ) ;
134- false
135- } else {
136- true
136+ fn check_inline ( & self , hir_id : HirId , attr : & Attribute , span : & Span , target : Target ) -> bool {
137+ match target {
138+ Target :: Fn | Target :: Closure | Target :: Method { body : true } => true ,
139+ _ => {
140+ struct_span_err ! ( self . tcx. sess,
141+ attr. span,
142+ E0518 ,
143+ "attribute should be applied to function or closure" )
144+ . span_label ( * span, "not a function or closure" )
145+ . emit ( ) ;
146+ false
147+ }
137148 }
138149 }
139150
@@ -166,8 +177,8 @@ impl CheckAttrVisitor<'tcx> {
166177 /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
167178 fn check_non_exhaustive (
168179 & self ,
169- attr : & hir :: Attribute ,
170- item : & hir :: Item ,
180+ attr : & Attribute ,
181+ span : & Span ,
171182 target : Target ,
172183 ) -> bool {
173184 match target {
@@ -177,54 +188,55 @@ impl CheckAttrVisitor<'tcx> {
177188 attr. span,
178189 E0701 ,
179190 "attribute can only be applied to a struct or enum" )
180- . span_label ( item . span , "not a struct or enum" )
191+ . span_label ( * span, "not a struct or enum" )
181192 . emit ( ) ;
182193 false
183194 }
184195 }
185196 }
186197
187198 /// Checks if the `#[marker]` attribute on an `item` is valid. Returns `true` if valid.
188- fn check_marker ( & self , attr : & hir :: Attribute , item : & hir :: Item , target : Target ) -> bool {
199+ fn check_marker ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
189200 match target {
190201 Target :: Trait => true ,
191202 _ => {
192203 self . tcx . sess
193204 . struct_span_err ( attr. span , "attribute can only be applied to a trait" )
194- . span_label ( item . span , "not a trait" )
205+ . span_label ( * span, "not a trait" )
195206 . emit ( ) ;
196207 false
197208 }
198209 }
199210 }
200211
201212 /// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
202- fn check_target_feature (
203- & self ,
204- attr : & hir:: Attribute ,
205- item : & hir:: Item ,
206- target : Target ,
207- ) -> bool {
213+ fn check_target_feature ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
208214 match target {
209215 Target :: Fn => true ,
210216 _ => {
211217 self . tcx . sess
212218 . struct_span_err ( attr. span , "attribute should be applied to a function" )
213- . span_label ( item . span , "not a function" )
219+ . span_label ( * span, "not a function" )
214220 . emit ( ) ;
215221 false
216222 } ,
217223 }
218224 }
219225
220226 /// Checks if the `#[repr]` attributes on `item` are valid.
221- fn check_repr ( & self , item : & hir:: Item , target : Target ) {
227+ fn check_repr (
228+ & self ,
229+ attrs : & HirVec < Attribute > ,
230+ span : & Span ,
231+ target : Target ,
232+ item : Option < & Item > ,
233+ ) {
222234 // Extract the names of all repr hints, e.g., [foo, bar, align] for:
223235 // ```
224236 // #[repr(foo)]
225237 // #[repr(bar, align(8))]
226238 // ```
227- let hints: Vec < _ > = item . attrs
239+ let hints: Vec < _ > = attrs
228240 . iter ( )
229241 . filter ( |attr| attr. check_name ( sym:: repr) )
230242 . filter_map ( |attr| attr. meta_item_list ( ) )
@@ -282,7 +294,7 @@ impl CheckAttrVisitor<'tcx> {
282294 } ;
283295 self . emit_repr_error (
284296 hint. span ( ) ,
285- item . span ,
297+ * span,
286298 & format ! ( "attribute should be applied to {}" , allowed_targets) ,
287299 & format ! ( "not {} {}" , article, allowed_targets) ,
288300 )
@@ -301,7 +313,7 @@ impl CheckAttrVisitor<'tcx> {
301313 // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
302314 if ( int_reprs > 1 )
303315 || ( is_simd && is_c)
304- || ( int_reprs == 1 && is_c && is_c_like_enum ( item) ) {
316+ || ( int_reprs == 1 && is_c && item . map ( |item| is_c_like_enum ( item) ) . unwrap_or ( false ) ) {
305317 let hint_spans: Vec < _ > = hint_spans. collect ( ) ;
306318 span_warn ! ( self . tcx. sess, hint_spans, E0566 ,
307319 "conflicting representation hints" ) ;
@@ -325,7 +337,7 @@ impl CheckAttrVisitor<'tcx> {
325337 if let hir:: StmtKind :: Local ( ref l) = stmt. kind {
326338 for attr in l. attrs . iter ( ) {
327339 if attr. check_name ( sym:: inline) {
328- self . check_inline ( attr, & stmt. span , Target :: Statement ) ;
340+ self . check_inline ( DUMMY_HIR_ID , attr, & stmt. span , Target :: Statement ) ;
329341 }
330342 if attr. check_name ( sym:: repr) {
331343 self . emit_repr_error (
@@ -346,7 +358,7 @@ impl CheckAttrVisitor<'tcx> {
346358 } ;
347359 for attr in expr. attrs . iter ( ) {
348360 if attr. check_name ( sym:: inline) {
349- self . check_inline ( attr, & expr. span , target) ;
361+ self . check_inline ( DUMMY_HIR_ID , attr, & expr. span , target) ;
350362 }
351363 if attr. check_name ( sym:: repr) {
352364 self . emit_repr_error (
@@ -359,8 +371,8 @@ impl CheckAttrVisitor<'tcx> {
359371 }
360372 }
361373
362- fn check_used ( & self , item : & hir :: Item , target : Target ) {
363- for attr in & item . attrs {
374+ fn check_used ( & self , attrs : & HirVec < Attribute > , target : Target ) {
375+ for attr in attrs {
364376 if attr. check_name ( sym:: used) && target != Target :: Static {
365377 self . tcx . sess
366378 . span_err ( attr. span , "attribute must be applied to a `static` variable" ) ;
@@ -374,9 +386,9 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
374386 NestedVisitorMap :: OnlyBodies ( & self . tcx . hir ( ) )
375387 }
376388
377- fn visit_item ( & mut self , item : & ' tcx hir :: Item ) {
389+ fn visit_item ( & mut self , item : & ' tcx Item ) {
378390 let target = Target :: from_item ( item) ;
379- self . check_attributes ( item, target) ;
391+ self . check_attributes ( item. hir_id , & item . attrs , & item . span , target, Some ( item ) ) ;
380392 intravisit:: walk_item ( self , item)
381393 }
382394
@@ -392,12 +404,12 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
392404 }
393405}
394406
395- fn is_c_like_enum ( item : & hir :: Item ) -> bool {
396- if let hir :: ItemKind :: Enum ( ref def, _) = item. kind {
407+ fn is_c_like_enum ( item : & Item ) -> bool {
408+ if let ItemKind :: Enum ( ref def, _) = item. kind {
397409 for variant in & def. variants {
398410 match variant. data {
399411 hir:: VariantData :: Unit ( ..) => { /* continue */ }
400- _ => { return false ; }
412+ _ => return false ,
401413 }
402414 }
403415 true
0 commit comments