diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 9020c8c6a2dc6..e7937f57002f3 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -158,11 +158,21 @@ impl<'a> Parser<'a> { self.parse_token_tree().into() } else if self.eat(&token::Eq) { let eq = TokenTree::Token(self.prev_span, token::Eq); - let tree = match self.token { - token::CloseDelim(_) | token::Eof => self.unexpected()?, - _ => self.parse_token_tree(), + let mut is_interpolated_expr = false; + if let token::Interpolated(nt) = &self.token { + if let token::NtExpr(..) = **nt { + is_interpolated_expr = true; + } + } + let tokens = 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().into() + } else { + self.parse_unsuffixed_lit()?.tokens() }; - TokenStream::new(vec![eq.into(), tree.into()]) + TokenStream::from_streams(vec![eq.into(), tokens]) } else { TokenStream::empty() }; diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 283679e758b54..4ce308d015c00 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -254,7 +254,7 @@ impl TokenStream { } } - fn from_streams(mut streams: Vec) -> TokenStream { + pub(crate) fn from_streams(mut streams: Vec) -> TokenStream { match streams.len() { 0 => TokenStream::empty(), 1 => streams.pop().unwrap(), diff --git a/src/test/ui/attr-eq-token-tree.rs b/src/test/ui/attr-eq-token-tree.rs index f28f76db9389d..b8dfafc446e91 100644 --- a/src/test/ui/attr-eq-token-tree.rs +++ b/src/test/ui/attr-eq-token-tree.rs @@ -1,6 +1,4 @@ -// compile-pass - #![feature(custom_attribute, unrestricted_attribute_tokens)] -#[my_attr = !] // OK under feature gate +#[my_attr = !] //~ ERROR unexpected token: `!` fn main() {} diff --git a/src/test/ui/attr-eq-token-tree.stderr b/src/test/ui/attr-eq-token-tree.stderr new file mode 100644 index 0000000000000..57d6a4e0f16a2 --- /dev/null +++ b/src/test/ui/attr-eq-token-tree.stderr @@ -0,0 +1,8 @@ +error: unexpected token: `!` + --> $DIR/attr-eq-token-tree.rs:3:11 + | +LL | #[my_attr = !] //~ ERROR unexpected token: `!` + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/macros/macro-attribute.rs b/src/test/ui/macros/macro-attribute.rs index 7ddac2745c5a4..332246fd1cf9b 100644 --- a/src/test/ui/macros/macro-attribute.rs +++ b/src/test/ui/macros/macro-attribute.rs @@ -1,4 +1,4 @@ #![feature(unrestricted_attribute_tokens)] -#[doc = $not_there] //~ ERROR expected `]`, found `not_there` +#[doc = $not_there] //~ ERROR unexpected token: `$` fn main() { } diff --git a/src/test/ui/macros/macro-attribute.stderr b/src/test/ui/macros/macro-attribute.stderr index fd4e7252d530d..55f8e09b7e3e5 100644 --- a/src/test/ui/macros/macro-attribute.stderr +++ b/src/test/ui/macros/macro-attribute.stderr @@ -1,8 +1,8 @@ -error: expected `]`, found `not_there` - --> $DIR/macro-attribute.rs:3:10 +error: unexpected token: `$` + --> $DIR/macro-attribute.rs:3:7 | -LL | #[doc = $not_there] //~ ERROR expected `]`, found `not_there` - | ^^^^^^^^^ expected `]` +LL | #[doc = $not_there] //~ ERROR unexpected token: `$` + | ^ error: aborting due to previous error diff --git a/src/test/ui/malformed/malformed-interpolated.rs b/src/test/ui/malformed/malformed-interpolated.rs new file mode 100644 index 0000000000000..e452435968bac --- /dev/null +++ b/src/test/ui/malformed/malformed-interpolated.rs @@ -0,0 +1,18 @@ +#![feature(custom_attribute)] + +macro_rules! check { + ($expr: expr) => ( + #[my_attr = $expr] //~ ERROR suffixed literals are not allowed in attributes + //~| ERROR unexpected token: `-0` + //~| ERROR unexpected token: `0 + 0` + use main as _; + ); +} + +check!("0"); // OK +check!(0); // OK +check!(0u8); // ERROR, see above +check!(-0); // ERROR, see above +check!(0 + 0); // ERROR, see above + +fn main() {} diff --git a/src/test/ui/malformed/malformed-interpolated.stderr b/src/test/ui/malformed/malformed-interpolated.stderr new file mode 100644 index 0000000000000..f9c89316fcd14 --- /dev/null +++ b/src/test/ui/malformed/malformed-interpolated.stderr @@ -0,0 +1,35 @@ +error: suffixed literals are not allowed in attributes + --> $DIR/malformed-interpolated.rs:5:21 + | +LL | #[my_attr = $expr] //~ ERROR suffixed literals are not allowed in attributes + | ^^^^^ +... +LL | check!(0u8); // ERROR, see above + | ------------ in this macro invocation + | + = help: instead of using a suffixed literal (1u8, 1.0f32, etc.), use an unsuffixed version (1, 1.0, etc.). + +error: unexpected token: `-0` + --> $DIR/malformed-interpolated.rs:5:19 + | +LL | #[my_attr = $expr] //~ ERROR suffixed literals are not allowed in attributes + | ^ +... +LL | check!(-0); // ERROR, see above + | ----------- in this macro invocation + | + = help: try enabling `#![feature(unrestricted_attribute_tokens)]` + +error: unexpected token: `0 + 0` + --> $DIR/malformed-interpolated.rs:5:19 + | +LL | #[my_attr = $expr] //~ ERROR suffixed literals are not allowed in attributes + | ^ +... +LL | check!(0 + 0); // ERROR, see above + | -------------- in this macro invocation + | + = help: try enabling `#![feature(unrestricted_attribute_tokens)]` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/attr-bad-meta-2.stderr b/src/test/ui/parser/attr-bad-meta-2.stderr index ddc7a4b034b7f..36e566b5aa41a 100644 --- a/src/test/ui/parser/attr-bad-meta-2.stderr +++ b/src/test/ui/parser/attr-bad-meta-2.stderr @@ -1,8 +1,8 @@ error: unexpected token: `]` - --> $DIR/attr-bad-meta-2.rs:1:9 + --> $DIR/attr-bad-meta-2.rs:1:8 | LL | #[path =] //~ ERROR unexpected token: `]` - | ^ unexpected token after this + | ^ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs index b708f6303148a..af6bfa08aaa94 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.rs +++ b/src/test/ui/proc-macro/proc-macro-gates.rs @@ -19,7 +19,7 @@ mod _test2_inner { //~| ERROR: non-builtin inner attributes are unstable } -#[a = y] //~ ERROR: must only be followed by a delimiter token +#[a = "y"] //~ ERROR: must only be followed by a delimiter token fn _test3() {} fn attrs() { diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr index c0bc06d358de9..abfcf09bfaf6c 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.stderr +++ b/src/test/ui/proc-macro/proc-macro-gates.stderr @@ -33,8 +33,8 @@ LL | #![a] //~ ERROR: custom attributes cannot be applied to modules error: custom attribute invocations must be of the form #[foo] or #[foo(..)], the macro name must only be followed by a delimiter token --> $DIR/proc-macro-gates.rs:22:1 | -LL | #[a = y] //~ ERROR: must only be followed by a delimiter token - | ^^^^^^^^ +LL | #[a = "y"] //~ ERROR: must only be followed by a delimiter token + | ^^^^^^^^^^ error[E0658]: custom attributes cannot be applied to statements (see issue #54727) --> $DIR/proc-macro-gates.rs:31:5