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.
This commit is contained in:
Steven Fackler 2014-05-22 22:29:13 -07:00
parent 24f98c6d7a
commit 864c5016ae
19 changed files with 102 additions and 64 deletions

View File

@ -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"]

View File

@ -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"]

View File

@ -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]
~~~

View File

@ -716,6 +716,45 @@ fn print_flowgraph<W:io::Writer>(analysis: CrateAnalysis,
pub fn collect_crate_types(session: &Session,
attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
// Unconditionally collect crate types from attributes to make them used
let attr_types: Vec<config::CrateType> = 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);
}

View File

@ -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))
}

View File

@ -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);
}
}

View File

@ -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");
}

View File

@ -314,9 +314,9 @@ impl Clean<Attribute> 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<InternedString> {
match **self {
match *self {
NameValue(_, ref v) => {
Some(token::intern_and_get_ident(v.as_slice()))
}

View File

@ -350,9 +350,9 @@ pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
// 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<AM: AttrMetaMethods, It: Iterator<AM>>
}
} else {
false
}
};
matches || this_matches
});
debug!("test_cfg (no_cfgs={}, some_cfg_matches={})", no_cfgs, some_cfg_matches);
no_cfgs || some_cfg_matches

View File

@ -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

View File

@ -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() {}

View File

@ -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

View File

@ -7,6 +7,7 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_attribute)]
#[foo(bar)]
mod foo {

View File

@ -9,8 +9,6 @@
// except according to those terms.
// ignore-win32 FIXME #13259
#![no_uv]
extern crate native;
use std::os;

View File

@ -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,

View File

@ -7,6 +7,7 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_attribute)]
struct cat {
name: StrBuf,

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() { }

View File

@ -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]

View File

@ -9,6 +9,7 @@
// except according to those terms.
// pp-exact - Make sure we print all the attributes
#![allow(unused_attribute)]
#[frobable]
trait frobable {