From 864c5016ae5492da8130bf3c1c2d5ef04b66efa7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 22 May 2014 22:29:13 -0700 Subject: [PATCH] Get "make check" to work with unused-attribute There's a fair number of attributes that have to be whitelisted since they're either looked for by rustdoc, in trans, or as needed. These can be cleaned up in the future. --- src/doc/rust.md | 1 + src/doc/rustdoc.md | 1 + src/doc/tutorial.md | 5 ++ src/librustc/driver/driver.rs | 78 ++++++++++---------- src/librustc/front/test.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/lint.rs | 32 +++++++- src/librustdoc/clean.rs | 6 +- src/libsyntax/attr.rs | 7 +- src/test/compile-fail/lint-misplaced-attr.rs | 3 + src/test/compile-fail/lint-obsolete-attr.rs | 3 + src/test/compile-fail/lint-unknown-attr.rs | 4 + src/test/run-pass/attr-mix-new.rs | 1 + src/test/run-pass/backtrace.rs | 2 - src/test/run-pass/class-attributes-1.rs | 1 + src/test/run-pass/class-attributes-2.rs | 1 + src/test/run-pass/issue-3250.rs | 15 ---- src/test/run-pass/item-attributes.rs | 1 + src/test/run-pass/method-attributes.rs | 1 + 19 files changed, 102 insertions(+), 64 deletions(-) delete mode 100644 src/test/run-pass/issue-3250.rs diff --git a/src/doc/rust.md b/src/doc/rust.md index d686a02b2fe6..b8fa4075e7a7 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -661,6 +661,7 @@ Attributes on the anonymous crate module define important metadata that influenc the behavior of the compiler. ~~~~ {.rust} +# #![allow(unused_attribute)] // Crate ID #![crate_id = "projx#2.5"] diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index d6cb782bd83b..af9cff7be67b 100644 --- a/src/doc/rustdoc.md +++ b/src/doc/rustdoc.md @@ -11,6 +11,7 @@ Documenting Rust APIs is quite simple. To document a given item, we have "doc comments": ~~~ +# #![allow(unused_attribute)] // the "link" crate attribute is currently required for rustdoc, but normally // isn't needed. #![crate_id = "universe"] diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index da78869d9fa8..d85734508bc1 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -3166,6 +3166,7 @@ without conflict. Therefore, if you plan to compile your crate as a library, you should annotate it with that information: ~~~~ +# #![allow(unused_attribute)] // `lib.rs` # #![crate_type = "lib"] @@ -3189,6 +3190,7 @@ Other crate settings and metadata include things like enabling/disabling certain or setting the crate type (library or executable) explicitly: ~~~~ +# #![allow(unused_attribute)] // `lib.rs` // ... @@ -3208,6 +3210,7 @@ Now for something that you can actually compile yourself. We define two crates, and use one of them as a library in the other. ~~~~ +# #![allow(unused_attribute)] // `world.rs` #![crate_id = "world#0.42"] @@ -3282,11 +3285,13 @@ fn main() { Both auto-insertions can be disabled with an attribute if necessary: ~~~ +# #![allow(unused_attribute)] // In the crate root: #![no_std] ~~~ ~~~ +# #![allow(unused_attribute)] // In any module: #![no_implicit_prelude] ~~~ diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4e682e8e34bb..ee9b10a80590 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -716,6 +716,45 @@ fn print_flowgraph(analysis: CrateAnalysis, pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { + // Unconditionally collect crate types from attributes to make them used + let attr_types: Vec = attrs.iter().filter_map(|a| { + if a.check_name("crate_type") { + match a.value_str() { + Some(ref n) if n.equiv(&("rlib")) => { + Some(config::CrateTypeRlib) + } + Some(ref n) if n.equiv(&("dylib")) => { + Some(config::CrateTypeDylib) + } + Some(ref n) if n.equiv(&("lib")) => { + Some(config::default_lib_output()) + } + Some(ref n) if n.equiv(&("staticlib")) => { + Some(config::CrateTypeStaticlib) + } + Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable), + Some(_) => { + session.add_lint(lint::UnknownCrateType, + ast::CRATE_NODE_ID, + a.span, + "invalid `crate_type` \ + value".to_strbuf()); + None + } + _ => { + session.add_lint(lint::UnknownCrateType, + ast::CRATE_NODE_ID, + a.span, + "`crate_type` requires a \ + value".to_strbuf()); + None + } + } + } else { + None + } + }).collect(); + // If we're generating a test executable, then ignore all other output // styles at all other locations if session.opts.test { @@ -729,44 +768,7 @@ pub fn collect_crate_types(session: &Session, if base.len() > 0 { return base } else { - let iter = attrs.iter().filter_map(|a| { - if a.name().equiv(&("crate_type")) { - match a.value_str() { - Some(ref n) if n.equiv(&("rlib")) => { - Some(config::CrateTypeRlib) - } - Some(ref n) if n.equiv(&("dylib")) => { - Some(config::CrateTypeDylib) - } - Some(ref n) if n.equiv(&("lib")) => { - Some(config::default_lib_output()) - } - Some(ref n) if n.equiv(&("staticlib")) => { - Some(config::CrateTypeStaticlib) - } - Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable), - Some(_) => { - session.add_lint(lint::UnknownCrateType, - ast::CRATE_NODE_ID, - a.span, - "invalid `crate_type` \ - value".to_strbuf()); - None - } - _ => { - session.add_lint(lint::UnknownCrateType, - ast::CRATE_NODE_ID, - a.span, - "`crate_type` requires a \ - value".to_strbuf()); - None - } - } - } else { - None - } - }); - base.extend(iter); + base.extend(attr_types.move_iter()); if base.len() == 0 { base.push(config::CrateTypeExecutable); } diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index d5e9192cd749..679444238085 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -253,7 +253,7 @@ fn is_bench_fn(cx: &TestCtxt, i: @ast::Item) -> bool { fn is_ignored(cx: &TestCtxt, i: @ast::Item) -> bool { i.attrs.iter().any(|attr| { // check ignore(cfg(foo, bar)) - attr.name().equiv(&("ignore")) && match attr.meta_item_list() { + attr.check_name("ignore") && match attr.meta_item_list() { Some(ref cfgs) => { attr::test_cfg(cx.config.as_slice(), cfgs.iter().map(|x| *x)) } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a06c6e59ea1d..2e3dc360ac29 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1447,7 +1447,7 @@ fn synthesize_crate_attrs(ecx: &EncodeContext, let mut attrs = Vec::new(); for attr in krate.attrs.iter() { - if !attr.name().equiv(&("crate_id")) { + if !attr.check_name("crate_id") { attrs.push(*attr); } } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 5315b223344c..25a0f1510904 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -293,7 +293,7 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ LintSpec { lint: UnusedAttribute, desc: "detects attributes that were not used by the compiler", - default: Allow + default: Warn }), ("unused_variable", @@ -1148,8 +1148,38 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { fn check_unused_attribute(cx: &Context, attrs: &[ast::Attribute]) { for attr in attrs.iter() { // whitelist docs since rustdoc looks at them + attr.check_name("automatically_derived"); attr.check_name("doc"); + // these are processed in trans, which happens after the lint pass + attr.check_name("address_insignificant"); + attr.check_name("cold"); + attr.check_name("inline"); + attr.check_name("link"); + attr.check_name("link_name"); + attr.check_name("link_section"); + attr.check_name("no_builtins"); + attr.check_name("no_mangle"); + attr.check_name("no_split_stack"); + attr.check_name("packed"); + attr.check_name("static_assert"); + attr.check_name("thread_local"); + + // not used anywhere (!?) but apparently we want to keep them around + attr.check_name("comment"); + attr.check_name("desc"); + attr.check_name("license"); + + // these are only looked at on-demand so we can't guarantee they'll have + // already been checked + attr.check_name("deprecated"); + attr.check_name("experimental"); + attr.check_name("frozen"); + attr.check_name("locked"); + attr.check_name("must_use"); + attr.check_name("stable"); + attr.check_name("unstable"); + if !attr::is_used(attr) { cx.span_lint(UnusedAttribute, attr.span, "unused attribute"); } diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index fb2a80333e82..6f3c6e4cd6f3 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -314,9 +314,9 @@ impl Clean for ast::Attribute { } // This is a rough approximation that gets us what we want. -impl<'a> attr::AttrMetaMethods for &'a Attribute { +impl attr::AttrMetaMethods for Attribute { fn name(&self) -> InternedString { - match **self { + match *self { Word(ref n) | List(ref n, _) | NameValue(ref n, _) => { token::intern_and_get_ident(n.as_slice()) } @@ -324,7 +324,7 @@ impl<'a> attr::AttrMetaMethods for &'a Attribute { } fn value_str(&self) -> Option { - match **self { + match *self { NameValue(_, ref v) => { Some(token::intern_and_get_ident(v.as_slice())) } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index bbd333163b59..1d43ac898f1f 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -350,9 +350,9 @@ pub fn test_cfg> // this would be much nicer as a chain of iterator adaptors, but // this doesn't work. - let some_cfg_matches = metas.any(|mi| { + let some_cfg_matches = metas.fold(false, |matches, mi| { debug!("testing name: {}", mi.name()); - if mi.check_name("cfg") { // it is a #[cfg()] attribute + let this_matches = if mi.check_name("cfg") { // it is a #[cfg()] attribute debug!("is cfg"); no_cfgs = false; // only #[cfg(...)] ones are understood. @@ -380,7 +380,8 @@ pub fn test_cfg> } } else { false - } + }; + matches || this_matches }); debug!("test_cfg (no_cfgs={}, some_cfg_matches={})", no_cfgs, some_cfg_matches); no_cfgs || some_cfg_matches diff --git a/src/test/compile-fail/lint-misplaced-attr.rs b/src/test/compile-fail/lint-misplaced-attr.rs index d422dfc513d2..f7db5c97aab1 100644 --- a/src/test/compile-fail/lint-misplaced-attr.rs +++ b/src/test/compile-fail/lint-misplaced-attr.rs @@ -12,9 +12,12 @@ // injected intrinsics by the compiler. #![deny(attribute_usage)] +#![deny(unused_attribute)] mod a { #![crate_type = "bin"] //~ ERROR: crate-level attribute + //~^ ERROR: unused attribute } #[crate_type = "bin"] fn main() {} //~ ERROR: crate-level attribute + //~^ ERROR: unused attribute diff --git a/src/test/compile-fail/lint-obsolete-attr.rs b/src/test/compile-fail/lint-obsolete-attr.rs index 8b70953146da..32058737ed30 100644 --- a/src/test/compile-fail/lint-obsolete-attr.rs +++ b/src/test/compile-fail/lint-obsolete-attr.rs @@ -12,10 +12,13 @@ // injected intrinsics by the compiler. #![deny(attribute_usage)] +#![deny(unused_attribute)] #![allow(dead_code)] #[abi="stdcall"] extern {} //~ ERROR: obsolete attribute + //~^ ERROR: unused attribute #[fixed_stack_segment] fn f() {} //~ ERROR: obsolete attribute + //~^ ERROR: unused attribute fn main() {} diff --git a/src/test/compile-fail/lint-unknown-attr.rs b/src/test/compile-fail/lint-unknown-attr.rs index dbbf91f725dc..32c0722d1ac2 100644 --- a/src/test/compile-fail/lint-unknown-attr.rs +++ b/src/test/compile-fail/lint-unknown-attr.rs @@ -12,9 +12,13 @@ // injected intrinsics by the compiler. #![deny(attribute_usage)] +#![deny(unused_attribute)] #![mutable_doc] //~ ERROR: unknown crate attribute + //~^ ERROR: unused attribute #[dance] mod a {} //~ ERROR: unknown attribute + //~^ ERROR: unused attribute #[dance] fn main() {} //~ ERROR: unknown attribute + //~^ ERROR: unused attribute diff --git a/src/test/run-pass/attr-mix-new.rs b/src/test/run-pass/attr-mix-new.rs index af615912f282..55ca75b4b713 100644 --- a/src/test/run-pass/attr-mix-new.rs +++ b/src/test/run-pass/attr-mix-new.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attribute)] #[foo(bar)] mod foo { diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 7f2c9e14af10..cf6126a37fa8 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -9,8 +9,6 @@ // except according to those terms. // ignore-win32 FIXME #13259 -#![no_uv] - extern crate native; use std::os; diff --git a/src/test/run-pass/class-attributes-1.rs b/src/test/run-pass/class-attributes-1.rs index 55cf41d73d59..186fec45c4bb 100644 --- a/src/test/run-pass/class-attributes-1.rs +++ b/src/test/run-pass/class-attributes-1.rs @@ -9,6 +9,7 @@ // except according to those terms. // pp-exact - Make sure we actually print the attributes +#![allow(unused_attribute)] struct cat { name: StrBuf, diff --git a/src/test/run-pass/class-attributes-2.rs b/src/test/run-pass/class-attributes-2.rs index b1ed70278ef3..6da8123c8c49 100644 --- a/src/test/run-pass/class-attributes-2.rs +++ b/src/test/run-pass/class-attributes-2.rs @@ -7,6 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_attribute)] struct cat { name: StrBuf, diff --git a/src/test/run-pass/issue-3250.rs b/src/test/run-pass/issue-3250.rs deleted file mode 100644 index 255f6b1635c1..000000000000 --- a/src/test/run-pass/issue-3250.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[auto_serialize] - -type t = (uint, uint); - -pub fn main() { } diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index ef825826ea49..bf94af601fea 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -11,6 +11,7 @@ // These are attributes of the implicit crate. Really this just needs to parse // for completeness since .rs files linked from .rc files support this // notation to specify their module's attributes +#![allow(unused_attribute)] #![attr1 = "val"] #![attr2 = "val"] #![attr3] diff --git a/src/test/run-pass/method-attributes.rs b/src/test/run-pass/method-attributes.rs index 87c43da9ebcf..c015244d520c 100644 --- a/src/test/run-pass/method-attributes.rs +++ b/src/test/run-pass/method-attributes.rs @@ -9,6 +9,7 @@ // except according to those terms. // pp-exact - Make sure we print all the attributes +#![allow(unused_attribute)] #[frobable] trait frobable {