@@ -92,7 +92,6 @@ pub enum Lint {
9292 TypeOverflow ,
9393 UnusedUnsafe ,
9494 UnsafeBlock ,
95- AttributeUsage ,
9695 UnusedAttribute ,
9796 UnknownFeatures ,
9897 UnknownCrateType ,
@@ -294,13 +293,6 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
294293 default : Allow
295294 } ) ,
296295
297- ( "attribute_usage" ,
298- LintSpec {
299- lint : AttributeUsage ,
300- desc : "detects bad use of attributes" ,
301- default : Warn
302- } ) ,
303-
304296 ( "unused_attribute" ,
305297 LintSpec {
306298 lint : UnusedAttribute ,
@@ -1096,94 +1088,7 @@ fn check_raw_ptr_deriving(cx: &mut Context, item: &ast::Item) {
10961088 }
10971089}
10981090
1099- static crate_attrs: & ' static [ & ' static str ] = & [
1100- "crate_type" , "feature" , "no_start" , "no_main" , "no_std" , "crate_id" ,
1101- "desc" , "comment" , "license" , "copyright" , // not used in rustc now
1102- "no_builtins" ,
1103- ] ;
1104-
1105-
1106- static obsolete_attrs: & ' static [ ( & ' static str , & ' static str ) ] = & [
1107- ( "abi" , "Use `extern \" abi\" fn` instead" ) ,
1108- ( "auto_encode" , "Use `#[deriving(Encodable)]` instead" ) ,
1109- ( "auto_decode" , "Use `#[deriving(Decodable)]` instead" ) ,
1110- ( "fast_ffi" , "Remove it" ) ,
1111- ( "fixed_stack_segment" , "Remove it" ) ,
1112- ( "rust_stack" , "Remove it" ) ,
1113- ] ;
1114-
1115- static other_attrs: & ' static [ & ' static str ] = & [
1116- // item-level
1117- "address_insignificant" , // can be crate-level too
1118- "thread_local" , // for statics
1119- "allow" , "deny" , "forbid" , "warn" , // lint options
1120- "deprecated" , "experimental" , "unstable" , "stable" , "locked" , "frozen" , //item stability
1121- "cfg" , "doc" , "export_name" , "link_section" ,
1122- "no_mangle" , "static_assert" , "unsafe_no_drop_flag" , "packed" ,
1123- "simd" , "repr" , "deriving" , "unsafe_destructor" , "link" , "phase" ,
1124- "macro_export" , "must_use" , "automatically_derived" ,
1125-
1126- //mod-level
1127- "path" , "link_name" , "link_args" , "macro_escape" , "no_implicit_prelude" ,
1128-
1129- // fn-level
1130- "test" , "bench" , "should_fail" , "ignore" , "inline" , "lang" , "main" , "start" ,
1131- "no_split_stack" , "cold" , "macro_registrar" , "linkage" ,
1132-
1133- // internal attribute: bypass privacy inside items
1134- "!resolve_unexported" ,
1135- ] ;
1136-
1137- fn check_crate_attrs_usage ( cx : & Context , attrs : & [ ast:: Attribute ] ) {
1138-
1139- for attr in attrs. iter ( ) {
1140- let name = attr. node . value . name ( ) ;
1141- let mut iter = crate_attrs. iter ( ) . chain ( other_attrs. iter ( ) ) ;
1142- if !iter. any ( |other_attr| { name. equiv ( other_attr) } ) {
1143- cx. span_lint ( AttributeUsage , attr. span , "unknown crate attribute" ) ;
1144- }
1145- if name. equiv ( & ( "link" ) ) {
1146- cx. tcx . sess . span_err ( attr. span ,
1147- "obsolete crate `link` attribute" ) ;
1148- cx. tcx . sess . note ( "the link attribute has been superceded by the crate_id \
1149- attribute, which has the format `#[crate_id = \" name#version\" ]`") ;
1150- }
1151- }
1152- }
1153-
1154- fn check_attrs_usage ( cx : & Context , attrs : & [ ast:: Attribute ] ) {
1155- // check if element has crate-level, obsolete, or any unknown attributes.
1156-
1157- for attr in attrs. iter ( ) {
1158- let name = attr. node . value . name ( ) ;
1159- for crate_attr in crate_attrs. iter ( ) {
1160- if name. equiv ( crate_attr) {
1161- let msg = match attr. node . style {
1162- ast:: AttrOuter => "crate-level attribute should be an inner attribute: \
1163- add an exclamation mark: #![foo]",
1164- ast:: AttrInner => "crate-level attribute should be in the root module" ,
1165- } ;
1166- cx. span_lint ( AttributeUsage , attr. span , msg) ;
1167- return ;
1168- }
1169- }
1170-
1171- for & ( obs_attr, obs_alter) in obsolete_attrs. iter ( ) {
1172- if name. equiv ( & obs_attr) {
1173- cx. span_lint ( AttributeUsage , attr. span ,
1174- format ! ( "obsolete attribute: {:s}" ,
1175- obs_alter) . as_slice ( ) ) ;
1176- return ;
1177- }
1178- }
1179-
1180- if !other_attrs. iter ( ) . any ( |other_attr| { name. equiv ( other_attr) } ) {
1181- cx. span_lint ( AttributeUsage , attr. span , "unknown attribute" ) ;
1182- }
1183- }
1184- }
1185-
1186- fn check_unused_attribute ( cx : & Context , attrs : & [ ast:: Attribute ] ) {
1091+ fn check_unused_attribute ( cx : & Context , attr : & ast:: Attribute ) {
11871092 static ATTRIBUTE_WHITELIST : & ' static [ & ' static str ] = & ' static [
11881093 // FIXME: #14408 whitelist docs since rustdoc looks at them
11891094 "doc" ,
@@ -1218,15 +1123,37 @@ fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) {
12181123 "stable" ,
12191124 "unstable" ,
12201125 ] ;
1221- for attr in attrs. iter ( ) {
1222- for & name in ATTRIBUTE_WHITELIST . iter ( ) {
1223- if attr. check_name ( name) {
1224- break ;
1225- }
1126+
1127+ static CRATE_ATTRS : & ' static [ & ' static str ] = & ' static [
1128+ "crate_type" ,
1129+ "feature" ,
1130+ "no_start" ,
1131+ "no_main" ,
1132+ "no_std" ,
1133+ "crate_id" ,
1134+ "desc" ,
1135+ "comment" ,
1136+ "license" ,
1137+ "copyright" ,
1138+ "no_builtins" ,
1139+ ] ;
1140+
1141+ for & name in ATTRIBUTE_WHITELIST . iter ( ) {
1142+ if attr. check_name ( name) {
1143+ break ;
12261144 }
1145+ }
12271146
1228- if !attr:: is_used ( attr) {
1229- cx. span_lint ( UnusedAttribute , attr. span , "unused attribute" ) ;
1147+ if !attr:: is_used ( attr) {
1148+ cx. span_lint ( UnusedAttribute , attr. span , "unused attribute" ) ;
1149+ if CRATE_ATTRS . contains ( & attr. name ( ) . get ( ) ) {
1150+ let msg = match attr. node . style {
1151+ ast:: AttrOuter => "crate-level attribute should be an inner \
1152+ attribute: add an exclamation mark: #![foo]",
1153+ ast:: AttrInner => "crate-level attribute should be in the \
1154+ root module",
1155+ } ;
1156+ cx. span_lint ( UnusedAttribute , attr. span , msg) ;
12301157 }
12311158 }
12321159}
@@ -1835,8 +1762,6 @@ impl<'a> Visitor<()> for Context<'a> {
18351762 check_item_non_uppercase_statics ( cx, it) ;
18361763 check_heap_item ( cx, it) ;
18371764 check_missing_doc_item ( cx, it) ;
1838- check_attrs_usage ( cx, it. attrs . as_slice ( ) ) ;
1839- check_unused_attribute ( cx, it. attrs . as_slice ( ) ) ;
18401765 check_raw_ptr_deriving ( cx, it) ;
18411766
18421767 cx. visit_ids ( |v| v. visit_item ( it, ( ) ) ) ;
@@ -1847,15 +1772,12 @@ impl<'a> Visitor<()> for Context<'a> {
18471772
18481773 fn visit_foreign_item ( & mut self , it : & ast:: ForeignItem , _: ( ) ) {
18491774 self . with_lint_attrs ( it. attrs . as_slice ( ) , |cx| {
1850- check_attrs_usage ( cx, it. attrs . as_slice ( ) ) ;
18511775 visit:: walk_foreign_item ( cx, it, ( ) ) ;
18521776 } )
18531777 }
18541778
18551779 fn visit_view_item ( & mut self , i : & ast:: ViewItem , _: ( ) ) {
18561780 self . with_lint_attrs ( i. attrs . as_slice ( ) , |cx| {
1857- check_attrs_usage ( cx, i. attrs . as_slice ( ) ) ;
1858-
18591781 cx. visit_ids ( |v| v. visit_view_item ( i, ( ) ) ) ;
18601782
18611783 visit:: walk_view_item ( cx, i, ( ) ) ;
@@ -1937,7 +1859,6 @@ impl<'a> Visitor<()> for Context<'a> {
19371859 visit:: FkMethod ( ident, _, m) => {
19381860 self . with_lint_attrs ( m. attrs . as_slice ( ) , |cx| {
19391861 check_missing_doc_method ( cx, m) ;
1940- check_attrs_usage ( cx, m. attrs . as_slice ( ) ) ;
19411862
19421863 match method_context ( cx, m) {
19431864 PlainImpl => check_snake_case ( cx, "method" , ident, span) ,
@@ -1962,7 +1883,6 @@ impl<'a> Visitor<()> for Context<'a> {
19621883 fn visit_ty_method ( & mut self , t : & ast:: TypeMethod , _: ( ) ) {
19631884 self . with_lint_attrs ( t. attrs . as_slice ( ) , |cx| {
19641885 check_missing_doc_ty_method ( cx, t) ;
1965- check_attrs_usage ( cx, t. attrs . as_slice ( ) ) ;
19661886 check_snake_case ( cx, "trait method" , t. ident , t. span ) ;
19671887
19681888 visit:: walk_ty_method ( cx, t, ( ) ) ;
@@ -1986,7 +1906,6 @@ impl<'a> Visitor<()> for Context<'a> {
19861906 fn visit_struct_field ( & mut self , s : & ast:: StructField , _: ( ) ) {
19871907 self . with_lint_attrs ( s. node . attrs . as_slice ( ) , |cx| {
19881908 check_missing_doc_struct_field ( cx, s) ;
1989- check_attrs_usage ( cx, s. node . attrs . as_slice ( ) ) ;
19901909
19911910 visit:: walk_struct_field ( cx, s, ( ) ) ;
19921911 } )
@@ -1995,14 +1914,17 @@ impl<'a> Visitor<()> for Context<'a> {
19951914 fn visit_variant ( & mut self , v : & ast:: Variant , g : & ast:: Generics , _: ( ) ) {
19961915 self . with_lint_attrs ( v. node . attrs . as_slice ( ) , |cx| {
19971916 check_missing_doc_variant ( cx, v) ;
1998- check_attrs_usage ( cx, v. node . attrs . as_slice ( ) ) ;
19991917
20001918 visit:: walk_variant ( cx, v, g, ( ) ) ;
20011919 } )
20021920 }
20031921
20041922 // FIXME(#10894) should continue recursing
20051923 fn visit_ty ( & mut self , _t : & ast:: Ty , _: ( ) ) { }
1924+
1925+ fn visit_attribute ( & mut self , attr : & ast:: Attribute , _: ( ) ) {
1926+ check_unused_attribute ( self , attr) ;
1927+ }
20061928}
20071929
20081930impl < ' a > IdVisitingOperation for Context < ' a > {
@@ -2051,10 +1973,8 @@ pub fn check_crate(tcx: &ty::ctxt,
20511973 visit:: walk_crate ( v, krate, ( ) ) ;
20521974 } ) ;
20531975
2054- check_crate_attrs_usage ( cx, krate. attrs . as_slice ( ) ) ;
20551976 // since the root module isn't visited as an item (because it isn't an item), warn for it
20561977 // here.
2057- check_unused_attribute ( cx, krate. attrs . as_slice ( ) ) ;
20581978 check_missing_doc_attrs ( cx,
20591979 None ,
20601980 krate. attrs . as_slice ( ) ,
0 commit comments