1
Fork 0

Accept arbitrary expressions in key-value attributes at parse time

This commit is contained in:
Vadim Petrochenkov 2020-11-07 16:09:40 +03:00
parent fa55f668e5
commit 31d72c2658
24 changed files with 145 additions and 210 deletions

View file

@ -24,7 +24,7 @@ pub use UnsafeSource::*;
use crate::ptr::P; use crate::ptr::P;
use crate::token::{self, CommentKind, DelimToken}; use crate::token::{self, CommentKind, DelimToken};
use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree}; use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
@ -39,7 +39,6 @@ use rustc_span::{Span, DUMMY_SP};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;
use std::iter;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -1514,20 +1513,6 @@ impl MacArgs {
} }
} }
/// Tokens together with the delimiters or `=`.
/// Use of this method generally means that something suboptimal or hacky is happening.
pub fn outer_tokens(&self) -> TokenStream {
match *self {
MacArgs::Empty => TokenStream::default(),
MacArgs::Delimited(dspan, delim, ref tokens) => {
TokenTree::Delimited(dspan, delim.to_token(), tokens.clone()).into()
}
MacArgs::Eq(eq_span, ref tokens) => {
iter::once(TokenTree::token(token::Eq, eq_span)).chain(tokens.trees()).collect()
}
}
}
/// Whether a macro with these arguments needs a semicolon /// Whether a macro with these arguments needs a semicolon
/// when used as a standalone item or statement. /// when used as a standalone item or statement.
pub fn need_semicolon(&self) -> bool { pub fn need_semicolon(&self) -> bool {

View file

@ -371,20 +371,15 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
// The value in `#[key = VALUE]` must be visited as an expression for backward // The value in `#[key = VALUE]` must be visited as an expression for backward
// compatibility, so that macros can be expanded in that position. // compatibility, so that macros can be expanded in that position.
if !vis.token_visiting_enabled() { if !vis.token_visiting_enabled() {
if let Some(TokenTree::Token(token)) = tokens.trees_ref().next() { match Lrc::make_mut(&mut tokens.0).get_mut(0) {
if let token::Interpolated(..) = token.kind { Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
// ^^ Do not `make_mut` unless we have to. token::Interpolated(nt) => match Lrc::make_mut(nt) {
match Lrc::make_mut(&mut tokens.0).get_mut(0) { token::NtExpr(expr) => vis.visit_expr(expr),
Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
token::Interpolated(nt) => match Lrc::make_mut(nt) {
token::NtExpr(expr) => vis.visit_expr(expr),
t => panic!("unexpected token in key-value attribute: {:?}", t),
},
t => panic!("unexpected token in key-value attribute: {:?}", t),
},
t => panic!("unexpected token in key-value attribute: {:?}", t), t => panic!("unexpected token in key-value attribute: {:?}", t),
} },
} t => panic!("unexpected token in key-value attribute: {:?}", t),
},
t => panic!("unexpected token in key-value attribute: {:?}", t),
} }
} }
} }

View file

@ -906,7 +906,6 @@ pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
token::NtExpr(expr) => visitor.visit_expr(expr), token::NtExpr(expr) => visitor.visit_expr(expr),
t => panic!("unexpected token in key-value attribute: {:?}", t), t => panic!("unexpected token in key-value attribute: {:?}", t),
}, },
token::Literal(..) | token::Ident(..) => {}
t => panic!("unexpected token in key-value attribute: {:?}", t), t => panic!("unexpected token in key-value attribute: {:?}", t),
}, },
t => panic!("unexpected token in key-value attribute: {:?}", t), t => panic!("unexpected token in key-value attribute: {:?}", t),

View file

@ -630,6 +630,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!(const_trait_impl, "const trait impls are experimental");
gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const, "inline-const is experimental");
gate_all!(
extended_key_value_attributes,
"arbitrary expressions in key-value attributes are unstable"
);
if sess.parse_sess.span_diagnostic.err_count() == 0 { if sess.parse_sess.span_diagnostic.err_count() == 0 {
// Errors for `destructuring_assignment` can get quite noisy, especially where `_` is // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
// involved, so we only emit errors where there are no other parsing errors. // involved, so we only emit errors where there are no other parsing errors.

View file

@ -620,6 +620,9 @@ declare_features! (
/// Allows capturing disjoint fields in a closure/generator (RFC 2229). /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
(active, capture_disjoint_fields, "1.49.0", Some(53488), None), (active, capture_disjoint_fields, "1.49.0", Some(53488), None),
/// Allows arbitrary expressions in key-value attributes at parse time.
(active, extended_key_value_attributes, "1.50.0", Some(78835), None),
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// feature-group-end: actual feature gates // feature-group-end: actual feature gates
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View file

@ -23,6 +23,7 @@ use rustc_ast::{self as ast, AnonConst, AttrStyle, AttrVec, Const, CrateSugar, E
use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit}; use rustc_ast::{Async, Expr, ExprKind, MacArgs, MacDelimiter, Mutability, StrLit};
use rustc_ast::{Visibility, VisibilityKind}; use rustc_ast::{Visibility, VisibilityKind};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
use rustc_errors::PResult; use rustc_errors::PResult;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError};
use rustc_session::parse::ParseSess; use rustc_session::parse::ParseSess;
@ -935,16 +936,24 @@ impl<'a> Parser<'a> {
is_interpolated_expr = true; is_interpolated_expr = true;
} }
} }
let token_tree = if is_interpolated_expr {
// We need to accept arbitrary interpolated expressions to continue
// supporting things like `doc = $expr` that work on stable.
// Non-literal interpolated expressions are rejected after expansion.
self.parse_token_tree()
} else {
self.parse_unsuffixed_lit()?.token_tree()
};
MacArgs::Eq(eq_span, token_tree.into()) // The value here is never passed to macros as tokens by itself (not as a part
// of the whole attribute), so we don't collect tokens here. If this changes,
// then token will need to be collected. One catch here is that we are using
// a nonterminal for keeping the expression, but this nonterminal should not
// be wrapped into a group when converting to token stream.
let expr = self.parse_expr()?;
let span = expr.span;
match &expr.kind {
// Not gated to supporte things like `doc = $expr` that work on stable.
_ if is_interpolated_expr => {}
ExprKind::Lit(lit) if lit.kind.is_unsuffixed() => {}
_ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span),
}
let token = token::Interpolated(Lrc::new(token::NtExpr(expr)));
MacArgs::Eq(eq_span, TokenTree::token(token, span).into())
} else { } else {
MacArgs::Empty MacArgs::Empty
} }

View file

@ -496,6 +496,7 @@ symbols! {
expf64, expf64,
export_name, export_name,
expr, expr,
extended_key_value_attributes,
extern_absolute_paths, extern_absolute_paths,
extern_crate_item_prelude, extern_crate_item_prelude,
extern_crate_self, extern_crate_self,

View file

@ -1,4 +1,5 @@
#![feature(external_doc)] #![feature(external_doc)]
#![feature(extended_key_value_attributes)]
// @has external_doc/struct.CanHasDocs.html // @has external_doc/struct.CanHasDocs.html
// @has - '//h1' 'External Docs' // @has - '//h1' 'External Docs'
@ -6,3 +7,18 @@
#[doc(include = "auxiliary/external-doc.md")] #[doc(include = "auxiliary/external-doc.md")]
/// ## Inline Docs /// ## Inline Docs
pub struct CanHasDocs; pub struct CanHasDocs;
// @has external_doc/struct.IncludeStrDocs.html
// @has - '//h1' 'External Docs'
// @has - '//h2' 'Inline Docs'
#[doc = include_str!("auxiliary/external-doc.md")]
/// ## Inline Docs
pub struct IncludeStrDocs;
macro_rules! dir { () => { "auxiliary" } }
// @has external_doc/struct.EagerExpansion.html
// @has - '//h1' 'External Docs'
#[doc = include_str!(concat!(dir!(), "/external-doc.md"))]
/// ## Inline Docs
pub struct EagerExpansion;

View file

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} {"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}

View file

@ -1 +1 @@
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} {"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}

View file

@ -1,2 +1,2 @@
#[my_attr = !] //~ ERROR unexpected token: `!` #[my_attr = !] //~ ERROR expected expression, found `]`
fn main() {} fn main() {}

View file

@ -1,8 +1,8 @@
error: unexpected token: `!` error: expected expression, found `]`
--> $DIR/attr-eq-token-tree.rs:1:13 --> $DIR/attr-eq-token-tree.rs:1:14
| |
LL | #[my_attr = !] LL | #[my_attr = !]
| ^ | ^ expected expression
error: aborting due to previous error error: aborting due to previous error

View file

@ -12,23 +12,22 @@ extern crate key_value_expansion;
macro_rules! bug { macro_rules! bug {
($expr:expr) => { ($expr:expr) => {
#[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc` #[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc`
//~^ ERROR unexpected token: `(7u32)`
struct S; struct S;
}; };
} }
// Any expressions containing macro call `X` that's more complex than `X` itself. // Any expressions containing macro call `X` that's more complex than `X` itself.
// Parentheses will work. // Parentheses will work.
bug!((column!())); bug!((column!())); //~ ERROR unexpected token: `(7u32)`
// Original test case. // Original test case.
macro_rules! bug { macro_rules! bug {
() => { () => {
bug!("bug" + stringify!(found)); bug!("bug" + stringify!(found)); //~ ERROR unexpected token: `"bug" + "found"`
}; };
($test:expr) => { ($test:expr) => {
#[doc = $test] //~ ERROR unexpected token: `"bug" + "found"` #[doc = $test]
struct Test {} struct Test {}
}; };
} }
@ -39,7 +38,7 @@ bug!();
macro_rules! doc_comment { macro_rules! doc_comment {
($x:expr) => { ($x:expr) => {
#[doc = $x] //~ ERROR unexpected token: `{ #[doc = $x]
extern {} extern {}
}; };
} }
@ -47,6 +46,7 @@ macro_rules! doc_comment {
macro_rules! some_macro { macro_rules! some_macro {
($t1: ty) => { ($t1: ty) => {
doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
//~^ ERROR unexpected token: `{
}; };
} }

View file

@ -1,19 +1,14 @@
error: unexpected token: `(7u32)` error: unexpected token: `(7u32)`
--> $DIR/key-value-expansion.rs:14:25 --> $DIR/key-value-expansion.rs:21:6
| |
LL | #[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc`
| ^^^^^
...
LL | bug!((column!())); LL | bug!((column!()));
| ------------------ in this macro invocation | ^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: unexpected token: `"bug" + "found"` error: unexpected token: `"bug" + "found"`
--> $DIR/key-value-expansion.rs:31:17 --> $DIR/key-value-expansion.rs:27:14
| |
LL | #[doc = $test] LL | bug!("bug" + stringify!(found));
| ^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
... ...
LL | bug!(); LL | bug!();
| ------- in this macro invocation | ------- in this macro invocation
@ -30,10 +25,10 @@ error: unexpected token: `{
})); }));
res res
}.as_str()` }.as_str()`
--> $DIR/key-value-expansion.rs:42:17 --> $DIR/key-value-expansion.rs:48:23
| |
LL | #[doc = $x] LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
| ^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
... ...
LL | some_macro!(u8); LL | some_macro!(u8);
| ---------------- in this macro invocation | ---------------- in this macro invocation

View file

@ -0,0 +1,8 @@
#[cfg(FALSE)]
#[attr = multi::segment::path] //~ ERROR arbitrary expressions in key-value attributes are unstable
#[attr = macro_call!()] //~ ERROR arbitrary expressions in key-value attributes are unstable
#[attr = 1 + 2] //~ ERROR arbitrary expressions in key-value attributes are unstable
#[attr = what?] //~ ERROR arbitrary expressions in key-value attributes are unstable
struct S;
fn main() {}

View file

@ -0,0 +1,39 @@
error[E0658]: arbitrary expressions in key-value attributes are unstable
--> $DIR/feature-gate-extended_key_value_attributes.rs:2:10
|
LL | #[attr = multi::segment::path]
| ^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
= help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
error[E0658]: arbitrary expressions in key-value attributes are unstable
--> $DIR/feature-gate-extended_key_value_attributes.rs:3:10
|
LL | #[attr = macro_call!()]
| ^^^^^^^^^^^^^
|
= note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
= help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
error[E0658]: arbitrary expressions in key-value attributes are unstable
--> $DIR/feature-gate-extended_key_value_attributes.rs:4:10
|
LL | #[attr = 1 + 2]
| ^^^^^
|
= note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
= help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
error[E0658]: arbitrary expressions in key-value attributes are unstable
--> $DIR/feature-gate-extended_key_value_attributes.rs:5:10
|
LL | #[attr = what?]
| ^^^^^
|
= note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
= help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,2 +1,2 @@
#[doc = $not_there] //~ ERROR unexpected token: `$` #[doc = $not_there] //~ ERROR expected expression, found `$`
fn main() { } fn main() { }

View file

@ -1,8 +1,8 @@
error: unexpected token: `$` error: expected expression, found `$`
--> $DIR/macro-attribute.rs:1:9 --> $DIR/macro-attribute.rs:1:9
| |
LL | #[doc = $not_there] LL | #[doc = $not_there]
| ^ | ^ expected expression
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,8 +2,7 @@
macro_rules! check { macro_rules! check {
($expr: expr) => ( ($expr: expr) => (
#[rustc_dummy = $expr] //~ ERROR unexpected token: `-0` #[rustc_dummy = $expr]
//~| ERROR unexpected token: `0 + 0`
use main as _; use main as _;
); );
} }
@ -11,7 +10,7 @@ macro_rules! check {
check!("0"); // OK check!("0"); // OK
check!(0); // OK check!(0); // OK
check!(0u8); //~ ERROR suffixed literals are not allowed in attributes check!(0u8); //~ ERROR suffixed literals are not allowed in attributes
check!(-0); // ERROR, see above check!(-0); //~ ERROR unexpected token: `-0`
check!(0 + 0); // ERROR, see above check!(0 + 0); //~ ERROR unexpected token: `0 + 0`
fn main() {} fn main() {}

View file

@ -1,5 +1,5 @@
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/malformed-interpolated.rs:13:8 --> $DIR/malformed-interpolated.rs:12:8
| |
LL | check!(0u8); LL | check!(0u8);
| ^^^ | ^^^
@ -7,26 +7,16 @@ LL | check!(0u8);
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: unexpected token: `-0` error: unexpected token: `-0`
--> $DIR/malformed-interpolated.rs:5:25 --> $DIR/malformed-interpolated.rs:13:8
| |
LL | #[rustc_dummy = $expr] LL | check!(-0);
| ^^^^^ | ^^
...
LL | check!(-0); // ERROR, see above
| ----------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: unexpected token: `0 + 0` error: unexpected token: `0 + 0`
--> $DIR/malformed-interpolated.rs:5:25 --> $DIR/malformed-interpolated.rs:14:8
| |
LL | #[rustc_dummy = $expr] LL | check!(0 + 0);
| ^^^^^ | ^^^^^
...
LL | check!(0 + 0); // ERROR, see above
| -------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,2 +1,2 @@
#[path =] //~ ERROR unexpected token: `]` #[path =] //~ ERROR expected expression, found `]`
mod m {} mod m {}

View file

@ -1,8 +1,8 @@
error: unexpected token: `]` error: expected expression, found `]`
--> $DIR/attr-bad-meta-2.rs:1:9 --> $DIR/attr-bad-meta-2.rs:1:9
| |
LL | #[path =] LL | #[path =]
| ^ | ^ expected expression
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,27 +1,15 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs, extended_key_value_attributes)]
#[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1u16] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1u16] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1u32] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1u32] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1u64] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1u64] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1isize] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1isize] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1i8] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1i8] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1i16] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1i16] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1i32] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1i32] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1i64] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1i64] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1.0f32] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
#[rustc_dummy = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes #[rustc_dummy = 1.0f64] //~ ERROR: suffixed literals are not allowed in attributes
//~| ERROR: suffixed literals are not allowed in attributes
fn main() {} fn main() {}

View file

@ -7,119 +7,23 @@ LL | #[rustc_dummy = 1usize]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:5:17 --> $DIR/suffixed-literal-meta.rs:4:17
| |
LL | #[rustc_dummy = 1u8] LL | #[rustc_dummy = 1u8]
| ^^^ | ^^^
| |
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:7:17
|
LL | #[rustc_dummy = 1u16]
| ^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:9:17
|
LL | #[rustc_dummy = 1u32]
| ^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:11:17
|
LL | #[rustc_dummy = 1u64]
| ^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:13:17
|
LL | #[rustc_dummy = 1isize]
| ^^^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:15:17
|
LL | #[rustc_dummy = 1i8]
| ^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:17:17
|
LL | #[rustc_dummy = 1i16]
| ^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:19:17
|
LL | #[rustc_dummy = 1i32]
| ^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:21:17
|
LL | #[rustc_dummy = 1i64]
| ^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:23:17
|
LL | #[rustc_dummy = 1.0f32]
| ^^^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:25:17
|
LL | #[rustc_dummy = 1.0f64]
| ^^^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:3:17
|
LL | #[rustc_dummy = 1usize]
| ^^^^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:5:17 --> $DIR/suffixed-literal-meta.rs:5:17
| |
LL | #[rustc_dummy = 1u8]
| ^^^
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:7:17
|
LL | #[rustc_dummy = 1u16] LL | #[rustc_dummy = 1u16]
| ^^^^ | ^^^^
| |
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:9:17 --> $DIR/suffixed-literal-meta.rs:6:17
| |
LL | #[rustc_dummy = 1u32] LL | #[rustc_dummy = 1u32]
| ^^^^ | ^^^^
@ -127,7 +31,7 @@ LL | #[rustc_dummy = 1u32]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:11:17 --> $DIR/suffixed-literal-meta.rs:7:17
| |
LL | #[rustc_dummy = 1u64] LL | #[rustc_dummy = 1u64]
| ^^^^ | ^^^^
@ -135,7 +39,7 @@ LL | #[rustc_dummy = 1u64]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:13:17 --> $DIR/suffixed-literal-meta.rs:8:17
| |
LL | #[rustc_dummy = 1isize] LL | #[rustc_dummy = 1isize]
| ^^^^^^ | ^^^^^^
@ -143,7 +47,7 @@ LL | #[rustc_dummy = 1isize]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:15:17 --> $DIR/suffixed-literal-meta.rs:9:17
| |
LL | #[rustc_dummy = 1i8] LL | #[rustc_dummy = 1i8]
| ^^^ | ^^^
@ -151,7 +55,7 @@ LL | #[rustc_dummy = 1i8]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:17:17 --> $DIR/suffixed-literal-meta.rs:10:17
| |
LL | #[rustc_dummy = 1i16] LL | #[rustc_dummy = 1i16]
| ^^^^ | ^^^^
@ -159,7 +63,7 @@ LL | #[rustc_dummy = 1i16]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:19:17 --> $DIR/suffixed-literal-meta.rs:11:17
| |
LL | #[rustc_dummy = 1i32] LL | #[rustc_dummy = 1i32]
| ^^^^ | ^^^^
@ -167,7 +71,7 @@ LL | #[rustc_dummy = 1i32]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:21:17 --> $DIR/suffixed-literal-meta.rs:12:17
| |
LL | #[rustc_dummy = 1i64] LL | #[rustc_dummy = 1i64]
| ^^^^ | ^^^^
@ -175,7 +79,7 @@ LL | #[rustc_dummy = 1i64]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:23:17 --> $DIR/suffixed-literal-meta.rs:13:17
| |
LL | #[rustc_dummy = 1.0f32] LL | #[rustc_dummy = 1.0f32]
| ^^^^^^ | ^^^^^^
@ -183,12 +87,12 @@ LL | #[rustc_dummy = 1.0f32]
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: suffixed literals are not allowed in attributes error: suffixed literals are not allowed in attributes
--> $DIR/suffixed-literal-meta.rs:25:17 --> $DIR/suffixed-literal-meta.rs:14:17
| |
LL | #[rustc_dummy = 1.0f64] LL | #[rustc_dummy = 1.0f64]
| ^^^^^^ | ^^^^^^
| |
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: aborting due to 24 previous errors error: aborting due to 12 previous errors