@@ -92,7 +92,6 @@ pub enum Lint {
92
92
TypeOverflow ,
93
93
UnusedUnsafe ,
94
94
UnsafeBlock ,
95
- AttributeUsage ,
96
95
UnusedAttribute ,
97
96
UnknownFeatures ,
98
97
UnknownCrateType ,
@@ -294,13 +293,6 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
294
293
default : Allow
295
294
} ) ,
296
295
297
- ( "attribute_usage" ,
298
- LintSpec {
299
- lint : AttributeUsage ,
300
- desc : "detects bad use of attributes" ,
301
- default : Warn
302
- } ) ,
303
-
304
296
( "unused_attribute" ,
305
297
LintSpec {
306
298
lint : UnusedAttribute ,
@@ -1096,94 +1088,7 @@ fn check_raw_ptr_deriving(cx: &mut Context, item: &ast::Item) {
1096
1088
}
1097
1089
}
1098
1090
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 ) {
1187
1092
static ATTRIBUTE_WHITELIST : & ' static [ & ' static str ] = & ' static [
1188
1093
// FIXME: #14408 whitelist docs since rustdoc looks at them
1189
1094
"doc" ,
@@ -1218,15 +1123,37 @@ fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) {
1218
1123
"stable" ,
1219
1124
"unstable" ,
1220
1125
] ;
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 ;
1226
1144
}
1145
+ }
1227
1146
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) ;
1230
1157
}
1231
1158
}
1232
1159
}
@@ -1835,8 +1762,6 @@ impl<'a> Visitor<()> for Context<'a> {
1835
1762
check_item_non_uppercase_statics ( cx, it) ;
1836
1763
check_heap_item ( cx, it) ;
1837
1764
check_missing_doc_item ( cx, it) ;
1838
- check_attrs_usage ( cx, it. attrs . as_slice ( ) ) ;
1839
- check_unused_attribute ( cx, it. attrs . as_slice ( ) ) ;
1840
1765
check_raw_ptr_deriving ( cx, it) ;
1841
1766
1842
1767
cx. visit_ids ( |v| v. visit_item ( it, ( ) ) ) ;
@@ -1847,15 +1772,12 @@ impl<'a> Visitor<()> for Context<'a> {
1847
1772
1848
1773
fn visit_foreign_item ( & mut self , it : & ast:: ForeignItem , _: ( ) ) {
1849
1774
self . with_lint_attrs ( it. attrs . as_slice ( ) , |cx| {
1850
- check_attrs_usage ( cx, it. attrs . as_slice ( ) ) ;
1851
1775
visit:: walk_foreign_item ( cx, it, ( ) ) ;
1852
1776
} )
1853
1777
}
1854
1778
1855
1779
fn visit_view_item ( & mut self , i : & ast:: ViewItem , _: ( ) ) {
1856
1780
self . with_lint_attrs ( i. attrs . as_slice ( ) , |cx| {
1857
- check_attrs_usage ( cx, i. attrs . as_slice ( ) ) ;
1858
-
1859
1781
cx. visit_ids ( |v| v. visit_view_item ( i, ( ) ) ) ;
1860
1782
1861
1783
visit:: walk_view_item ( cx, i, ( ) ) ;
@@ -1937,7 +1859,6 @@ impl<'a> Visitor<()> for Context<'a> {
1937
1859
visit:: FkMethod ( ident, _, m) => {
1938
1860
self . with_lint_attrs ( m. attrs . as_slice ( ) , |cx| {
1939
1861
check_missing_doc_method ( cx, m) ;
1940
- check_attrs_usage ( cx, m. attrs . as_slice ( ) ) ;
1941
1862
1942
1863
match method_context ( cx, m) {
1943
1864
PlainImpl => check_snake_case ( cx, "method" , ident, span) ,
@@ -1962,7 +1883,6 @@ impl<'a> Visitor<()> for Context<'a> {
1962
1883
fn visit_ty_method ( & mut self , t : & ast:: TypeMethod , _: ( ) ) {
1963
1884
self . with_lint_attrs ( t. attrs . as_slice ( ) , |cx| {
1964
1885
check_missing_doc_ty_method ( cx, t) ;
1965
- check_attrs_usage ( cx, t. attrs . as_slice ( ) ) ;
1966
1886
check_snake_case ( cx, "trait method" , t. ident , t. span ) ;
1967
1887
1968
1888
visit:: walk_ty_method ( cx, t, ( ) ) ;
@@ -1986,7 +1906,6 @@ impl<'a> Visitor<()> for Context<'a> {
1986
1906
fn visit_struct_field ( & mut self , s : & ast:: StructField , _: ( ) ) {
1987
1907
self . with_lint_attrs ( s. node . attrs . as_slice ( ) , |cx| {
1988
1908
check_missing_doc_struct_field ( cx, s) ;
1989
- check_attrs_usage ( cx, s. node . attrs . as_slice ( ) ) ;
1990
1909
1991
1910
visit:: walk_struct_field ( cx, s, ( ) ) ;
1992
1911
} )
@@ -1995,14 +1914,17 @@ impl<'a> Visitor<()> for Context<'a> {
1995
1914
fn visit_variant ( & mut self , v : & ast:: Variant , g : & ast:: Generics , _: ( ) ) {
1996
1915
self . with_lint_attrs ( v. node . attrs . as_slice ( ) , |cx| {
1997
1916
check_missing_doc_variant ( cx, v) ;
1998
- check_attrs_usage ( cx, v. node . attrs . as_slice ( ) ) ;
1999
1917
2000
1918
visit:: walk_variant ( cx, v, g, ( ) ) ;
2001
1919
} )
2002
1920
}
2003
1921
2004
1922
// FIXME(#10894) should continue recursing
2005
1923
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
+ }
2006
1928
}
2007
1929
2008
1930
impl < ' a > IdVisitingOperation for Context < ' a > {
@@ -2051,10 +1973,8 @@ pub fn check_crate(tcx: &ty::ctxt,
2051
1973
visit:: walk_crate ( v, krate, ( ) ) ;
2052
1974
} ) ;
2053
1975
2054
- check_crate_attrs_usage ( cx, krate. attrs . as_slice ( ) ) ;
2055
1976
// since the root module isn't visited as an item (because it isn't an item), warn for it
2056
1977
// here.
2057
- check_unused_attribute ( cx, krate. attrs . as_slice ( ) ) ;
2058
1978
check_missing_doc_attrs ( cx,
2059
1979
None ,
2060
1980
krate. attrs . as_slice ( ) ,
0 commit comments