@@ -66,22 +66,24 @@ impl CheckAttrVisitor<'tcx> {
6666 } else if self . tcx . sess . check_name ( attr, sym:: marker) {
6767 self . check_marker ( attr, span, target)
6868 } 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)
7070 } else if self . tcx . sess . check_name ( attr, sym:: track_caller) {
7171 self . check_track_caller ( & attr. span , attrs, span, target)
7272 } else if self . tcx . sess . check_name ( attr, sym:: doc) {
7373 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)
7874 } else if self . tcx . sess . check_name ( attr, sym:: no_link) {
7975 self . check_no_link ( & attr, span, target)
8076 } else if self . tcx . sess . check_name ( attr, sym:: export_name) {
8177 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)
8478 } 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+ }
8587 true
8688 } ;
8789 }
@@ -212,10 +214,31 @@ impl CheckAttrVisitor<'tcx> {
212214 }
213215
214216 /// 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 {
216224 match target {
217225 Target :: Fn
218226 | 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+ }
219242 _ => {
220243 self . tcx
221244 . sess
@@ -288,45 +311,58 @@ impl CheckAttrVisitor<'tcx> {
288311 }
289312
290313 /// 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 ) {
292315 match target {
293- Target :: Fn | Target :: Method ( ..) | Target :: ForeignFn => true ,
316+ Target :: Fn | Target :: Method ( ..) | Target :: ForeignFn => { }
294317 _ => {
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+ } ) ;
301330 }
302331 }
303332 }
304333
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!",
322348 ) ;
323- } else {
324- err. span_help ( attr. span , r#"try `#[link(name = "...")]` instead"# ) ;
325- }
326- }
327349
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+ }
330366 }
331367 }
332368
@@ -362,20 +398,23 @@ impl CheckAttrVisitor<'tcx> {
362398 }
363399 }
364400
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 ) {
367403 match target {
368- Target :: Static | Target :: Fn | Target :: Method ( ..) => true ,
404+ Target :: Static | Target :: Fn | Target :: Method ( ..) => { }
369405 _ => {
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+ } ) ;
379418 }
380419 }
381420 }
@@ -424,7 +463,11 @@ impl CheckAttrVisitor<'tcx> {
424463 }
425464 sym:: simd => {
426465 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+ }
428471 }
429472 sym:: transparent => {
430473 is_transparent = true ;
@@ -461,7 +504,11 @@ impl CheckAttrVisitor<'tcx> {
461504 | sym:: isize
462505 | sym:: usize => {
463506 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+ }
465512 }
466513 _ => continue ,
467514 } ;
0 commit comments