From 6ff697d3933754bf9ec5ee5875f487f02a7d087d Mon Sep 17 00:00:00 2001 From: klutzy Date: Tue, 5 Nov 2013 00:35:56 +0900 Subject: [PATCH 1/8] rustc: Add lint for misplaced crate attributes --- src/etc/extract-tests.py | 1 + src/librustc/middle/lint.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/etc/extract-tests.py b/src/etc/extract-tests.py index 736292337adcb..5904e10a08dba 100644 --- a/src/etc/extract-tests.py +++ b/src/etc/extract-tests.py @@ -63,6 +63,7 @@ #[ allow(unused_variable) ];\n #[ allow(dead_assignment) ];\n #[ allow(unused_mut) ];\n +#[ allow(attribute_usage) ];\n #[ feature(macro_rules, globs, struct_variant, managed_boxes) ];\n """ + block if xfail: diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 473b7025cbf95..7ce560055a33c 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -76,6 +76,7 @@ pub enum lint { type_overflow, unused_unsafe, unsafe_block, + attribute_usage, managed_heap_memory, owned_heap_memory, @@ -244,6 +245,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ default: allow }), + ("attribute_usage", + LintSpec { + lint: attribute_usage, + desc: "detects bad use of attributes", + default: warn + }), + ("unused_variable", LintSpec { lint: unused_variable, @@ -790,6 +798,27 @@ fn check_heap_item(cx: &Context, it: &ast::item) { } } +// check if crate-level attribute is used on item, +// since it is usually caused by mistake of semicolon omission. +// also make error on obsolete attributes for less confusion. +fn check_item_attribute_usage(cx: &Context, it: &ast::item) { + let crate_attrs = ["crate_type", "link", "feature", "no_uv", "no_main", "no_std"]; + + for attr in it.attrs.iter() { + let name = attr.node.value.name(); + for crate_attr in crate_attrs.iter() { + if name.equiv(crate_attr) { + let msg = match attr.node.style { + ast::AttrOuter => "crate-level attribute should be an inner attribute: \ + add semicolon at end", + ast::AttrInner => "crate-level attribute should be in the root module", + }; + cx.span_lint(attribute_usage, attr.span, msg); + } + } + } +} + fn check_heap_expr(cx: &Context, e: &ast::Expr) { let ty = ty::expr_ty(cx.tcx, e); check_heap_type(cx, e.span, ty); @@ -1110,6 +1139,7 @@ impl<'self> Visitor<()> for Context<'self> { check_item_non_uppercase_statics(cx, it); check_heap_item(cx, it); check_missing_doc_item(cx, it); + check_item_attribute_usage(cx, it); do cx.visit_ids |v| { v.visit_item(it, ()); From 1f7bfac9d28340b3eda0291dd01b7914c77a88ae Mon Sep 17 00:00:00 2001 From: klutzy Date: Wed, 6 Nov 2013 12:16:19 +0900 Subject: [PATCH 2/8] rustc: Add lint for obsolete attributes This also moves `#[auto_{en,de}code]` checker from syntax to lint. --- src/librustc/middle/lint.rs | 12 +++++++ src/libstd/io/native/process.rs | 1 - src/libsyntax/ext/auto_encode.rs | 35 ------------------- src/libsyntax/ext/base.rs | 8 +---- src/libsyntax/lib.rs | 1 - src/test/compile-fail/deprecated-auto-code.rs | 15 -------- 6 files changed, 13 insertions(+), 59 deletions(-) delete mode 100644 src/libsyntax/ext/auto_encode.rs delete mode 100644 src/test/compile-fail/deprecated-auto-code.rs diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 7ce560055a33c..bbb835c2032ec 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -803,6 +803,11 @@ fn check_heap_item(cx: &Context, it: &ast::item) { // also make error on obsolete attributes for less confusion. fn check_item_attribute_usage(cx: &Context, it: &ast::item) { let crate_attrs = ["crate_type", "link", "feature", "no_uv", "no_main", "no_std"]; + let obsolete_attrs = [ + ("abi", "extern \"abi\" fn"), + ("auto_encode", "#[deriving(Encodable)]"), + ("auto_decode", "#[deriving(Decodable)]"), + ]; for attr in it.attrs.iter() { let name = attr.node.value.name(); @@ -816,6 +821,13 @@ fn check_item_attribute_usage(cx: &Context, it: &ast::item) { cx.span_lint(attribute_usage, attr.span, msg); } } + + for &(obs_attr, obs_alter) in obsolete_attrs.iter() { + if name.equiv(&obs_attr) { + cx.span_lint(attribute_usage, attr.span, + format!("obsolete attribute: use `{:s}` instead", obs_alter)); + } + } } } diff --git a/src/libstd/io/native/process.rs b/src/libstd/io/native/process.rs index 6aa3ae65fc985..292b0a2e78f2b 100644 --- a/src/libstd/io/native/process.rs +++ b/src/libstd/io/native/process.rs @@ -365,7 +365,6 @@ fn spawn_process_os(prog: &str, args: &[~str], use libc::funcs::bsd44::getdtablesize; mod rustrt { - #[abi = "cdecl"] extern { pub fn rust_unset_sigprocmask(); } diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs deleted file mode 100644 index c1e7ba60fade4..0000000000000 --- a/src/libsyntax/ext/auto_encode.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 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. - -/// Deprecated #[auto_encode] and #[auto_decode] syntax extensions - -use ast; -use codemap::Span; -use ext::base::*; - -pub fn expand_auto_encode( - cx: @ExtCtxt, - span: Span, - _mitem: @ast::MetaItem, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - cx.span_err(span, "`#[auto_encode]` is deprecated, use `#[deriving(Encodable)]` instead"); - in_items -} - -pub fn expand_auto_decode( - cx: @ExtCtxt, - span: Span, - _mitem: @ast::MetaItem, - in_items: ~[@ast::item] -) -> ~[@ast::item] { - cx.span_err(span, "`#[auto_decode]` is deprecated, use `#[deriving(Decodable)]` instead"); - in_items -} diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 448f8ee88f90a..ccb88e0c9c019 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -143,7 +143,7 @@ pub enum MacResult { } pub enum SyntaxExtension { - // #[auto_encode] and such + // #[deriving] and such ItemDecorator(ItemDecorator), // Token-tree expanders @@ -229,12 +229,6 @@ pub fn syntax_expander_table() -> SyntaxEnv { syntax_expanders.insert(intern(&"format_args"), builtin_normal_tt_no_ctxt( ext::format::expand_args)); - syntax_expanders.insert( - intern(&"auto_encode"), - @SE(ItemDecorator(ext::auto_encode::expand_auto_encode))); - syntax_expanders.insert( - intern(&"auto_decode"), - @SE(ItemDecorator(ext::auto_encode::expand_auto_decode))); syntax_expanders.insert(intern(&"env"), builtin_normal_tt_no_ctxt( ext::env::expand_env)); diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 247be194b90fe..29ed87f220283 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -83,7 +83,6 @@ pub mod ext { pub mod concat; pub mod concat_idents; pub mod log_syntax; - pub mod auto_encode; pub mod source_util; pub mod trace_macros; diff --git a/src/test/compile-fail/deprecated-auto-code.rs b/src/test/compile-fail/deprecated-auto-code.rs deleted file mode 100644 index e4576e0f57c54..0000000000000 --- a/src/test/compile-fail/deprecated-auto-code.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 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_encode] //~ ERROR: `#[auto_encode]` is deprecated -#[auto_decode] //~ ERROR: `#[auto_decode]` is deprecated -struct A; - -fn main() {} From 87b166d94a16d3b7e32ba53d0cec7a5d3fd776ba Mon Sep 17 00:00:00 2001 From: klutzy Date: Wed, 6 Nov 2013 12:16:47 +0900 Subject: [PATCH 3/8] std: Remove unused attributes This also enables two tests properly. --- src/libstd/cell.rs | 2 -- src/libstd/vec.rs | 4 ++-- src/test/run-pass/ifmt.rs | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index 019cd53be55bc..e49cf3e5303b3 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -10,8 +10,6 @@ //! Types dealing with dynamic mutability -#[missing_doc]; - use prelude::*; use cast; use util::NonCopyable; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 5cc344fdfc1ab..7e797cec03fad 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2704,7 +2704,7 @@ mod tests { assert_eq!(a.init(), &[11]); } - #[init] + #[test] #[should_fail] fn test_init_empty() { let a: ~[int] = ~[]; @@ -2719,7 +2719,7 @@ mod tests { assert_eq!(a.initn(2), &[11]); } - #[init] + #[test] #[should_fail] fn test_initn_empty() { let a: ~[int] = ~[]; diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 04958936fbe2d..f39bb8fef0cf8 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -23,7 +23,6 @@ use std::str; struct A; struct B; -#[fmt="foo"] impl fmt::Signed for A { fn fmt(_: &A, f: &mut fmt::Formatter) { f.buf.write("aloha".as_bytes()); } } From 365c44cb2d7dc224af68cf870bd263d753a0690c Mon Sep 17 00:00:00 2001 From: klutzy Date: Wed, 6 Nov 2013 15:30:19 +0900 Subject: [PATCH 4/8] Add tests for attribute lint --- src/test/compile-fail/lint-misplaced-attr.rs | 20 ++++++++++++++++++++ src/test/compile-fail/lint-obsolete-attr.rs | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/test/compile-fail/lint-misplaced-attr.rs create mode 100644 src/test/compile-fail/lint-obsolete-attr.rs diff --git a/src/test/compile-fail/lint-misplaced-attr.rs b/src/test/compile-fail/lint-misplaced-attr.rs new file mode 100644 index 0000000000000..64b3a52848b1e --- /dev/null +++ b/src/test/compile-fail/lint-misplaced-attr.rs @@ -0,0 +1,20 @@ +// Copyright 2013 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. + +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. + +#[deny(attribute_usage)]; + +mod a { + #[crate_type = "bin"]; //~ ERROR: crate-level attribute +} + +#[crate_type = "bin"] fn main() {} //~ ERROR: crate-level attribute diff --git a/src/test/compile-fail/lint-obsolete-attr.rs b/src/test/compile-fail/lint-obsolete-attr.rs new file mode 100644 index 0000000000000..2a0ffe80ab804 --- /dev/null +++ b/src/test/compile-fail/lint-obsolete-attr.rs @@ -0,0 +1,18 @@ +// Copyright 2013 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. + +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. + +#[deny(attribute_usage)]; + +#[abi="stdcall"] extern {} //~ ERROR: obsolete attribute + +fn main() {} From 37f2f7173b93e775eafd63c4f4976b42cafa3b9a Mon Sep 17 00:00:00 2001 From: klutzy Date: Mon, 11 Nov 2013 15:21:51 +0900 Subject: [PATCH 5/8] rustc: Add lint for unknown attributes --- src/librustc/middle/lint.rs | 66 ++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index bbb835c2032ec..03563c596fb35 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -798,27 +798,51 @@ fn check_heap_item(cx: &Context, it: &ast::item) { } } -// check if crate-level attribute is used on item, -// since it is usually caused by mistake of semicolon omission. -// also make error on obsolete attributes for less confusion. -fn check_item_attribute_usage(cx: &Context, it: &ast::item) { - let crate_attrs = ["crate_type", "link", "feature", "no_uv", "no_main", "no_std"]; +fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { + // check if element has crate-level, obsolete, or any unknown attributes. + + let crate_attrs = [ + "crate_type", "link", "feature", "no_uv", "no_main", "no_std", + "comment", "license", "copyright", // not used in rustc now + ]; + let obsolete_attrs = [ ("abi", "extern \"abi\" fn"), ("auto_encode", "#[deriving(Encodable)]"), ("auto_decode", "#[deriving(Decodable)]"), ]; - for attr in it.attrs.iter() { + let other_attrs = [ + // item-level + "address_insignificant", // can be crate-level too + "allow", "deny", "forbid", "warn", // lint options + "deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability + "crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze", + "no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", + "packed", "simd", "repr", "deriving", "unsafe_destructor", + + // mod-level + "path", "link_name", "link_args", "nolink", "macro_escape", "no_implicit_prelude", + + // fn-level + "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start", + "fixed_stack_segment", "no_split_stack", "rust_stack", "cold", + + // internal attribute: bypass privacy inside items + "!resolve_unexported", + ]; + + for attr in attrs.iter() { let name = attr.node.value.name(); for crate_attr in crate_attrs.iter() { if name.equiv(crate_attr) { let msg = match attr.node.style { - ast::AttrOuter => "crate-level attribute should be an inner attribute: \ - add semicolon at end", + ast::AttrOuter => "crate-level attribute should be an inner attribute: \ + add semicolon at end", ast::AttrInner => "crate-level attribute should be in the root module", }; cx.span_lint(attribute_usage, attr.span, msg); + return; } } @@ -826,8 +850,13 @@ fn check_item_attribute_usage(cx: &Context, it: &ast::item) { if name.equiv(&obs_attr) { cx.span_lint(attribute_usage, attr.span, format!("obsolete attribute: use `{:s}` instead", obs_alter)); + return; } } + + if !other_attrs.iter().any(|other_attr| { name.equiv(other_attr) }) { + cx.span_lint(attribute_usage, attr.span, "unknown attribute"); + } } } @@ -1151,7 +1180,7 @@ impl<'self> Visitor<()> for Context<'self> { check_item_non_uppercase_statics(cx, it); check_heap_item(cx, it); check_missing_doc_item(cx, it); - check_item_attribute_usage(cx, it); + check_attrs_usage(cx, it.attrs); do cx.visit_ids |v| { v.visit_item(it, ()); @@ -1161,6 +1190,20 @@ impl<'self> Visitor<()> for Context<'self> { } } + fn visit_foreign_item(&mut self, it: @ast::foreign_item, _: ()) { + do self.with_lint_attrs(it.attrs) |cx| { + check_attrs_usage(cx, it.attrs); + visit::walk_foreign_item(cx, it, ()); + } + } + + fn visit_view_item(&mut self, i: &ast::view_item, _: ()) { + do self.with_lint_attrs(i.attrs) |cx| { + check_attrs_usage(cx, i.attrs); + visit::walk_view_item(cx, i, ()); + } + } + fn visit_pat(&mut self, p: &ast::Pat, _: ()) { check_pat_non_uppercase_statics(self, p); check_unused_mut_pat(self, p); @@ -1210,6 +1253,7 @@ impl<'self> Visitor<()> for Context<'self> { visit::fk_method(_, _, m) => { do self.with_lint_attrs(m.attrs) |cx| { check_missing_doc_method(cx, m); + check_attrs_usage(cx, m.attrs); do cx.visit_ids |v| { v.visit_fn(fk, decl, body, span, id, ()); @@ -1221,9 +1265,11 @@ impl<'self> Visitor<()> for Context<'self> { } } + fn visit_ty_method(&mut self, t: &ast::TypeMethod, _: ()) { do self.with_lint_attrs(t.attrs) |cx| { check_missing_doc_ty_method(cx, t); + check_attrs_usage(cx, t.attrs); visit::walk_ty_method(cx, t, ()); } @@ -1244,6 +1290,7 @@ impl<'self> Visitor<()> for Context<'self> { fn visit_struct_field(&mut self, s: @ast::struct_field, _: ()) { do self.with_lint_attrs(s.node.attrs) |cx| { check_missing_doc_struct_field(cx, s); + check_attrs_usage(cx, s.node.attrs); visit::walk_struct_field(cx, s, ()); } @@ -1252,6 +1299,7 @@ impl<'self> Visitor<()> for Context<'self> { fn visit_variant(&mut self, v: &ast::variant, g: &ast::Generics, _: ()) { do self.with_lint_attrs(v.node.attrs) |cx| { check_missing_doc_variant(cx, v); + check_attrs_usage(cx, v.node.attrs); visit::walk_variant(cx, v, g, ()); } From b4ad3363f3ce5facdaac7384892319914f119177 Mon Sep 17 00:00:00 2001 From: klutzy Date: Mon, 11 Nov 2013 17:51:27 +0900 Subject: [PATCH 6/8] Add test for unknown attribute lint --- src/test/compile-fail/lint-unknown-attr.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/compile-fail/lint-unknown-attr.rs diff --git a/src/test/compile-fail/lint-unknown-attr.rs b/src/test/compile-fail/lint-unknown-attr.rs new file mode 100644 index 0000000000000..2ec7706addfed --- /dev/null +++ b/src/test/compile-fail/lint-unknown-attr.rs @@ -0,0 +1,18 @@ +// Copyright 2013 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. + +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. + +#[deny(attribute_usage)]; + +#[dance] mod a {} //~ ERROR: unknown attribute + +#[dance] fn main() {} //~ ERROR: unknown attribute From 9432e2a25dc5f3a71aa4f95a9dd6ba17198c79bd Mon Sep 17 00:00:00 2001 From: klutzy Date: Mon, 25 Nov 2013 23:17:01 +0900 Subject: [PATCH 7/8] rustc: Update obsolete attribute list --- src/librustc/middle/lint.rs | 13 ++++++++----- src/librustpkg/path_util.rs | 2 -- src/test/compile-fail/cast-to-bare-fn.rs | 1 - src/test/compile-fail/lint-obsolete-attr.rs | 2 ++ 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 03563c596fb35..42dbe3f6d9ecb 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -807,9 +807,12 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { ]; let obsolete_attrs = [ - ("abi", "extern \"abi\" fn"), - ("auto_encode", "#[deriving(Encodable)]"), - ("auto_decode", "#[deriving(Decodable)]"), + ("abi", "Use `extern \"abi\" fn` instead"), + ("auto_encode", "Use `#[deriving(Encodable)]` instead"), + ("auto_decode", "Use `#[deriving(Decodable)]` instead"), + ("fast_ffi", "Remove it"), + ("fixed_stack_segment", "Remove it"), + ("rust_stack", "Remove it"), ]; let other_attrs = [ @@ -826,7 +829,7 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { // fn-level "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start", - "fixed_stack_segment", "no_split_stack", "rust_stack", "cold", + "no_split_stack", "cold", // internal attribute: bypass privacy inside items "!resolve_unexported", @@ -849,7 +852,7 @@ fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { for &(obs_attr, obs_alter) in obsolete_attrs.iter() { if name.equiv(&obs_attr) { cx.span_lint(attribute_usage, attr.span, - format!("obsolete attribute: use `{:s}` instead", obs_alter)); + format!("obsolete attribute: {:s}", obs_alter)); return; } } diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index 921005fdaab57..bce41e5a49fe0 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -461,7 +461,6 @@ pub fn versionize(p: &Path, v: &Version) -> Path { } #[cfg(target_os = "win32")] -#[fixed_stack_segment] pub fn chmod_read_only(p: &Path) -> bool { unsafe { do p.with_c_str |src_buf| { @@ -471,7 +470,6 @@ pub fn chmod_read_only(p: &Path) -> bool { } #[cfg(not(target_os = "win32"))] -#[fixed_stack_segment] pub fn chmod_read_only(p: &Path) -> bool { unsafe { do p.with_c_str |src_buf| { diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs index 8d75c66cb8274..10a829fd79455 100644 --- a/src/test/compile-fail/cast-to-bare-fn.rs +++ b/src/test/compile-fail/cast-to-bare-fn.rs @@ -10,7 +10,6 @@ fn foo(_x: int) { } -#[fixed_stack_segment] fn main() { let v: u64 = 5; let x = foo as extern "C" fn() -> int; diff --git a/src/test/compile-fail/lint-obsolete-attr.rs b/src/test/compile-fail/lint-obsolete-attr.rs index 2a0ffe80ab804..919769783152d 100644 --- a/src/test/compile-fail/lint-obsolete-attr.rs +++ b/src/test/compile-fail/lint-obsolete-attr.rs @@ -15,4 +15,6 @@ #[abi="stdcall"] extern {} //~ ERROR: obsolete attribute +#[fixed_stack_segment] fn f() {} //~ ERROR: obsolete attribute + fn main() {} From fa2077af990dbcd71c0e5682ae9207c71485d384 Mon Sep 17 00:00:00 2001 From: klutzy Date: Tue, 26 Nov 2013 00:22:40 +0900 Subject: [PATCH 8/8] rustc: Add crate-level attribute lint --- src/librustc/middle/lint.rs | 83 +++++++++++++--------- src/test/compile-fail/lint-unknown-attr.rs | 2 + 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 42dbe3f6d9ecb..d67677f07835b 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -798,43 +798,55 @@ fn check_heap_item(cx: &Context, it: &ast::item) { } } +static crate_attrs: &'static [&'static str] = &[ + "crate_type", "link", "feature", "no_uv", "no_main", "no_std", + "desc", "comment", "license", "copyright", // not used in rustc now +]; + + +static obsolete_attrs: &'static [(&'static str, &'static str)] = &[ + ("abi", "Use `extern \"abi\" fn` instead"), + ("auto_encode", "Use `#[deriving(Encodable)]` instead"), + ("auto_decode", "Use `#[deriving(Decodable)]` instead"), + ("fast_ffi", "Remove it"), + ("fixed_stack_segment", "Remove it"), + ("rust_stack", "Remove it"), +]; + +static other_attrs: &'static [&'static str] = &[ + // item-level + "address_insignificant", // can be crate-level too + "allow", "deny", "forbid", "warn", // lint options + "deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability + "crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze", + "no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", + "packed", "simd", "repr", "deriving", "unsafe_destructor", + + //mod-level + "path", "link_name", "link_args", "nolink", "macro_escape", "no_implicit_prelude", + + // fn-level + "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start", + "no_split_stack", "cold", + + // internal attribute: bypass privacy inside items + "!resolve_unexported", +]; + +fn check_crate_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { + + for attr in attrs.iter() { + let name = attr.node.value.name(); + let mut iter = crate_attrs.iter().chain(other_attrs.iter()); + if !iter.any(|other_attr| { name.equiv(other_attr) }) { + cx.span_lint(attribute_usage, attr.span, "unknown crate attribute"); + } + } +} + fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { // check if element has crate-level, obsolete, or any unknown attributes. - let crate_attrs = [ - "crate_type", "link", "feature", "no_uv", "no_main", "no_std", - "comment", "license", "copyright", // not used in rustc now - ]; - - let obsolete_attrs = [ - ("abi", "Use `extern \"abi\" fn` instead"), - ("auto_encode", "Use `#[deriving(Encodable)]` instead"), - ("auto_decode", "Use `#[deriving(Decodable)]` instead"), - ("fast_ffi", "Remove it"), - ("fixed_stack_segment", "Remove it"), - ("rust_stack", "Remove it"), - ]; - - let other_attrs = [ - // item-level - "address_insignificant", // can be crate-level too - "allow", "deny", "forbid", "warn", // lint options - "deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability - "crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze", - "no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", - "packed", "simd", "repr", "deriving", "unsafe_destructor", - - // mod-level - "path", "link_name", "link_args", "nolink", "macro_escape", "no_implicit_prelude", - - // fn-level - "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start", - "no_split_stack", "cold", - - // internal attribute: bypass privacy inside items - "!resolve_unexported", - ]; - for attr in attrs.iter() { let name = attr.node.value.name(); for crate_attr in crate_attrs.iter() { @@ -1349,6 +1361,9 @@ pub fn check_crate(tcx: ty::ctxt, v.visited_outermost = true; visit::walk_crate(v, crate, ()); } + + check_crate_attrs_usage(cx, crate.attrs); + visit::walk_crate(cx, crate, ()); } diff --git a/src/test/compile-fail/lint-unknown-attr.rs b/src/test/compile-fail/lint-unknown-attr.rs index 2ec7706addfed..ce83ba464c06e 100644 --- a/src/test/compile-fail/lint-unknown-attr.rs +++ b/src/test/compile-fail/lint-unknown-attr.rs @@ -13,6 +13,8 @@ #[deny(attribute_usage)]; +#[mutable_doc]; //~ ERROR: unknown crate attribute + #[dance] mod a {} //~ ERROR: unknown attribute #[dance] fn main() {} //~ ERROR: unknown attribute