Skip to content

syntax: Add enum for defined attributes #10937

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ mod test {
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
let cfg = build_configuration(sess);
assert!((attr::contains_name(cfg, "test")));
assert!((attr::contains_attr(cfg, attr::AttrTest)));
}

// When the user supplies --test and --cfg test, don't implicitly add
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ pub fn building_library(options: &options, crate: &ast::Crate) -> bool {
}
}
if options.test { return false }
match syntax::attr::first_attr_value_str_by_name(crate.attrs, "crate_type") {
match syntax::attr::first_attr_value(crate.attrs, syntax::attr::AttrCrateType) {
Some(s) => "lib" == s || "rlib" == s || "dylib" == s || "staticlib" == s,
_ => false
}
Expand Down
16 changes: 7 additions & 9 deletions src/librustc/front/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,11 @@ impl Visitor<()> for Context {
}

fn visit_item(&mut self, i: @ast::item, _:()) {
for attr in i.attrs.iter() {
if "thread_local" == attr.name() {
self.gate_feature("thread_local", i.span,
"`#[thread_local]` is an experimental feature, and does not \
currently handle destructors. There is no corresponding \
`#[task_local]` mapping to the task model");
}
if attr::contains_attr(i.attrs, attr::AttrThreadLocal) {
self.gate_feature("thread_local", i.span,
"`#[thread_local]` is an experimental feature, and does not \
currently handle destructors. There is no corresponding \
`#[task_local]` mapping to the task model");
}
match i.node {
ast::item_enum(ref def, _) => {
Expand All @@ -135,7 +133,7 @@ impl Visitor<()> for Context {
}

ast::item_foreign_mod(..) => {
if attr::contains_name(i.attrs, "link_args") {
if attr::contains_attr(i.attrs, attr::AttrLinkArgs) {
self.gate_feature("link_args", i.span,
"the `link_args` attribute is not portable \
across platforms, it is recommended to \
Expand Down Expand Up @@ -192,7 +190,7 @@ pub fn check_crate(sess: Session, crate: &ast::Crate) {
};

for attr in crate.attrs.iter() {
if "feature" != attr.name() { continue }
if !attr.is_defined_attr(attr::AttrFeature) { continue }

match attr.meta_item_list() {
None => {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/front/std_inject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ pub fn maybe_inject_libstd_ref(sess: Session, crate: ast::Crate)
}

fn use_std(crate: &ast::Crate) -> bool {
!attr::contains_name(crate.attrs, "no_std")
!attr::contains_attr(crate.attrs, attr::AttrNoStd)
}

fn use_uv(crate: &ast::Crate) -> bool {
!attr::contains_name(crate.attrs, "no_uv")
!attr::contains_attr(crate.attrs, attr::AttrNoUv)
}

fn no_prelude(attrs: &[ast::Attribute]) -> bool {
attr::contains_name(attrs, "no_implicit_prelude")
attr::contains_attr(attrs, attr::AttrNoImplicitPrelude)
}

fn spanned<T>(x: T) -> codemap::Spanned<T> {
Expand Down
14 changes: 7 additions & 7 deletions src/librustc/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn modify_for_testing(sess: session::Session,
// We generate the test harness when building in the 'test'
// configuration, either with the '--test' or '--cfg test'
// command line options.
let should_test = attr::contains_name(crate.config, "test");
let should_test = attr::contains_attr(crate.config, attr::AttrTest);

if should_test {
generate_test_harness(sess, crate)
Expand Down Expand Up @@ -120,7 +120,7 @@ impl fold::ast_fold for TestHarnessGenerator {
if !*cx.sess.building_library {
@ast::item {
attrs: item.attrs.iter().filter_map(|attr| {
if "main" != attr.name() {
if !attr.is_defined_attr(attr::AttrMain) {
Some(*attr)
} else {
None
Expand Down Expand Up @@ -175,13 +175,13 @@ fn strip_test_functions(crate: ast::Crate) -> ast::Crate {
// When not compiling with --test we should not compile the
// #[test] functions
config::strip_items(crate, |attrs| {
!attr::contains_name(attrs, "test") &&
!attr::contains_name(attrs, "bench")
!attr::contains_attr(attrs, attr::AttrTest) &&
!attr::contains_attr(attrs, attr::AttrBench)
})
}

fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool {
let has_test_attr = attr::contains_name(i.attrs, "test");
let has_test_attr = attr::contains_attr(i.attrs, attr::AttrTest);

fn has_test_signature(i: @ast::item) -> bool {
match &i.node {
Expand Down Expand Up @@ -210,7 +210,7 @@ fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool {
}

fn is_bench_fn(i: @ast::item) -> bool {
let has_bench_attr = attr::contains_name(i.attrs, "bench");
let has_bench_attr = attr::contains_attr(i.attrs, attr::AttrBench);

fn has_test_signature(i: @ast::item) -> bool {
match i.node {
Expand Down Expand Up @@ -244,7 +244,7 @@ fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool {
}

fn should_fail(i: @ast::item) -> bool {
attr::contains_name(i.attrs, "should_fail")
attr::contains_attr(i.attrs, attr::AttrShouldFail)
}

fn add_test_module(cx: &TestCtxt, m: &ast::_mod) -> ast::_mod {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map)
}

// If the user wants no main function at all, then stop here.
if attr::contains_name(crate.attrs, "no_main") {
if attr::contains_attr(crate.attrs, attr::AttrNoMain) {
*session.entry_type = Some(session::EntryNone);
return
}
Expand Down Expand Up @@ -98,7 +98,7 @@ fn find_item(item: @item, ctxt: &mut EntryContext) {
}
}

if attr::contains_name(item.attrs, "main") {
if attr::contains_attr(item.attrs, attr::AttrMain) {
if ctxt.attr_main_fn.is_none() {
ctxt.attr_main_fn = Some((item.id, item.span));
} else {
Expand All @@ -108,7 +108,7 @@ fn find_item(item: @item, ctxt: &mut EntryContext) {
}
}

if attr::contains_name(item.attrs, "start") {
if attr::contains_attr(item.attrs, attr::AttrStart) {
if ctxt.start_fn.is_none() {
ctxt.start_fn = Some((item.id, item.span));
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ fn check_impl_of_trait(cx: &mut Context, it: @item, trait_ref: &trait_ref, self_
}

fn check_item(cx: &mut Context, item: @item) {
if !attr::contains_name(item.attrs, "unsafe_destructor") {
if !attr::contains_attr(item.attrs, attr::AttrUnsafeDestructor) {
match item.node {
item_impl(_, Some(ref trait_ref), self_type, _) => {
check_impl_of_trait(cx, item, trait_ref, self_type);
Expand Down
128 changes: 41 additions & 87 deletions src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,11 @@ impl<'a> Context<'a> {

let old_is_doc_hidden = self.is_doc_hidden;
self.is_doc_hidden = self.is_doc_hidden ||
attrs.iter().any(|attr| ("doc" == attr.name() && match attr.meta_item_list()
{ None => false,
Some(l) => attr::contains_name(l, "hidden") }));
attrs.iter().any(|attr| (attr.is_defined_attr(attr::AttrDoc) &&
match attr.meta_item_list() {
None => false,
Some(l) => attr::contains_name(l, "hidden")
}));

f(self);

Expand Down Expand Up @@ -815,81 +817,39 @@ fn check_heap_item(cx: &Context, it: &ast::item) {
}
}

static crate_attrs: &'static [&'static str] = &[
"crate_type", "feature", "no_uv", "no_main", "no_std", "pkgid",
"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
"thread_local", // for statics
"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", "link",

//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]) {
fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute], is_crate: bool) {
// check if element has crate-level, obsolete, or any unknown attributes.

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::AttrInner => "crate-level attribute should be in the root module",
};
cx.span_lint(attribute_usage, attr.span, msg);
return;
match attr.to_defined_attr() {
Some(def_attr) => {
if !is_crate && def_attr.is_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);
continue;
}
if def_attr.is_obsolete() {
let msg = match def_attr {
attr::AttrAbi => "Use `extern \"abi\" fn` instead",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be lower case or the message will look like obsolete attribute: Use ....

(Also, auto_{en,de}code have be gone for a long time, and had a deprecation error message for a long time too, so I think we can just drop them at this point.)

attr::AttrAutoEncode => "Use `#[deriving(Encodable)]` instead",
attr::AttrAutoDecode => "Use `#[deriving(Decodable)]` instead",
attr::AttrFastFfi | attr::AttrFixedStackSegment |
attr::AttrRustStack => "Remove it",
_ => fail!(),
};
cx.span_lint(attribute_usage, attr.span,
format!("obsolete attribute: {:s}", msg));
continue;
}
}
}

for &(obs_attr, obs_alter) in obsolete_attrs.iter() {
if name.equiv(&obs_attr) {
cx.span_lint(attribute_usage, attr.span,
format!("obsolete attribute: {:s}", obs_alter));
return;
None => {
cx.span_lint(attribute_usage, attr.span, "unknown attribute");
}
}

if !other_attrs.iter().any(|other_attr| { name.equiv(other_attr) }) {
cx.span_lint(attribute_usage, attr.span, "unknown attribute");
}
}
}

Expand Down Expand Up @@ -1094,13 +1054,7 @@ fn check_missing_doc_attrs(cx: &Context,
_ => ()
}

let has_doc = attrs.iter().any(|a| {
match a.node.value.node {
ast::MetaNameValue(ref name, _) if "doc" == *name => true,
_ => false
}
});
if !has_doc {
if !attr::contains_attr(attrs, attr::AttrDoc) {
cx.span_lint(missing_doc, sp,
format!("missing documentation for {}", desc));
}
Expand Down Expand Up @@ -1242,7 +1196,7 @@ impl<'a> Visitor<()> for Context<'a> {
check_item_non_uppercase_statics(cx, it);
check_heap_item(cx, it);
check_missing_doc_item(cx, it);
check_attrs_usage(cx, it.attrs);
check_attrs_usage(cx, it.attrs, false);

cx.visit_ids(|v| v.visit_item(it, ()));

Expand All @@ -1252,14 +1206,14 @@ impl<'a> Visitor<()> for Context<'a> {

fn visit_foreign_item(&mut self, it: @ast::foreign_item, _: ()) {
self.with_lint_attrs(it.attrs, |cx| {
check_attrs_usage(cx, it.attrs);
check_attrs_usage(cx, it.attrs, false);
visit::walk_foreign_item(cx, it, ());
})
}

fn visit_view_item(&mut self, i: &ast::view_item, _: ()) {
self.with_lint_attrs(i.attrs, |cx| {
check_attrs_usage(cx, i.attrs);
check_attrs_usage(cx, i.attrs, false);
visit::walk_view_item(cx, i, ());
})
}
Expand Down Expand Up @@ -1313,7 +1267,7 @@ impl<'a> Visitor<()> for Context<'a> {
visit::fk_method(_, _, m) => {
self.with_lint_attrs(m.attrs, |cx| {
check_missing_doc_method(cx, m);
check_attrs_usage(cx, m.attrs);
check_attrs_usage(cx, m.attrs, false);

cx.visit_ids(|v| {
v.visit_fn(fk, decl, body, span, id, ());
Expand All @@ -1329,7 +1283,7 @@ impl<'a> Visitor<()> for Context<'a> {
fn visit_ty_method(&mut self, t: &ast::TypeMethod, _: ()) {
self.with_lint_attrs(t.attrs, |cx| {
check_missing_doc_ty_method(cx, t);
check_attrs_usage(cx, t.attrs);
check_attrs_usage(cx, t.attrs, false);

visit::walk_ty_method(cx, t, ());
})
Expand All @@ -1350,7 +1304,7 @@ impl<'a> Visitor<()> for Context<'a> {
fn visit_struct_field(&mut self, s: &ast::struct_field, _: ()) {
self.with_lint_attrs(s.node.attrs, |cx| {
check_missing_doc_struct_field(cx, s);
check_attrs_usage(cx, s.node.attrs);
check_attrs_usage(cx, s.node.attrs, false);

visit::walk_struct_field(cx, s, ());
})
Expand All @@ -1359,7 +1313,7 @@ impl<'a> Visitor<()> for Context<'a> {
fn visit_variant(&mut self, v: &ast::variant, g: &ast::Generics, _: ()) {
self.with_lint_attrs(v.node.attrs, |cx| {
check_missing_doc_variant(cx, v);
check_attrs_usage(cx, v.node.attrs);
check_attrs_usage(cx, v.node.attrs, false);

visit::walk_variant(cx, v, g, ());
})
Expand Down Expand Up @@ -1411,7 +1365,7 @@ pub fn check_crate(tcx: ty::ctxt,
visit::walk_crate(v, crate, ());
});

check_crate_attrs_usage(cx, crate.attrs);
check_attrs_usage(cx, crate.attrs, true);
// since the root module isn't visited as an item (because it isn't an item), warn for it
// here.
check_missing_doc_attrs(cx, None, crate.attrs, crate.span, "crate");
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
fn visit_item(&mut self, item: @ast::item, _: ()) {
// Do not check privacy inside items with the resolve_unexported
// attribute. This is used for the test runner.
if attr::contains_name(item.attrs, "!resolve_unexported") {
if attr::contains_attr(item.attrs, attr::AttrResolveUnexported) {
return;
}

Expand Down
Loading