@@ -66,22 +66,24 @@ impl CheckAttrVisitor<'tcx> {
66
66
} else if self . tcx . sess . check_name ( attr, sym:: marker) {
67
67
self . check_marker ( attr, span, target)
68
68
} else if self . tcx . sess . check_name ( attr, sym:: target_feature) {
69
- self . check_target_feature ( attr, span, target)
69
+ self . check_target_feature ( hir_id , attr, span, target)
70
70
} else if self . tcx . sess . check_name ( attr, sym:: track_caller) {
71
71
self . check_track_caller ( & attr. span , attrs, span, target)
72
72
} else if self . tcx . sess . check_name ( attr, sym:: doc) {
73
73
self . check_doc_alias ( attr, hir_id, target)
74
- } else if self . tcx . sess . check_name ( attr, sym:: cold) {
75
- self . check_cold ( & attr, span, target)
76
- } else if self . tcx . sess . check_name ( attr, sym:: link_name) {
77
- self . check_link_name ( & attr, span, target)
78
74
} else if self . tcx . sess . check_name ( attr, sym:: no_link) {
79
75
self . check_no_link ( & attr, span, target)
80
76
} else if self . tcx . sess . check_name ( attr, sym:: export_name) {
81
77
self . check_export_name ( & attr, span, target)
82
- } else if self . tcx . sess . check_name ( attr, sym:: link_section) {
83
- self . check_link_section ( & attr, span, target)
84
78
} else {
79
+ // lint-only checks
80
+ if self . tcx . sess . check_name ( attr, sym:: cold) {
81
+ self . check_cold ( hir_id, attr, span, target) ;
82
+ } else if self . tcx . sess . check_name ( attr, sym:: link_name) {
83
+ self . check_link_name ( hir_id, attr, span, target) ;
84
+ } else if self . tcx . sess . check_name ( attr, sym:: link_section) {
85
+ self . check_link_section ( hir_id, attr, span, target) ;
86
+ }
85
87
true
86
88
} ;
87
89
}
@@ -212,10 +214,31 @@ impl CheckAttrVisitor<'tcx> {
212
214
}
213
215
214
216
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
215
- fn check_target_feature ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
217
+ fn check_target_feature (
218
+ & self ,
219
+ hir_id : HirId ,
220
+ attr : & Attribute ,
221
+ span : & Span ,
222
+ target : Target ,
223
+ ) -> bool {
216
224
match target {
217
225
Target :: Fn
218
226
| Target :: Method ( MethodKind :: Trait { body : true } | MethodKind :: Inherent ) => true ,
227
+ // FIXME: #[target_feature] was previously erroneously allowed on statements and some
228
+ // crates used this, so only emit a warning.
229
+ Target :: Statement => {
230
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
231
+ lint. build ( "attribute should be applied to a function" )
232
+ . warn (
233
+ "this was previously accepted by the compiler but is \
234
+ being phased out; it will become a hard error in \
235
+ a future release!",
236
+ )
237
+ . span_label ( * span, "not a function" )
238
+ . emit ( ) ;
239
+ } ) ;
240
+ true
241
+ }
219
242
_ => {
220
243
self . tcx
221
244
. sess
@@ -288,45 +311,58 @@ impl CheckAttrVisitor<'tcx> {
288
311
}
289
312
290
313
/// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid.
291
- fn check_cold ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
314
+ fn check_cold ( & self , hir_id : HirId , attr : & Attribute , span : & Span , target : Target ) {
292
315
match target {
293
- Target :: Fn | Target :: Method ( ..) | Target :: ForeignFn => true ,
316
+ Target :: Fn | Target :: Method ( ..) | Target :: ForeignFn => { }
294
317
_ => {
295
- self . tcx
296
- . sess
297
- . struct_span_err ( attr. span , "attribute should be applied to a function" )
298
- . span_label ( * span, "not a function" )
299
- . emit ( ) ;
300
- false
318
+ // FIXME: #[cold] was previously allowed on non-functions and some crates used
319
+ // this, so only emit a warning.
320
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
321
+ lint. build ( "attribute should be applied to a function" )
322
+ . warn (
323
+ "this was previously accepted by the compiler but is \
324
+ being phased out; it will become a hard error in \
325
+ a future release!",
326
+ )
327
+ . span_label ( * span, "not a function" )
328
+ . emit ( ) ;
329
+ } ) ;
301
330
}
302
331
}
303
332
}
304
333
305
- /// Checks if `#[link_name]` is applied to an item other than a foreign function or static. Returns `true` if valid.
306
- fn check_link_name ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
307
- if target == Target :: ForeignFn || target == Target :: ForeignStatic {
308
- true
309
- } else {
310
- let mut err = self . tcx . sess . struct_span_err (
311
- attr. span ,
312
- "attribute should be applied to a foreign function or static" ,
313
- ) ;
314
- err. span_label ( * span, "not a foreign function or static" ) ;
315
-
316
- // See issue #47725
317
- if target == Target :: ForeignMod {
318
- if let Some ( value) = attr. value_str ( ) {
319
- err. span_help (
320
- attr. span ,
321
- & format ! ( r#"try `#[link(name = "{}")]` instead"# , value) ,
334
+ /// Checks if `#[link_name]` is applied to an item other than a foreign function or static.
335
+ fn check_link_name ( & self , hir_id : HirId , attr : & Attribute , span : & Span , target : Target ) {
336
+ match target {
337
+ Target :: ForeignFn | Target :: ForeignStatic => { }
338
+ _ => {
339
+ // FIXME: #[cold] was previously allowed on non-functions/statics and some crates
340
+ // used this, so only emit a warning.
341
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
342
+ let mut diag =
343
+ lint. build ( "attribute should be applied to a foreign function or static" ) ;
344
+ diag. warn (
345
+ "this was previously accepted by the compiler but is \
346
+ being phased out; it will become a hard error in \
347
+ a future release!",
322
348
) ;
323
- } else {
324
- err. span_help ( attr. span , r#"try `#[link(name = "...")]` instead"# ) ;
325
- }
326
- }
327
349
328
- err. emit ( ) ;
329
- false
350
+ // See issue #47725
351
+ if let Target :: ForeignMod = target {
352
+ if let Some ( value) = attr. value_str ( ) {
353
+ diag. span_help (
354
+ attr. span ,
355
+ & format ! ( r#"try `#[link(name = "{}")]` instead"# , value) ,
356
+ ) ;
357
+ } else {
358
+ diag. span_help ( attr. span , r#"try `#[link(name = "...")]` instead"# ) ;
359
+ }
360
+ }
361
+
362
+ diag. span_label ( * span, "not a foreign function or static" ) ;
363
+ diag. emit ( ) ;
364
+ } ) ;
365
+ }
330
366
}
331
367
}
332
368
@@ -362,20 +398,23 @@ impl CheckAttrVisitor<'tcx> {
362
398
}
363
399
}
364
400
365
- /// Checks if `#[link_section]` is applied to a function or static. Returns `true` if valid.
366
- fn check_link_section ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
401
+ /// Checks if `#[link_section]` is applied to a function or static.
402
+ fn check_link_section ( & self , hir_id : HirId , attr : & Attribute , span : & Span , target : Target ) {
367
403
match target {
368
- Target :: Static | Target :: Fn | Target :: Method ( ..) => true ,
404
+ Target :: Static | Target :: Fn | Target :: Method ( ..) => { }
369
405
_ => {
370
- self . tcx
371
- . sess
372
- . struct_span_err (
373
- attr. span ,
374
- "attribute should be applied to a function or static" ,
375
- )
376
- . span_label ( * span, "not a function or static" )
377
- . emit ( ) ;
378
- false
406
+ // FIXME: #[link_section] was previously allowed on non-functions/statics and some
407
+ // crates used this, so only emit a warning.
408
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
409
+ lint. build ( "attribute should be applied to a function or static" )
410
+ . warn (
411
+ "this was previously accepted by the compiler but is \
412
+ being phased out; it will become a hard error in \
413
+ a future release!",
414
+ )
415
+ . span_label ( * span, "not a function or static" )
416
+ . emit ( ) ;
417
+ } ) ;
379
418
}
380
419
}
381
420
}
@@ -424,7 +463,11 @@ impl CheckAttrVisitor<'tcx> {
424
463
}
425
464
sym:: simd => {
426
465
is_simd = true ;
427
- if target != Target :: Struct { ( "a" , "struct" ) } else { continue }
466
+ if target != Target :: Struct {
467
+ ( "a" , "struct" )
468
+ } else {
469
+ continue ;
470
+ }
428
471
}
429
472
sym:: transparent => {
430
473
is_transparent = true ;
@@ -461,7 +504,11 @@ impl CheckAttrVisitor<'tcx> {
461
504
| sym:: isize
462
505
| sym:: usize => {
463
506
int_reprs += 1 ;
464
- if target != Target :: Enum { ( "an" , "enum" ) } else { continue }
507
+ if target != Target :: Enum {
508
+ ( "an" , "enum" )
509
+ } else {
510
+ continue ;
511
+ }
465
512
}
466
513
_ => continue ,
467
514
} ;
0 commit comments