about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-08-29 21:59:24 +0000
committerbors <bors@rust-lang.org>2015-08-29 21:59:24 +0000
commit9982314577e3d86da87b8024496d932b2cfff298 (patch)
tree8630b747865a1120d3b730d1e629db9227707a39
parent09dd65c2f60ba635378d2e9afdb1ca4775d8e76c (diff)
parent4b571b055d8ac9c77d1337e2bda2652bfc024de9 (diff)
downloadrust-9982314577e3d86da87b8024496d932b2cfff298.tar.gz
rust-9982314577e3d86da87b8024496d932b2cfff298.zip
Auto merge of #28077 - jonas-schievink:attr-gateage, r=huonw
This allows marking attributes as whitelisted/crate-only independent of
their feature gate status.

Closes #24213
-rw-r--r--src/librustc/plugin/registry.rs5
-rw-r--r--src/librustc_lint/builtin.rs12
-rw-r--r--src/libsyntax/feature_gate.rs242
-rw-r--r--src/test/compile-fail/invalid-plugin-attr.rs17
4 files changed, 149 insertions, 127 deletions
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs
index 5faaa53e4d0..2f3625ff22f 100644
--- a/src/librustc/plugin/registry.rs
+++ b/src/librustc/plugin/registry.rs
@@ -145,11 +145,6 @@ impl<'a> Registry<'a> {
     /// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
     /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
     pub fn register_attribute(&mut self, name: String, ty: AttributeType) {
-        if let AttributeType::Gated(..) = ty {
-            self.sess.span_err(self.krate_span, "plugin tried to register a gated \
-                                                 attribute. Only `Normal`, `Whitelisted`, \
-                                                 and `CrateLevel` attributes are allowed");
-        }
         self.attributes.push((name, ty));
     }
 }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index e582b9266cd..abdeb6ae46e 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -887,10 +887,9 @@ impl LintPass for UnusedAttributes {
 
     fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
         // Note that check_name() marks the attribute as used if it matches.
-        for &(ref name, ty) in KNOWN_ATTRIBUTES {
+        for &(ref name, ty, _) in KNOWN_ATTRIBUTES {
             match ty {
-                AttributeType::Whitelisted
-                | AttributeType::Gated(_, _) if attr.check_name(name) => {
+                AttributeType::Whitelisted if attr.check_name(name) => {
                     break;
                 },
                 _ => ()
@@ -907,8 +906,11 @@ impl LintPass for UnusedAttributes {
         if !attr::is_used(attr) {
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
             // Is it a builtin attribute that must be used at the crate level?
-            let known_crate = KNOWN_ATTRIBUTES.contains(&(&attr.name(),
-                                                          AttributeType::CrateLevel));
+            let known_crate = KNOWN_ATTRIBUTES.iter().find(|&&(name, ty, _)| {
+                attr.name() == name &&
+                ty == AttributeType::CrateLevel
+            }).is_some();
+
             // Has a plugin registered this attribute as one which must be used at
             // the crate level?
             let plugin_crate = plugin_attributes.iter()
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index f5a0a2f4718..3fa55df7594 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -24,6 +24,7 @@
 
 use self::Status::*;
 use self::AttributeType::*;
+use self::AttributeGate::*;
 
 use abi::Abi;
 use ast::NodeId;
@@ -203,135 +204,137 @@ enum Status {
 }
 
 // Attributes that have a special meaning to rustc or rustdoc
-pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
+pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[
     // Normal attributes
 
-    ("warn", Normal),
-    ("allow", Normal),
-    ("forbid", Normal),
-    ("deny", Normal),
-
-    ("macro_reexport", Normal),
-    ("macro_use", Normal),
-    ("macro_export", Normal),
-    ("plugin_registrar", Normal),
-
-    ("cfg", Normal),
-    ("cfg_attr", Normal),
-    ("main", Normal),
-    ("start", Normal),
-    ("test", Normal),
-    ("bench", Normal),
-    ("simd", Normal),
-    ("repr", Normal),
-    ("path", Normal),
-    ("abi", Normal),
-    ("automatically_derived", Normal),
-    ("no_mangle", Normal),
-    ("no_link", Normal),
-    ("derive", Normal),
-    ("should_panic", Normal),
-    ("ignore", Normal),
-    ("no_implicit_prelude", Normal),
-    ("reexport_test_harness_main", Normal),
-    ("link_args", Normal),
-    ("macro_escape", Normal),
+    ("warn", Normal, Ungated),
+    ("allow", Normal, Ungated),
+    ("forbid", Normal, Ungated),
+    ("deny", Normal, Ungated),
+
+    ("macro_reexport", Normal, Ungated),
+    ("macro_use", Normal, Ungated),
+    ("macro_export", Normal, Ungated),
+    ("plugin_registrar", Normal, Ungated),
+
+    ("cfg", Normal, Ungated),
+    ("cfg_attr", Normal, Ungated),
+    ("main", Normal, Ungated),
+    ("start", Normal, Ungated),
+    ("test", Normal, Ungated),
+    ("bench", Normal, Ungated),
+    ("simd", Normal, Ungated),
+    ("repr", Normal, Ungated),
+    ("path", Normal, Ungated),
+    ("abi", Normal, Ungated),
+    ("automatically_derived", Normal, Ungated),
+    ("no_mangle", Normal, Ungated),
+    ("no_link", Normal, Ungated),
+    ("derive", Normal, Ungated),
+    ("should_panic", Normal, Ungated),
+    ("ignore", Normal, Ungated),
+    ("no_implicit_prelude", Normal, Ungated),
+    ("reexport_test_harness_main", Normal, Ungated),
+    ("link_args", Normal, Ungated),
+    ("macro_escape", Normal, Ungated),
 
     // Not used any more, but we can't feature gate it
-    ("no_stack_check", Normal),
-
-    ("staged_api", Gated("staged_api",
-                         "staged_api is for use by rustc only")),
-    ("plugin", Gated("plugin",
-                     "compiler plugins are experimental \
-                      and possibly buggy")),
-    ("no_std", Gated("no_std",
-                     "no_std is experimental")),
-    ("no_core", Gated("no_core",
-                     "no_core is experimental")),
-    ("lang", Gated("lang_items",
-                     "language items are subject to change")),
-    ("linkage", Gated("linkage",
-                      "the `linkage` attribute is experimental \
-                       and not portable across platforms")),
-    ("thread_local", Gated("thread_local",
-                            "`#[thread_local]` is an experimental feature, and does not \
-                             currently handle destructors. There is no corresponding \
-                             `#[task_local]` mapping to the task model")),
-
-    ("rustc_on_unimplemented", Gated("on_unimplemented",
-                                     "the `#[rustc_on_unimplemented]` attribute \
+    ("no_stack_check", Normal, Ungated),
+
+    ("staged_api", CrateLevel, Gated("staged_api",
+                                     "staged_api is for use by rustc only")),
+    ("plugin", CrateLevel, Gated("plugin",
+                                 "compiler plugins are experimental \
+                                  and possibly buggy")),
+    ("no_std", CrateLevel, Gated("no_std",
+                                 "no_std is experimental")),
+    ("no_core", CrateLevel, Gated("no_core",
+                                  "no_core is experimental")),
+    ("lang", Normal, Gated("lang_items",
+                           "language items are subject to change")),
+    ("linkage", Whitelisted, Gated("linkage",
+                                   "the `linkage` attribute is experimental \
+                                    and not portable across platforms")),
+    ("thread_local", Whitelisted, Gated("thread_local",
+                                        "`#[thread_local]` is an experimental feature, and does \
+                                         not currently handle destructors. There is no \
+                                         corresponding `#[task_local]` mapping to the task \
+                                         model")),
+
+    ("rustc_on_unimplemented", Normal, Gated("on_unimplemented",
+                                             "the `#[rustc_on_unimplemented]` attribute \
+                                              is an experimental feature")),
+    ("allocator", Whitelisted, Gated("allocator",
+                                     "the `#[allocator]` attribute is an experimental feature")),
+    ("needs_allocator", Normal, Gated("needs_allocator",
+                                      "the `#[needs_allocator]` \
+                                       attribute is an experimental \
+                                       feature")),
+    ("rustc_variance", Normal, Gated("rustc_attrs",
+                                     "the `#[rustc_variance]` attribute \
                                       is an experimental feature")),
-    ("allocator", Gated("allocator",
-                        "the `#[allocator]` attribute is an experimental feature")),
-    ("needs_allocator", Gated("needs_allocator", "the `#[needs_allocator]` \
-                                                  attribute is an experimental \
-                                                  feature")),
-    ("rustc_variance", Gated("rustc_attrs",
-                             "the `#[rustc_variance]` attribute \
-                              is an experimental feature")),
-    ("rustc_error", Gated("rustc_attrs",
-                          "the `#[rustc_error]` attribute \
-                           is an experimental feature")),
-    ("rustc_move_fragments", Gated("rustc_attrs",
-                                   "the `#[rustc_move_fragments]` attribute \
-                                    is an experimental feature")),
-
-    ("allow_internal_unstable", Gated("allow_internal_unstable",
-                                      EXPLAIN_ALLOW_INTERNAL_UNSTABLE)),
-
-    ("fundamental", Gated("fundamental",
-                          "the `#[fundamental]` attribute \
-                           is an experimental feature")),
-
-    ("linked_from", Gated("linked_from",
-                          "the `#[linked_from]` attribute \
-                           is an experimental feature")),
+    ("rustc_error", Whitelisted, Gated("rustc_attrs",
+                                       "the `#[rustc_error]` attribute \
+                                        is an experimental feature")),
+    ("rustc_move_fragments", Normal, Gated("rustc_attrs",
+                                           "the `#[rustc_move_fragments]` attribute \
+                                            is an experimental feature")),
+
+    ("allow_internal_unstable", Normal, Gated("allow_internal_unstable",
+                                              EXPLAIN_ALLOW_INTERNAL_UNSTABLE)),
+
+    ("fundamental", Whitelisted, Gated("fundamental",
+                                       "the `#[fundamental]` attribute \
+                                        is an experimental feature")),
+
+    ("linked_from", Normal, Gated("linked_from",
+                                  "the `#[linked_from]` attribute \
+                                   is an experimental feature")),
 
     // FIXME: #14408 whitelist docs since rustdoc looks at them
-    ("doc", Whitelisted),
+    ("doc", Whitelisted, Ungated),
 
     // FIXME: #14406 these are processed in trans, which happens after the
     // lint pass
-    ("cold", Whitelisted),
-    ("export_name", Whitelisted),
-    ("inline", Whitelisted),
-    ("link", Whitelisted),
-    ("link_name", Whitelisted),
-    ("link_section", Whitelisted),
-    ("no_builtins", Whitelisted),
-    ("no_mangle", Whitelisted),
-    ("no_debug", Whitelisted),
-    ("omit_gdb_pretty_printer_section", Whitelisted),
-    ("unsafe_no_drop_flag", Gated("unsafe_no_drop_flag",
-                                  "unsafe_no_drop_flag has unstable semantics \
-                                   and may be removed in the future")),
+    ("cold", Whitelisted, Ungated),
+    ("export_name", Whitelisted, Ungated),
+    ("inline", Whitelisted, Ungated),
+    ("link", Whitelisted, Ungated),
+    ("link_name", Whitelisted, Ungated),
+    ("link_section", Whitelisted, Ungated),
+    ("no_builtins", Whitelisted, Ungated),
+    ("no_mangle", Whitelisted, Ungated),
+    ("no_debug", Whitelisted, Ungated),
+    ("omit_gdb_pretty_printer_section", Whitelisted, Ungated),
+    ("unsafe_no_drop_flag", Whitelisted, Gated("unsafe_no_drop_flag",
+                                               "unsafe_no_drop_flag has unstable semantics \
+                                                and may be removed in the future")),
 
     // used in resolve
-    ("prelude_import", Gated("prelude_import",
-                             "`#[prelude_import]` is for use by rustc only")),
+    ("prelude_import", Whitelisted, Gated("prelude_import",
+                                          "`#[prelude_import]` is for use by rustc only")),
 
     // FIXME: #14407 these are only looked at on-demand so we can't
     // guarantee they'll have already been checked
-    ("deprecated", Whitelisted),
-    ("must_use", Whitelisted),
-    ("stable", Whitelisted),
-    ("unstable", Whitelisted),
+    ("deprecated", Whitelisted, Ungated),
+    ("must_use", Whitelisted, Ungated),
+    ("stable", Whitelisted, Ungated),
+    ("unstable", Whitelisted, Ungated),
 
-    ("rustc_paren_sugar", Gated("unboxed_closures",
-                                "unboxed_closures are still evolving")),
-    ("rustc_reflect_like", Gated("reflect",
-                                 "defining reflective traits is still evolving")),
+    ("rustc_paren_sugar", Normal, Gated("unboxed_closures",
+                                        "unboxed_closures are still evolving")),
+    ("rustc_reflect_like", Whitelisted, Gated("reflect",
+                                              "defining reflective traits is still evolving")),
 
     // Crate level attributes
-    ("crate_name", CrateLevel),
-    ("crate_type", CrateLevel),
-    ("crate_id", CrateLevel),
-    ("feature", CrateLevel),
-    ("no_start", CrateLevel),
-    ("no_main", CrateLevel),
-    ("no_builtins", CrateLevel),
-    ("recursion_limit", CrateLevel),
+    ("crate_name", CrateLevel, Ungated),
+    ("crate_type", CrateLevel, Ungated),
+    ("crate_id", CrateLevel, Ungated),
+    ("feature", CrateLevel, Ungated),
+    ("no_start", CrateLevel, Ungated),
+    ("no_main", CrateLevel, Ungated),
+    ("no_builtins", CrateLevel, Ungated),
+    ("recursion_limit", CrateLevel, Ungated),
 ];
 
 macro_rules! cfg_fn {
@@ -398,12 +401,17 @@ pub enum AttributeType {
     /// will be ignored by the unused_attribute lint
     Whitelisted,
 
+    /// Builtin attribute that is only allowed at the crate level
+    CrateLevel,
+}
+
+#[derive(PartialEq, Copy, Clone, Debug)]
+pub enum AttributeGate {
     /// Is gated by a given feature gate and reason
-    /// These get whitelisted too
     Gated(&'static str, &'static str),
 
-    /// Builtin attribute that is only allowed at the crate level
-    CrateLevel,
+    /// Ungated attribute, can be used on all release channels
+    Ungated,
 }
 
 /// A set of features to be used by later passes.
@@ -522,12 +530,12 @@ impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
         let name = &*attr.name();
-        for &(n, ty) in KNOWN_ATTRIBUTES {
+        for &(n, ty, gateage) in KNOWN_ATTRIBUTES {
             if n == name {
-                if let Gated(gate, desc) = ty {
+                if let Gated(gate, desc) = gateage {
                     self.gate_feature(gate, attr.span, desc);
                 }
-                debug!("check_attribute: {:?} is known, {:?}", name, ty);
+                debug!("check_attribute: {:?} is known, {:?}, {:?}", name, ty, gateage);
                 return;
             }
         }
diff --git a/src/test/compile-fail/invalid-plugin-attr.rs b/src/test/compile-fail/invalid-plugin-attr.rs
new file mode 100644
index 00000000000..3bf09e10ae8
--- /dev/null
+++ b/src/test/compile-fail/invalid-plugin-attr.rs
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+#![deny(unused_attributes)]
+#![feature(plugin)]
+
+#[plugin(bla)]  //~ ERROR unused attribute
+                //~^ ERROR should be an inner attribute
+
+fn main() {}