4
4
//! conflicts between multiple such attributes attached to the same
5
5
//! item.
6
6
7
- use crate :: hir;
7
+ use crate :: hir:: { self , HirId , HirVec , Attribute , Item , ItemKind , TraitItem , TraitItemKind } ;
8
+ use crate :: hir:: DUMMY_HIR_ID ;
8
9
use crate :: hir:: def_id:: DefId ;
9
10
use crate :: hir:: intravisit:: { self , Visitor , NestedVisitorMap } ;
10
11
use crate :: ty:: TyCtxt ;
@@ -64,24 +65,26 @@ impl Display for Target {
64
65
}
65
66
66
67
impl Target {
67
- pub ( crate ) fn from_item ( item : & hir :: Item ) -> Target {
68
+ pub ( crate ) fn from_item ( item : & Item ) -> Target {
68
69
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
+ }
85
88
}
86
89
}
87
90
}
@@ -92,17 +95,24 @@ struct CheckAttrVisitor<'tcx> {
92
95
93
96
impl CheckAttrVisitor < ' tcx > {
94
97
/// 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
+ ) {
96
106
let mut is_valid = true ;
97
- for attr in & item . attrs {
107
+ for attr in attrs {
98
108
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)
100
110
} else if attr. check_name ( sym:: non_exhaustive) {
101
- self . check_non_exhaustive ( attr, item , target)
111
+ self . check_non_exhaustive ( attr, span , target)
102
112
} else if attr. check_name ( sym:: marker) {
103
- self . check_marker ( attr, item , target)
113
+ self . check_marker ( attr, span , target)
104
114
} else if attr. check_name ( sym:: target_feature) {
105
- self . check_target_feature ( attr, item , target)
115
+ self . check_target_feature ( attr, span , target)
106
116
} else if attr. check_name ( sym:: track_caller) {
107
117
self . check_track_caller ( attr, & item, target)
108
118
} else {
@@ -115,25 +125,26 @@ impl CheckAttrVisitor<'tcx> {
115
125
}
116
126
117
127
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) ) ;
119
129
}
120
130
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) ;
123
133
}
124
134
125
135
/// 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
+ }
137
148
}
138
149
}
139
150
@@ -166,8 +177,8 @@ impl CheckAttrVisitor<'tcx> {
166
177
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
167
178
fn check_non_exhaustive (
168
179
& self ,
169
- attr : & hir :: Attribute ,
170
- item : & hir :: Item ,
180
+ attr : & Attribute ,
181
+ span : & Span ,
171
182
target : Target ,
172
183
) -> bool {
173
184
match target {
@@ -177,54 +188,55 @@ impl CheckAttrVisitor<'tcx> {
177
188
attr. span,
178
189
E0701 ,
179
190
"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" )
181
192
. emit ( ) ;
182
193
false
183
194
}
184
195
}
185
196
}
186
197
187
198
/// 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 {
189
200
match target {
190
201
Target :: Trait => true ,
191
202
_ => {
192
203
self . tcx . sess
193
204
. 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" )
195
206
. emit ( ) ;
196
207
false
197
208
}
198
209
}
199
210
}
200
211
201
212
/// 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 {
208
214
match target {
209
215
Target :: Fn => true ,
210
216
_ => {
211
217
self . tcx . sess
212
218
. 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" )
214
220
. emit ( ) ;
215
221
false
216
222
} ,
217
223
}
218
224
}
219
225
220
226
/// 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
+ ) {
222
234
// Extract the names of all repr hints, e.g., [foo, bar, align] for:
223
235
// ```
224
236
// #[repr(foo)]
225
237
// #[repr(bar, align(8))]
226
238
// ```
227
- let hints: Vec < _ > = item . attrs
239
+ let hints: Vec < _ > = attrs
228
240
. iter ( )
229
241
. filter ( |attr| attr. check_name ( sym:: repr) )
230
242
. filter_map ( |attr| attr. meta_item_list ( ) )
@@ -282,7 +294,7 @@ impl CheckAttrVisitor<'tcx> {
282
294
} ;
283
295
self . emit_repr_error (
284
296
hint. span ( ) ,
285
- item . span ,
297
+ * span,
286
298
& format ! ( "attribute should be applied to {}" , allowed_targets) ,
287
299
& format ! ( "not {} {}" , article, allowed_targets) ,
288
300
)
@@ -301,7 +313,7 @@ impl CheckAttrVisitor<'tcx> {
301
313
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
302
314
if ( int_reprs > 1 )
303
315
|| ( 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 ) ) {
305
317
let hint_spans: Vec < _ > = hint_spans. collect ( ) ;
306
318
span_warn ! ( self . tcx. sess, hint_spans, E0566 ,
307
319
"conflicting representation hints" ) ;
@@ -325,7 +337,7 @@ impl CheckAttrVisitor<'tcx> {
325
337
if let hir:: StmtKind :: Local ( ref l) = stmt. kind {
326
338
for attr in l. attrs . iter ( ) {
327
339
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 ) ;
329
341
}
330
342
if attr. check_name ( sym:: repr) {
331
343
self . emit_repr_error (
@@ -346,7 +358,7 @@ impl CheckAttrVisitor<'tcx> {
346
358
} ;
347
359
for attr in expr. attrs . iter ( ) {
348
360
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) ;
350
362
}
351
363
if attr. check_name ( sym:: repr) {
352
364
self . emit_repr_error (
@@ -359,8 +371,8 @@ impl CheckAttrVisitor<'tcx> {
359
371
}
360
372
}
361
373
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 {
364
376
if attr. check_name ( sym:: used) && target != Target :: Static {
365
377
self . tcx . sess
366
378
. span_err ( attr. span , "attribute must be applied to a `static` variable" ) ;
@@ -374,9 +386,9 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
374
386
NestedVisitorMap :: OnlyBodies ( & self . tcx . hir ( ) )
375
387
}
376
388
377
- fn visit_item ( & mut self , item : & ' tcx hir :: Item ) {
389
+ fn visit_item ( & mut self , item : & ' tcx Item ) {
378
390
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 ) ) ;
380
392
intravisit:: walk_item ( self , item)
381
393
}
382
394
@@ -392,12 +404,12 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
392
404
}
393
405
}
394
406
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 {
397
409
for variant in & def. variants {
398
410
match variant. data {
399
411
hir:: VariantData :: Unit ( ..) => { /* continue */ }
400
- _ => { return false ; }
412
+ _ => return false ,
401
413
}
402
414
}
403
415
true
0 commit comments