Skip to content

Commit 9239bb4

Browse files
committed
auto merge of #14741 : sfackler/rust/visit-attr, r=alexcrichton
The lint was missing a *lot* of cases previously.
2 parents 010d96e + 9452cd2 commit 9239bb4

File tree

10 files changed

+152
-174
lines changed

10 files changed

+152
-174
lines changed

src/librustc/middle/lang_items.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ impl<'a> LanguageItemCollector<'a> {
187187

188188
pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
189189
for attribute in attrs.iter() {
190-
match attribute.name_str_pair() {
191-
Some((ref key, ref value)) if key.equiv(&("lang")) => {
192-
return Some((*value).clone());
190+
match attribute.value_str() {
191+
Some(ref value) if attribute.check_name("lang") => {
192+
return Some(value.clone());
193193
}
194-
Some(..) | None => {}
194+
_ => {}
195195
}
196196
}
197197

src/librustc/middle/lint.rs

Lines changed: 34 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -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

20081930
impl<'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(),

src/librustdoc/clean/mod.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,17 +429,11 @@ impl attr::AttrMetaMethods for Attribute {
429429
}
430430
}
431431
fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
432-
fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
433-
None
434-
}
435432
}
436433
impl<'a> attr::AttrMetaMethods for &'a Attribute {
437434
fn name(&self) -> InternedString { (**self).name() }
438435
fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
439436
fn meta_item_list<'a>(&'a self) -> Option<&'a [@ast::MetaItem]> { None }
440-
fn name_str_pair(&self) -> Option<(InternedString, InternedString)> {
441-
None
442-
}
443437
}
444438

445439
#[deriving(Clone, Encodable, Decodable)]

src/librustdoc/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool) -> String {
205205
if lints {
206206
prog.push_str(r"
207207
#![deny(warnings)]
208-
#![allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)]
208+
#![allow(unused_variable, dead_assignment, unused_mut, unused_attribute, dead_code)]
209209
");
210210
}
211211

src/libsyntax/attr.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ pub trait AttrMetaMethods {
5353
fn value_str(&self) -> Option<InternedString>;
5454
/// Gets a list of inner meta items from a list MetaItem type.
5555
fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]>;
56-
57-
/**
58-
* If the meta item is a name-value type with a string value then returns
59-
* a tuple containing the name and string value, otherwise `None`
60-
*/
61-
fn name_str_pair(&self) -> Option<(InternedString,InternedString)>;
6256
}
6357

6458
impl AttrMetaMethods for Attribute {
@@ -76,9 +70,6 @@ impl AttrMetaMethods for Attribute {
7670
fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]> {
7771
self.node.value.meta_item_list()
7872
}
79-
fn name_str_pair(&self) -> Option<(InternedString,InternedString)> {
80-
self.meta().name_str_pair()
81-
}
8273
}
8374

8475
impl AttrMetaMethods for MetaItem {
@@ -108,10 +99,6 @@ impl AttrMetaMethods for MetaItem {
10899
_ => None
109100
}
110101
}
111-
112-
fn name_str_pair(&self) -> Option<(InternedString,InternedString)> {
113-
self.value_str().map(|s| (self.name(), s))
114-
}
115102
}
116103

117104
// Annoying, but required to get test_cfg to work
@@ -121,9 +108,6 @@ impl AttrMetaMethods for @MetaItem {
121108
fn meta_item_list<'a>(&'a self) -> Option<&'a [@MetaItem]> {
122109
(**self).meta_item_list()
123110
}
124-
fn name_str_pair(&self) -> Option<(InternedString,InternedString)> {
125-
(**self).name_str_pair()
126-
}
127111
}
128112

129113

0 commit comments

Comments
 (0)