about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-08-11 16:40:08 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-08-11 16:41:17 +0300
commitd2f56378da7f722145d54f7c9c54deed43e2a12b (patch)
tree07b11cc0c107f7966bf7cfeee366a198c7969e22 /src
parent0aa8d0320266b5579428312095fe49af05ada972 (diff)
downloadrust-d2f56378da7f722145d54f7c9c54deed43e2a12b.tar.gz
rust-d2f56378da7f722145d54f7c9c54deed43e2a12b.zip
Feature gate arbitrary tokens in non-macro attributes with a separate gate
Feature gate `rustc_` and `derive_` with their own gates again instead of `custom_attribute`
Diffstat (limited to 'src')
-rw-r--r--src/librustc_resolve/macros.rs33
-rw-r--r--src/libsyntax/feature_gate.rs46
-rw-r--r--src/test/compile-fail/gated-attr-literals.rs32
-rw-r--r--src/test/compile-fail/macro-attribute.rs2
-rw-r--r--src/test/parse-fail/attr-bad-meta.rs2
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/derive-b.rs2
-rw-r--r--src/test/ui/feature-gate-rustc-attrs-1.rs18
-rw-r--r--src/test/ui/feature-gate-rustc-attrs-1.stderr19
-rw-r--r--src/test/ui/feature-gate-rustc-attrs.rs2
-rw-r--r--src/test/ui/feature-gate-rustc-attrs.stderr20
-rw-r--r--src/test/ui/feature-gate-unrestricted-attribute-tokens.rs17
-rw-r--r--src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr20
12 files changed, 144 insertions, 69 deletions
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index d680b2d9f7d..2054b7a351f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -28,6 +28,7 @@ use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
 use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
+use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE;
 use syntax::fold::{self, Folder};
 use syntax::parse::parser::PathStyle;
 use syntax::parse::token::{self, Token};
@@ -338,19 +339,37 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
             match attr_kind {
                 NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
                 NonMacroAttrKind::Custom if is_attr_invoc => {
+                    let features = self.session.features_untracked();
                     if attr_kind == NonMacroAttrKind::Tool &&
-                       !self.session.features_untracked().tool_attributes {
+                       !features.tool_attributes {
                         feature_err(&self.session.parse_sess, "tool_attributes",
                                     invoc.span(), GateIssue::Language,
                                     "tool attributes are unstable").emit();
                     }
-                    if attr_kind == NonMacroAttrKind::Custom &&
-                       !self.session.features_untracked().custom_attribute {
-                        let msg = format!("The attribute `{}` is currently unknown to the compiler \
-                                           and may have meaning added to it in the future", path);
-                        feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
-                                    GateIssue::Language, &msg).emit();
+                    if attr_kind == NonMacroAttrKind::Custom {
+                        assert!(path.segments.len() == 1);
+                        let name = path.segments[0].ident.name.as_str();
+                        if name.starts_with("rustc_") {
+                            if !features.rustc_attrs {
+                                let msg = "unless otherwise specified, attributes with the prefix \
+                                        `rustc_` are reserved for internal compiler diagnostics";
+                                feature_err(&self.session.parse_sess, "rustc_attrs", invoc.span(),
+                                            GateIssue::Language, &msg).emit();
+                            }
+                        } else if name.starts_with("derive_") {
+                            if !features.custom_derive {
+                                feature_err(&self.session.parse_sess, "custom_derive", invoc.span(),
+                                            GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
+                            }
+                        } else if !features.custom_attribute {
+                            let msg = format!("The attribute `{}` is currently unknown to the \
+                                               compiler and may have meaning added to it in the \
+                                               future", path);
+                            feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
+                                        GateIssue::Language, &msg).emit();
+                        }
                     }
+
                     return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
                         mark_used: attr_kind == NonMacroAttrKind::Tool,
                     })));
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 976708ae788..b779b2eb689 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -90,7 +90,7 @@ macro_rules! declare_features {
                 self.macros_in_extern || self.proc_macro_path_invoc ||
                 self.proc_macro_mod || self.proc_macro_expr ||
                 self.proc_macro_non_items || self.proc_macro_gen ||
-                self.stmt_expr_attributes
+                self.stmt_expr_attributes || self.unrestricted_attribute_tokens
             }
         }
     };
@@ -504,6 +504,9 @@ declare_features! (
     // impl<I:Iterator> Iterator for &mut Iterator
     // impl Debug for Foo<'_>
     (active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
+
+    // Support for arbitrary delimited token streams in non-macro attributes.
+    (active, unrestricted_attribute_tokens, "1.30.0", Some(44690), None),
 );
 
 declare_features! (
@@ -721,8 +724,7 @@ pub fn is_builtin_attr_name(name: ast::Name) -> bool {
 }
 
 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
-    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name) ||
-    attr.name().as_str().starts_with("rustc_")
+    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name)
 }
 
 // Attributes that have a special meaning to rustc or rustdoc
@@ -1521,25 +1523,27 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             }
         }
 
-        // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
-        let mut allow_attr_literal = false;
-        if attr.path == "repr" {
-            if let Some(content) = attr.meta_item_list() {
-                allow_attr_literal = content.iter().any(
-                    |c| c.check_name("align") || c.check_name("packed"));
-            }
-        }
-
-        if self.context.features.use_extern_macros() && attr::is_known(attr) {
-            return
-        }
+        match attr.parse_meta(self.context.parse_sess) {
+            Ok(meta) => {
+                // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
+                let mut allow_attr_literal = false;
+                if attr.path == "repr" {
+                    if let Some(content) = meta.meta_item_list() {
+                        allow_attr_literal = content.iter().any(
+                            |c| c.check_name("align") || c.check_name("packed"));
+                    }
+                }
 
-        if !allow_attr_literal {
-            let meta = panictry!(attr.parse_meta(self.context.parse_sess));
-            if contains_novel_literal(&meta) {
-                gate_feature_post!(&self, attr_literals, attr.span,
-                                   "non-string literals in attributes, or string \
-                                   literals in top-level positions, are experimental");
+                if !allow_attr_literal && contains_novel_literal(&meta) {
+                    gate_feature_post!(&self, attr_literals, attr.span,
+                                    "non-string literals in attributes, or string \
+                                    literals in top-level positions, are experimental");
+                }
+            }
+            Err(mut err) => {
+                err.cancel();
+                gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
+                                    "arbitrary tokens in non-macro attributes are unstable");
             }
         }
     }
diff --git a/src/test/compile-fail/gated-attr-literals.rs b/src/test/compile-fail/gated-attr-literals.rs
index b500bfc3c21..8d36745116b 100644
--- a/src/test/compile-fail/gated-attr-literals.rs
+++ b/src/test/compile-fail/gated-attr-literals.rs
@@ -11,37 +11,33 @@
 // Check that literals in attributes don't parse without the feature gate.
 
 // gate-test-attr_literals
-// gate-test-custom_attribute
 
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
+#![feature(custom_attribute)]
 
-#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
-#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr] // OK
+#[fake_attr(100)]
     //~^ ERROR non-string literals in attributes
-#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(1, 2, 3)]
     //~^ ERROR non-string literals in attributes
-#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr("hello")]
     //~^ ERROR string literals in top-level positions, are experimental
-#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
-#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(name = "hello")] // OK
+#[fake_attr(1, "hi", key = 12, true, false)]
     //~^ ERROR non-string literals in attributes, or string literals in top-level positions
-#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(key = "hello", val = 10)]
     //~^ ERROR non-string literals in attributes
-#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(key("hello"), val(10))]
     //~^ ERROR non-string literals in attributes, or string literals in top-level positions
-#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(enabled = true, disabled = false)]
     //~^ ERROR non-string literals in attributes
-#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(true)]
     //~^ ERROR non-string literals in attributes
-#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(pi = 3.14159)]
     //~^ ERROR non-string literals in attributes
-#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(b"hi")]
     //~^ ERROR string literals in top-level positions, are experimental
-#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
+#[fake_doc(r"doc")]
     //~^ ERROR string literals in top-level positions, are experimental
 struct Q {  }
 
-#[rustc_error]
 fn main() { }
diff --git a/src/test/compile-fail/macro-attribute.rs b/src/test/compile-fail/macro-attribute.rs
index 52f867fe913..a77b1724876 100644
--- a/src/test/compile-fail/macro-attribute.rs
+++ b/src/test/compile-fail/macro-attribute.rs
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[doc = $not_there] //~ error: unexpected token: `$`
+#[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
 fn main() { }
diff --git a/src/test/parse-fail/attr-bad-meta.rs b/src/test/parse-fail/attr-bad-meta.rs
index d57a813311b..41db88121cb 100644
--- a/src/test/parse-fail/attr-bad-meta.rs
+++ b/src/test/parse-fail/attr-bad-meta.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 // asterisk is bogus
-#[path*] //~ ERROR expected one of `(` or `=`
+#[path*] //~ ERROR arbitrary tokens in non-macro attributes are unstable
 mod m {}
diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs
index 4a7c8f3e834..918d2c17123 100644
--- a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs
@@ -11,7 +11,7 @@
 // aux-build:derive-b.rs
 // ignore-stage1
 
-#![feature(proc_macro_path_invoc)]
+#![feature(proc_macro_path_invoc, unrestricted_attribute_tokens)]
 
 extern crate derive_b;
 
diff --git a/src/test/ui/feature-gate-rustc-attrs-1.rs b/src/test/ui/feature-gate-rustc-attrs-1.rs
new file mode 100644
index 00000000000..7295de80db5
--- /dev/null
+++ b/src/test/ui/feature-gate-rustc-attrs-1.rs
@@ -0,0 +1,18 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
+
+#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
+#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gate-rustc-attrs-1.stderr
new file mode 100644
index 00000000000..54a580ce9f9
--- /dev/null
+++ b/src/test/ui/feature-gate-rustc-attrs-1.stderr
@@ -0,0 +1,19 @@
+error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs-1.rs:15:1
+   |
+LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs-1.rs:16:1
+   |
+LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gate-rustc-attrs.rs
index 8cfd3e020c6..99bc51b69c6 100644
--- a/src/test/ui/feature-gate-rustc-attrs.rs
+++ b/src/test/ui/feature-gate-rustc-attrs.rs
@@ -12,8 +12,6 @@
 
 // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
 
-#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
-#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
 #[rustc_foo]
 //~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
 
diff --git a/src/test/ui/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gate-rustc-attrs.stderr
index fda95a5b97a..52a4d3664ce 100644
--- a/src/test/ui/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gate-rustc-attrs.stderr
@@ -1,27 +1,11 @@
-error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
-  --> $DIR/feature-gate-rustc-attrs.rs:15:1
-   |
-LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
-
-error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
-  --> $DIR/feature-gate-rustc-attrs.rs:16:1
-   |
-LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-   | ^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
-
 error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
-  --> $DIR/feature-gate-rustc-attrs.rs:17:1
+  --> $DIR/feature-gate-rustc-attrs.rs:15:1
    |
 LL | #[rustc_foo]
    | ^^^^^^^^^^^^
    |
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-unrestricted-attribute-tokens.rs b/src/test/ui/feature-gate-unrestricted-attribute-tokens.rs
new file mode 100644
index 00000000000..daebbe658a2
--- /dev/null
+++ b/src/test/ui/feature-gate-unrestricted-attribute-tokens.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 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.
+
+#![feature(custom_attribute)]
+
+#[my_attr(a b c d)]
+//~^ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
+//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
+//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
+fn main() {}
diff --git a/src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr b/src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr
new file mode 100644
index 00000000000..cc5694b1598
--- /dev/null
+++ b/src/test/ui/feature-gate-unrestricted-attribute-tokens.stderr
@@ -0,0 +1,20 @@
+error: expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
+  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:13
+   |
+LL | #[my_attr(a b c d)]
+   |             ^ expected one of `(`, `)`, `,`, `::`, or `=` here
+
+error: expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
+  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:15
+   |
+LL | #[my_attr(a b c d)]
+   |               ^ expected one of `(`, `)`, `,`, `::`, or `=` here
+
+error: expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
+  --> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:17
+   |
+LL | #[my_attr(a b c d)]
+   |                 ^ expected one of `(`, `)`, `,`, `::`, or `=` here
+
+error: aborting due to 3 previous errors
+