mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
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`
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
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 @@ fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool)
|
||||
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,
|
||||
})));
|
||||
|
||||
@@ -90,7 +90,7 @@ pub fn use_extern_macros(&self) -> bool {
|
||||
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 @@ pub fn use_extern_macros(&self) -> bool {
|
||||
// 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 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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"));
|
||||
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 && 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 self.context.features.use_extern_macros() && attr::is_known(attr) {
|
||||
return
|
||||
}
|
||||
|
||||
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");
|
||||
Err(mut err) => {
|
||||
err.cancel();
|
||||
gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
|
||||
"arbitrary tokens in non-macro attributes are unstable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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`.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user