Skip to content

Commit d2f5637

Browse files
committed
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`
1 parent 0aa8d03 commit d2f5637

12 files changed

+144
-69
lines changed

src/librustc_resolve/macros.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
2828
use syntax::ext::hygiene::{self, Mark};
2929
use syntax::ext::tt::macro_rules;
3030
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
31+
use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE;
3132
use syntax::fold::{self, Folder};
3233
use syntax::parse::parser::PathStyle;
3334
use syntax::parse::token::{self, Token};
@@ -338,19 +339,37 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
338339
match attr_kind {
339340
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
340341
NonMacroAttrKind::Custom if is_attr_invoc => {
342+
let features = self.session.features_untracked();
341343
if attr_kind == NonMacroAttrKind::Tool &&
342-
!self.session.features_untracked().tool_attributes {
344+
!features.tool_attributes {
343345
feature_err(&self.session.parse_sess, "tool_attributes",
344346
invoc.span(), GateIssue::Language,
345347
"tool attributes are unstable").emit();
346348
}
347-
if attr_kind == NonMacroAttrKind::Custom &&
348-
!self.session.features_untracked().custom_attribute {
349-
let msg = format!("The attribute `{}` is currently unknown to the compiler \
350-
and may have meaning added to it in the future", path);
351-
feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
352-
GateIssue::Language, &msg).emit();
349+
if attr_kind == NonMacroAttrKind::Custom {
350+
assert!(path.segments.len() == 1);
351+
let name = path.segments[0].ident.name.as_str();
352+
if name.starts_with("rustc_") {
353+
if !features.rustc_attrs {
354+
let msg = "unless otherwise specified, attributes with the prefix \
355+
`rustc_` are reserved for internal compiler diagnostics";
356+
feature_err(&self.session.parse_sess, "rustc_attrs", invoc.span(),
357+
GateIssue::Language, &msg).emit();
358+
}
359+
} else if name.starts_with("derive_") {
360+
if !features.custom_derive {
361+
feature_err(&self.session.parse_sess, "custom_derive", invoc.span(),
362+
GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
363+
}
364+
} else if !features.custom_attribute {
365+
let msg = format!("The attribute `{}` is currently unknown to the \
366+
compiler and may have meaning added to it in the \
367+
future", path);
368+
feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
369+
GateIssue::Language, &msg).emit();
370+
}
353371
}
372+
354373
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
355374
mark_used: attr_kind == NonMacroAttrKind::Tool,
356375
})));

src/libsyntax/feature_gate.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ macro_rules! declare_features {
9090
self.macros_in_extern || self.proc_macro_path_invoc ||
9191
self.proc_macro_mod || self.proc_macro_expr ||
9292
self.proc_macro_non_items || self.proc_macro_gen ||
93-
self.stmt_expr_attributes
93+
self.stmt_expr_attributes || self.unrestricted_attribute_tokens
9494
}
9595
}
9696
};
@@ -504,6 +504,9 @@ declare_features! (
504504
// impl<I:Iterator> Iterator for &mut Iterator
505505
// impl Debug for Foo<'_>
506506
(active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
507+
508+
// Support for arbitrary delimited token streams in non-macro attributes.
509+
(active, unrestricted_attribute_tokens, "1.30.0", Some(44690), None),
507510
);
508511

509512
declare_features! (
@@ -721,8 +724,7 @@ pub fn is_builtin_attr_name(name: ast::Name) -> bool {
721724
}
722725

723726
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
724-
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name) ||
725-
attr.name().as_str().starts_with("rustc_")
727+
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name)
726728
}
727729

728730
// Attributes that have a special meaning to rustc or rustdoc
@@ -1521,25 +1523,27 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
15211523
}
15221524
}
15231525

1524-
// allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
1525-
let mut allow_attr_literal = false;
1526-
if attr.path == "repr" {
1527-
if let Some(content) = attr.meta_item_list() {
1528-
allow_attr_literal = content.iter().any(
1529-
|c| c.check_name("align") || c.check_name("packed"));
1530-
}
1531-
}
1532-
1533-
if self.context.features.use_extern_macros() && attr::is_known(attr) {
1534-
return
1535-
}
1526+
match attr.parse_meta(self.context.parse_sess) {
1527+
Ok(meta) => {
1528+
// allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
1529+
let mut allow_attr_literal = false;
1530+
if attr.path == "repr" {
1531+
if let Some(content) = meta.meta_item_list() {
1532+
allow_attr_literal = content.iter().any(
1533+
|c| c.check_name("align") || c.check_name("packed"));
1534+
}
1535+
}
15361536

1537-
if !allow_attr_literal {
1538-
let meta = panictry!(attr.parse_meta(self.context.parse_sess));
1539-
if contains_novel_literal(&meta) {
1540-
gate_feature_post!(&self, attr_literals, attr.span,
1541-
"non-string literals in attributes, or string \
1542-
literals in top-level positions, are experimental");
1537+
if !allow_attr_literal && contains_novel_literal(&meta) {
1538+
gate_feature_post!(&self, attr_literals, attr.span,
1539+
"non-string literals in attributes, or string \
1540+
literals in top-level positions, are experimental");
1541+
}
1542+
}
1543+
Err(mut err) => {
1544+
err.cancel();
1545+
gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
1546+
"arbitrary tokens in non-macro attributes are unstable");
15431547
}
15441548
}
15451549
}

src/test/compile-fail/gated-attr-literals.rs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,33 @@
1111
// Check that literals in attributes don't parse without the feature gate.
1212

1313
// gate-test-attr_literals
14-
// gate-test-custom_attribute
1514

16-
#![feature(rustc_attrs)]
17-
#![allow(dead_code)]
18-
#![allow(unused_variables)]
15+
#![feature(custom_attribute)]
1916

20-
#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
21-
#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
17+
#[fake_attr] // OK
18+
#[fake_attr(100)]
2219
//~^ ERROR non-string literals in attributes
23-
#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
20+
#[fake_attr(1, 2, 3)]
2421
//~^ ERROR non-string literals in attributes
25-
#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
22+
#[fake_attr("hello")]
2623
//~^ ERROR string literals in top-level positions, are experimental
27-
#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
28-
#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
24+
#[fake_attr(name = "hello")] // OK
25+
#[fake_attr(1, "hi", key = 12, true, false)]
2926
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
30-
#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
27+
#[fake_attr(key = "hello", val = 10)]
3128
//~^ ERROR non-string literals in attributes
32-
#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
29+
#[fake_attr(key("hello"), val(10))]
3330
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
34-
#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
31+
#[fake_attr(enabled = true, disabled = false)]
3532
//~^ ERROR non-string literals in attributes
36-
#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
33+
#[fake_attr(true)]
3734
//~^ ERROR non-string literals in attributes
38-
#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
35+
#[fake_attr(pi = 3.14159)]
3936
//~^ ERROR non-string literals in attributes
40-
#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
37+
#[fake_attr(b"hi")]
4138
//~^ ERROR string literals in top-level positions, are experimental
42-
#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
39+
#[fake_doc(r"doc")]
4340
//~^ ERROR string literals in top-level positions, are experimental
4441
struct Q { }
4542

46-
#[rustc_error]
4743
fn main() { }

src/test/compile-fail/macro-attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#[doc = $not_there] //~ error: unexpected token: `$`
11+
#[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
1212
fn main() { }

src/test/parse-fail/attr-bad-meta.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
// asterisk is bogus
12-
#[path*] //~ ERROR expected one of `(` or `=`
12+
#[path*] //~ ERROR arbitrary tokens in non-macro attributes are unstable
1313
mod m {}

src/test/run-pass-fulldeps/proc-macro/derive-b.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// aux-build:derive-b.rs
1212
// ignore-stage1
1313

14-
#![feature(proc_macro_path_invoc)]
14+
#![feature(proc_macro_path_invoc, unrestricted_attribute_tokens)]
1515

1616
extern crate derive_b;
1717

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
14+
15+
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
16+
#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
17+
18+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
2+
--> $DIR/feature-gate-rustc-attrs-1.rs:15:1
3+
|
4+
LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
8+
9+
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
10+
--> $DIR/feature-gate-rustc-attrs-1.rs:16:1
11+
|
12+
LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
13+
| ^^^^^^^^^^^^^^
14+
|
15+
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/feature-gate-rustc-attrs.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
1414

15-
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
16-
#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
1715
#[rustc_foo]
1816
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
1917

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
1-
error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
2-
--> $DIR/feature-gate-rustc-attrs.rs:15:1
3-
|
4-
LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
5-
| ^^^^^^^^^^^^^^^^^
6-
|
7-
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
8-
9-
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
10-
--> $DIR/feature-gate-rustc-attrs.rs:16:1
11-
|
12-
LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
13-
| ^^^^^^^^^^^^^^
14-
|
15-
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
16-
171
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
18-
--> $DIR/feature-gate-rustc-attrs.rs:17:1
2+
--> $DIR/feature-gate-rustc-attrs.rs:15:1
193
|
204
LL | #[rustc_foo]
215
| ^^^^^^^^^^^^
226
|
237
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
248

25-
error: aborting due to 3 previous errors
9+
error: aborting due to previous error
2610

2711
For more information about this error, try `rustc --explain E0658`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(custom_attribute)]
12+
13+
#[my_attr(a b c d)]
14+
//~^ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
15+
//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
16+
//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
17+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
2+
--> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:13
3+
|
4+
LL | #[my_attr(a b c d)]
5+
| ^ expected one of `(`, `)`, `,`, `::`, or `=` here
6+
7+
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
8+
--> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:15
9+
|
10+
LL | #[my_attr(a b c d)]
11+
| ^ expected one of `(`, `)`, `,`, `::`, or `=` here
12+
13+
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
14+
--> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:17
15+
|
16+
LL | #[my_attr(a b c d)]
17+
| ^ expected one of `(`, `)`, `,`, `::`, or `=` here
18+
19+
error: aborting due to 3 previous errors
20+

0 commit comments

Comments
 (0)