diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9d6ee65049a..220bbed7e78 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -24,7 +24,7 @@ pub use UnsafeSource::*; use crate::ptr::P; 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::stack::ensure_sufficient_stack; @@ -39,7 +39,6 @@ use rustc_span::{Span, DUMMY_SP}; use std::cmp::Ordering; use std::convert::TryFrom; use std::fmt; -use std::iter; #[cfg(test)] 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 /// when used as a standalone item or statement. pub fn need_semicolon(&self) -> bool { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c4e92a9f6d1..3889ede7f4c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -371,20 +371,15 @@ pub fn visit_mac_args(args: &mut MacArgs, vis: &mut T) { // The value in `#[key = VALUE]` must be visited as an expression for backward // compatibility, so that macros can be expanded in that position. if !vis.token_visiting_enabled() { - if let Some(TokenTree::Token(token)) = tokens.trees_ref().next() { - if let token::Interpolated(..) = token.kind { - // ^^ Do not `make_mut` unless we have to. - match Lrc::make_mut(&mut tokens.0).get_mut(0) { - 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), - }, + match Lrc::make_mut(&mut tokens.0).get_mut(0) { + 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), } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 61426a838de..a420bb56350 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -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), 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), diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 5b75fbf339b..9d54d89e080 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -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!(half_open_range_patterns, "half-open range patterns are unstable"); 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 { // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is // involved, so we only emit errors where there are no other parsing errors. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 75337634d3f..845e03150d7 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -620,6 +620,9 @@ declare_features! ( /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (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 // ------------------------------------------------------------------------- diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 22f308ff36d..df4695b18e7 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -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::{Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; +use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError}; use rustc_session::parse::ParseSess; @@ -935,16 +936,24 @@ impl<'a> Parser<'a> { 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 { MacArgs::Empty } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e75ddb36ff8..b9c942d61a9 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -496,6 +496,7 @@ symbols! { expf64, export_name, expr, + extended_key_value_attributes, extern_absolute_paths, extern_crate_item_prelude, extern_crate_self, diff --git a/src/test/rustdoc/external-doc.rs b/src/test/rustdoc/external-doc.rs index 4a13f4069c4..befd31a5492 100644 --- a/src/test/rustdoc/external-doc.rs +++ b/src/test/rustdoc/external-doc.rs @@ -1,4 +1,5 @@ #![feature(external_doc)] +#![feature(extended_key_value_attributes)] // @has external_doc/struct.CanHasDocs.html // @has - '//h1' 'External Docs' @@ -6,3 +7,18 @@ #[doc(include = "auxiliary/external-doc.md")] /// ## Inline Docs 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; diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index b19cfc4d5c3..deb2a1af204 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -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":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 65d6cd475cc..71336f452fc 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -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":[]} diff --git a/src/test/ui/attr-eq-token-tree.rs b/src/test/ui/attr-eq-token-tree.rs index c301492b9e2..330b119772a 100644 --- a/src/test/ui/attr-eq-token-tree.rs +++ b/src/test/ui/attr-eq-token-tree.rs @@ -1,2 +1,2 @@ -#[my_attr = !] //~ ERROR unexpected token: `!` +#[my_attr = !] //~ ERROR expected expression, found `]` fn main() {} diff --git a/src/test/ui/attr-eq-token-tree.stderr b/src/test/ui/attr-eq-token-tree.stderr index bb37c2e0cc4..1846444b668 100644 --- a/src/test/ui/attr-eq-token-tree.stderr +++ b/src/test/ui/attr-eq-token-tree.stderr @@ -1,8 +1,8 @@ -error: unexpected token: `!` - --> $DIR/attr-eq-token-tree.rs:1:13 +error: expected expression, found `]` + --> $DIR/attr-eq-token-tree.rs:1:14 | LL | #[my_attr = !] - | ^ + | ^ expected expression error: aborting due to previous error diff --git a/src/test/ui/attributes/key-value-expansion.rs b/src/test/ui/attributes/key-value-expansion.rs index 831c8091f32..08121413ee9 100644 --- a/src/test/ui/attributes/key-value-expansion.rs +++ b/src/test/ui/attributes/key-value-expansion.rs @@ -12,23 +12,22 @@ extern crate key_value_expansion; macro_rules! bug { ($expr:expr) => { #[rustc_dummy = $expr] // Any key-value attribute, not necessarily `doc` - //~^ ERROR unexpected token: `(7u32)` struct S; }; } // Any expressions containing macro call `X` that's more complex than `X` itself. // Parentheses will work. -bug!((column!())); +bug!((column!())); //~ ERROR unexpected token: `(7u32)` // Original test case. macro_rules! bug { () => { - bug!("bug" + stringify!(found)); + bug!("bug" + stringify!(found)); //~ ERROR unexpected token: `"bug" + "found"` }; ($test:expr) => { - #[doc = $test] //~ ERROR unexpected token: `"bug" + "found"` + #[doc = $test] struct Test {} }; } @@ -39,7 +38,7 @@ bug!(); macro_rules! doc_comment { ($x:expr) => { - #[doc = $x] //~ ERROR unexpected token: `{ + #[doc = $x] extern {} }; } @@ -47,6 +46,7 @@ macro_rules! doc_comment { macro_rules! some_macro { ($t1: ty) => { doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} + //~^ ERROR unexpected token: `{ }; } diff --git a/src/test/ui/attributes/key-value-expansion.stderr b/src/test/ui/attributes/key-value-expansion.stderr index 5da4557f0ae..4b14b88a74f 100644 --- a/src/test/ui/attributes/key-value-expansion.stderr +++ b/src/test/ui/attributes/key-value-expansion.stderr @@ -1,19 +1,14 @@ 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!())); - | ------------------ 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"` - --> $DIR/key-value-expansion.rs:31:17 + --> $DIR/key-value-expansion.rs:27:14 | -LL | #[doc = $test] - | ^^^^^ +LL | bug!("bug" + stringify!(found)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bug!(); | ------- in this macro invocation @@ -30,10 +25,10 @@ error: unexpected token: `{ })); res }.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); | ---------------- in this macro invocation diff --git a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs new file mode 100644 index 00000000000..f19fdb45f1f --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs @@ -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() {} diff --git a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr new file mode 100644 index 00000000000..9887814b907 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr @@ -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 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 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 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 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`. diff --git a/src/test/ui/macros/macro-attribute.rs b/src/test/ui/macros/macro-attribute.rs index f580dfa8e34..88834a96721 100644 --- a/src/test/ui/macros/macro-attribute.rs +++ b/src/test/ui/macros/macro-attribute.rs @@ -1,2 +1,2 @@ -#[doc = $not_there] //~ ERROR unexpected token: `$` +#[doc = $not_there] //~ ERROR expected expression, found `$` fn main() { } diff --git a/src/test/ui/macros/macro-attribute.stderr b/src/test/ui/macros/macro-attribute.stderr index d28ce25341d..3316d387264 100644 --- a/src/test/ui/macros/macro-attribute.stderr +++ b/src/test/ui/macros/macro-attribute.stderr @@ -1,8 +1,8 @@ -error: unexpected token: `$` +error: expected expression, found `$` --> $DIR/macro-attribute.rs:1:9 | LL | #[doc = $not_there] - | ^ + | ^ expected expression error: aborting due to previous error diff --git a/src/test/ui/malformed/malformed-interpolated.rs b/src/test/ui/malformed/malformed-interpolated.rs index 5101b5caeea..b962447e7ed 100644 --- a/src/test/ui/malformed/malformed-interpolated.rs +++ b/src/test/ui/malformed/malformed-interpolated.rs @@ -2,8 +2,7 @@ macro_rules! check { ($expr: expr) => ( - #[rustc_dummy = $expr] //~ ERROR unexpected token: `-0` - //~| ERROR unexpected token: `0 + 0` + #[rustc_dummy = $expr] use main as _; ); } @@ -11,7 +10,7 @@ macro_rules! check { check!("0"); // OK check!(0); // OK check!(0u8); //~ ERROR suffixed literals are not allowed in attributes -check!(-0); // ERROR, see above -check!(0 + 0); // ERROR, see above +check!(-0); //~ ERROR unexpected token: `-0` +check!(0 + 0); //~ ERROR unexpected token: `0 + 0` fn main() {} diff --git a/src/test/ui/malformed/malformed-interpolated.stderr b/src/test/ui/malformed/malformed-interpolated.stderr index d1be82cf7b7..4b9332ddd01 100644 --- a/src/test/ui/malformed/malformed-interpolated.stderr +++ b/src/test/ui/malformed/malformed-interpolated.stderr @@ -1,5 +1,5 @@ error: suffixed literals are not allowed in attributes - --> $DIR/malformed-interpolated.rs:13:8 + --> $DIR/malformed-interpolated.rs:12:8 | 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.) error: unexpected token: `-0` - --> $DIR/malformed-interpolated.rs:5:25 + --> $DIR/malformed-interpolated.rs:13:8 | -LL | #[rustc_dummy = $expr] - | ^^^^^ -... -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) +LL | check!(-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); // 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) +LL | check!(0 + 0); + | ^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/attr-bad-meta-2.rs b/src/test/ui/parser/attr-bad-meta-2.rs index cefd3369742..db612ed883d 100644 --- a/src/test/ui/parser/attr-bad-meta-2.rs +++ b/src/test/ui/parser/attr-bad-meta-2.rs @@ -1,2 +1,2 @@ -#[path =] //~ ERROR unexpected token: `]` +#[path =] //~ ERROR expected expression, found `]` mod m {} diff --git a/src/test/ui/parser/attr-bad-meta-2.stderr b/src/test/ui/parser/attr-bad-meta-2.stderr index 2d772dae691..6fc6fb665a8 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: `]` +error: expected expression, found `]` --> $DIR/attr-bad-meta-2.rs:1:9 | LL | #[path =] - | ^ + | ^ expected expression error: aborting due to previous error diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/suffixed-literal-meta.rs index c3a4eabad70..319264aec9c 100644 --- a/src/test/ui/suffixed-literal-meta.rs +++ b/src/test/ui/suffixed-literal-meta.rs @@ -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 - //~| 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 - //~| 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 - //~| 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 - //~| 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 - //~| 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 - //~| 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() {} diff --git a/src/test/ui/suffixed-literal-meta.stderr b/src/test/ui/suffixed-literal-meta.stderr index 84fe91d662a..5245ffead71 100644 --- a/src/test/ui/suffixed-literal-meta.stderr +++ b/src/test/ui/suffixed-literal-meta.stderr @@ -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.) 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] | ^^^ | = 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 --> $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] | ^^^^ | = 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 + --> $DIR/suffixed-literal-meta.rs:6:17 | 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.) 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] | ^^^^ @@ -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.) 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] | ^^^^^^ @@ -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.) 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] | ^^^ @@ -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.) 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] | ^^^^ @@ -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.) 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] | ^^^^ @@ -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.) 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] | ^^^^ @@ -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.) 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] | ^^^^^^ @@ -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.) 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] | ^^^^^^ | = 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