the behavior of the compiler.
~~~~ {.rust}
+# #![allow(unused_attribute)]
// Crate ID
#![crate_id = "projx#2.5"]
comments":
~~~
+# #![allow(unused_attribute)]
// the "link" crate attribute is currently required for rustdoc, but normally
// isn't needed.
#![crate_id = "universe"]
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"]
or setting the crate type (library or executable) explicitly:
~~~~
+# #![allow(unused_attribute)]
// `lib.rs`
// ...
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"]
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]
~~~
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 {
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);
}
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))
}
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);
}
}
LintSpec {
lint: UnusedAttribute,
desc: "detects attributes that were not used by the compiler",
- default: Allow
+ default: Warn
}),
("unused_variable",
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");
}
}
// 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())
}
}
fn value_str(&self) -> Option<InternedString> {
- match **self {
+ match *self {
NameValue(_, ref v) => {
Some(token::intern_and_get_ident(v.as_slice()))
}
// 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.
}
} else {
false
- }
+ };
+ matches || this_matches
});
debug!("test_cfg (no_cfgs={}, some_cfg_matches={})", no_cfgs, some_cfg_matches);
no_cfgs || some_cfg_matches
// 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
// 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() {}
// 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
// <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 {
// except according to those terms.
// ignore-win32 FIXME #13259
-#![no_uv]
-
extern crate native;
use std::os;
// except according to those terms.
// pp-exact - Make sure we actually print the attributes
+#![allow(unused_attribute)]
struct cat {
name: StrBuf,
// <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,
+++ /dev/null
-// 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() { }
// 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]
// except according to those terms.
// pp-exact - Make sure we print all the attributes
+#![allow(unused_attribute)]
#[frobable]
trait frobable {