From f183966992d98c2f3da095d3fffa06631d529e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 15 Sep 2025 02:28:43 -0700 Subject: [PATCH 1/3] Handle macro invocation in attribute during parse ``` error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` --> $DIR/macro-in-attribute.rs:4:21 | LL | #[deprecated(note = concat!("a", "b"))] | ^^^^^^^^^^^^^^^^^ macros are not allowed here ``` --- compiler/rustc_attr_parsing/messages.ftl | 1 + compiler/rustc_attr_parsing/src/parser.rs | 40 ++++++++++++++----- .../src/session_diagnostics.rs | 2 + .../rustc_parse/src/parser/diagnostics.rs | 2 +- tests/ui/parser/macro/macro-in-attribute.rs | 9 +++++ .../ui/parser/macro/macro-in-attribute.stderr | 8 ++++ 6 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 tests/ui/parser/macro/macro-in-attribute.rs create mode 100644 tests/ui/parser/macro/macro-in-attribute.stderr diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index a2a5f8ab14236..cb65fdc050a74 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -99,6 +99,7 @@ attr_parsing_invalid_link_modifier = attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal + .label = macros are not allowed here attr_parsing_invalid_predicate = invalid predicate `{$predicate}` diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 7474471f2fe0f..23f0e4fa0330c 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; -use rustc_parse::parser::{Parser, PathStyle, token_descr}; +use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; use rustc_session::errors::{create_lit_error, report_lit_error}; use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym}; @@ -488,6 +488,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { descr: token_descr(&self.parser.token), quote_ident_sugg: None, remove_neg_sugg: None, + macro_call: None, }; // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and @@ -496,20 +497,37 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { if self.parser.prev_token == token::Eq && let token::Ident(..) = self.parser.token.kind { - let before = self.parser.token.span.shrink_to_lo(); - while let token::Ident(..) = self.parser.token.kind { - self.parser.bump(); + if self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Bang)) { + let snapshot = self.parser.create_snapshot_for_diagnostic(); + let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); + match stmt { + Ok(Some(stmt)) => { + // The user tried to write something like + // `#[deprecated(note = concat!("a", "b"))]`. + err.descr = format!("macro {}", err.descr); + err.macro_call = Some(stmt.span); + err.span = stmt.span; + } + Ok(None) => {} + Err(err) => { + err.cancel(); + self.parser.restore_snapshot(snapshot); + } + } + } else { + let before = self.parser.token.span.shrink_to_lo(); + while let token::Ident(..) = self.parser.token.kind { + self.parser.bump(); + } + err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { + before, + after: self.parser.prev_token.span.shrink_to_hi(), + }); } - err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { - before, - after: self.parser.prev_token.span.shrink_to_hi(), - }); } if self.parser.token == token::Minus - && self - .parser - .look_ahead(1, |t| matches!(t.kind, rustc_ast::token::TokenKind::Literal { .. })) + && self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Literal { .. })) { err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg { negative_sign: self.parser.token.span }); diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 82bd29218313e..1d68fea34ce60 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -831,6 +831,8 @@ pub(crate) struct InvalidMetaItem { pub quote_ident_sugg: Option, #[subdiagnostic] pub remove_neg_sugg: Option, + #[label] + pub macro_call: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c36cd610c6a59..8aec7f476f5d7 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -288,7 +288,7 @@ impl<'a> Parser<'a> { } /// Replace `self` with `snapshot.parser`. - pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { + pub fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { *self = snapshot.parser; } diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs new file mode 100644 index 0000000000000..57808c6fd27da --- /dev/null +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -0,0 +1,9 @@ +// Test for #146325. +// Ensure that when we encounter a macro invocation in an attribute, we don't suggest nonsense. + +#[deprecated(note = concat!("a", "b"))] +struct X; +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` +//~| NOTE: macros are not allowed here + +fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr new file mode 100644 index 0000000000000..e0ae51365a85c --- /dev/null +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -0,0 +1,8 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` + --> $DIR/macro-in-attribute.rs:4:21 + | +LL | #[deprecated(note = concat!("a", "b"))] + | ^^^^^^^^^^^^^^^^^ macros are not allowed here + +error: aborting due to 1 previous error + From d7b9a269af3cddc93aca9a8bf6ef58b14beee6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 28 Sep 2025 20:52:57 +0000 Subject: [PATCH 2/3] Rework attribute recovery logic --- compiler/rustc_ast/src/ast.rs | 13 +++ compiler/rustc_attr_parsing/messages.ftl | 2 +- compiler/rustc_attr_parsing/src/parser.rs | 80 ++++++++++--------- .../src/session_diagnostics.rs | 2 +- tests/ui/attributes/malformed-fn-align.rs | 2 +- tests/ui/attributes/malformed-fn-align.stderr | 4 +- ...-66340-deprecated-attr-non-meta-grammar.rs | 2 +- ...40-deprecated-attr-non-meta-grammar.stderr | 4 +- tests/ui/parser/attribute/attr-bad-meta-4.rs | 2 +- .../parser/attribute/attr-bad-meta-4.stderr | 4 +- .../parser/attribute/attr-unquoted-ident.rs | 19 +++-- .../attribute/attr-unquoted-ident.stderr | 25 ++++-- tests/ui/parser/macro/expr-in-attribute.rs | 9 +++ .../ui/parser/macro/expr-in-attribute.stderr | 8 ++ tests/ui/parser/macro/macro-in-attribute.rs | 2 +- .../ui/parser/macro/macro-in-attribute.stderr | 2 +- 16 files changed, 116 insertions(+), 64 deletions(-) create mode 100644 tests/ui/parser/macro/expr-in-attribute.rs create mode 100644 tests/ui/parser/macro/expr-in-attribute.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8f44931826398..a4621a7e40bed 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1247,6 +1247,19 @@ pub enum StmtKind { MacCall(Box), } +impl StmtKind { + pub fn descr(&self) -> &'static str { + match self { + StmtKind::Let(_) => "local", + StmtKind::Item(_) => "item", + StmtKind::Expr(_) => "expression", + StmtKind::Semi(_) => "statement", + StmtKind::Empty => "semicolon", + StmtKind::MacCall(_) => "macro", + } + } +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct MacCallStmt { pub mac: Box, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index cb65fdc050a74..59fae5b8dc111 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -99,7 +99,7 @@ attr_parsing_invalid_link_modifier = attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal - .label = macros are not allowed here + .label = {$descr}s are not allowed here attr_parsing_invalid_predicate = invalid predicate `{$predicate}` diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 23f0e4fa0330c..819e5630561d0 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -8,7 +8,7 @@ use std::fmt::{Debug, Display}; use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path}; +use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path, StmtKind, UnOp}; use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; @@ -488,51 +488,55 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { descr: token_descr(&self.parser.token), quote_ident_sugg: None, remove_neg_sugg: None, - macro_call: None, + label: None, }; + if let token::OpenInvisible(_) = self.parser.token.kind { + // Do not attempt to suggest anything when encountered as part of a macro expansion. + return self.parser.dcx().create_err(err); + } + // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable // when macro metavariables are involved. - if self.parser.prev_token == token::Eq - && let token::Ident(..) = self.parser.token.kind - { - if self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Bang)) { - let snapshot = self.parser.create_snapshot_for_diagnostic(); - let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); - match stmt { - Ok(Some(stmt)) => { - // The user tried to write something like - // `#[deprecated(note = concat!("a", "b"))]`. - err.descr = format!("macro {}", err.descr); - err.macro_call = Some(stmt.span); - err.span = stmt.span; - } - Ok(None) => {} - Err(err) => { - err.cancel(); - self.parser.restore_snapshot(snapshot); + let snapshot = self.parser.create_snapshot_for_diagnostic(); + let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); + match stmt { + Ok(Some(stmt)) => { + // The user tried to write something like + // `#[deprecated(note = concat!("a", "b"))]`. + err.descr = stmt.kind.descr().to_string(); + err.label = Some(stmt.span); + err.span = stmt.span; + if let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Unary(UnOp::Neg, val) = &expr.kind + && let ExprKind::Lit(_) = val.kind + { + err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg { + negative_sign: expr.span.until(val.span), + }); + } else if let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Path(None, Path { segments, .. }) = &expr.kind + && segments.len() == 1 + { + while let token::Ident(..) | token::Literal(_) | token::Dot = + self.parser.token.kind + { + // We've got a word, so we try to consume the rest of a potential sentence. + // We include `.` to correctly handle things like `A sentence here.`. + self.parser.bump(); } + err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { + before: expr.span.shrink_to_lo(), + after: self.parser.prev_token.span.shrink_to_hi(), + }); } - } else { - let before = self.parser.token.span.shrink_to_lo(); - while let token::Ident(..) = self.parser.token.kind { - self.parser.bump(); - } - err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { - before, - after: self.parser.prev_token.span.shrink_to_hi(), - }); } - } - - if self.parser.token == token::Minus - && self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Literal { .. })) - { - err.remove_neg_sugg = - Some(InvalidMetaItemRemoveNegSugg { negative_sign: self.parser.token.span }); - self.parser.bump(); - self.parser.bump(); + Ok(None) => {} + Err(e) => { + e.cancel(); + self.parser.restore_snapshot(snapshot); + } } self.parser.dcx().create_err(err) diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 1d68fea34ce60..b0e0c638ecd3f 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -832,7 +832,7 @@ pub(crate) struct InvalidMetaItem { #[subdiagnostic] pub remove_neg_sugg: Option, #[label] - pub macro_call: Option, + pub label: Option, } #[derive(Subdiagnostic)] diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index c76eda65a75b0..219218f034793 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -26,7 +26,7 @@ fn f3() {} #[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on functions fn f4() {} -#[rustc_align(-1)] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +#[rustc_align(-1)] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn f5() {} #[rustc_align(3)] //~ ERROR invalid alignment value: not a power of two diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index 33f789b626952..b419df8ea2d18 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -37,11 +37,11 @@ error[E0589]: invalid alignment value: not a power of two LL | #[rustc_align(0)] | ^ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/malformed-fn-align.rs:29:15 | LL | #[rustc_align(-1)] - | ^ + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs index 378d0a3e72358..cdf2b76a1cccc 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -7,5 +7,5 @@ fn main() { } #[deprecated(note = test)] -//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `test` +//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn foo() {} diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr index cd985ab5a1824..379c7f5812240 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `test` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 | LL | #[deprecated(note = test)] - | ^^^^ + | ^^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs index 606b41e89a5f5..bfd2958ad5659 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.rs +++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs @@ -9,7 +9,7 @@ macro_rules! mac { mac!(an(arbitrary token stream)); #[cfg(feature = -1)] -//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn handler() {} fn main() {} diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index 1d939942fb9a9..8f4edca226d3b 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-bad-meta-4.rs:11:17 | LL | #[cfg(feature = -1)] - | ^ + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs index 8a0c65b783a74..152448bf8a0f9 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.rs +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -4,14 +4,21 @@ fn main() { #[cfg(key=foo)] - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - //~| HELP surround the identifier with quotation marks to make it into a string literal + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here println!(); #[cfg(key="bar")] println!(); #[cfg(key=foo bar baz)] - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - //~| HELP surround the identifier with quotation marks to make it into a string literal + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here + println!(); + #[cfg(key=foo 1 bar 2.0 baz.)] + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here println!(); } @@ -19,7 +26,7 @@ fn main() { macro_rules! make { ($name:ident) => { #[doc(alias = $name)] pub struct S; } - //~^ ERROR expected unsuffixed literal, found identifier `nickname` + //~^ ERROR: expected unsuffixed literal, found identifier `nickname` } -make!(nickname); //~ NOTE in this expansion +make!(nickname); //~ NOTE: in this expansion diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr index 8a2785280adc3..f1af60dec9bbb 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -1,27 +1,38 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-unquoted-ident.rs:6:15 | LL | #[cfg(key=foo)] - | ^^^ + | ^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | LL | #[cfg(key="foo")] | + + -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - --> $DIR/attr-unquoted-ident.rs:12:15 +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/attr-unquoted-ident.rs:13:15 | LL | #[cfg(key=foo bar baz)] - | ^^^ + | ^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | LL | #[cfg(key="foo bar baz")] | + + +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/attr-unquoted-ident.rs:18:15 + | +LL | #[cfg(key=foo 1 bar 2.0 baz.)] + | ^^^ expressions are not allowed here + | +help: surround the identifier with quotation marks to make it into a string literal + | +LL | #[cfg(key="foo 1 bar 2.0 baz.")] + | + + + error: expected unsuffixed literal, found identifier `nickname` - --> $DIR/attr-unquoted-ident.rs:21:38 + --> $DIR/attr-unquoted-ident.rs:28:38 | LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; } | ^^^^^ @@ -31,5 +42,5 @@ LL | make!(nickname); | = note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/parser/macro/expr-in-attribute.rs b/tests/ui/parser/macro/expr-in-attribute.rs new file mode 100644 index 0000000000000..8c8934493361b --- /dev/null +++ b/tests/ui/parser/macro/expr-in-attribute.rs @@ -0,0 +1,9 @@ +// Test for #146325. +// Ensure that when we encounter an expr invocation in an attribute, we don't suggest nonsense. + +#[deprecated(note = a!=b)] +struct X; +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression +//~| NOTE: expressions are not allowed here + +fn main() {} diff --git a/tests/ui/parser/macro/expr-in-attribute.stderr b/tests/ui/parser/macro/expr-in-attribute.stderr new file mode 100644 index 0000000000000..08d6f12d1e641 --- /dev/null +++ b/tests/ui/parser/macro/expr-in-attribute.stderr @@ -0,0 +1,8 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/expr-in-attribute.rs:4:21 + | +LL | #[deprecated(note = a!=b)] + | ^^^^ expressions are not allowed here + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs index 57808c6fd27da..efb7de9f01c4f 100644 --- a/tests/ui/parser/macro/macro-in-attribute.rs +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -3,7 +3,7 @@ #[deprecated(note = concat!("a", "b"))] struct X; -//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found //~| NOTE: macros are not allowed here fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr index e0ae51365a85c..08fb664407574 100644 --- a/tests/ui/parser/macro/macro-in-attribute.stderr +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -1,4 +1,4 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro --> $DIR/macro-in-attribute.rs:4:21 | LL | #[deprecated(note = concat!("a", "b"))] From 9ca819848160f095512727fae6ca04002efcc848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Nov 2025 19:21:31 +0000 Subject: [PATCH 3/3] review comment --- compiler/rustc_ast/src/ast.rs | 2 +- tests/ui/parser/macro/macro-in-attribute.rs | 2 +- tests/ui/parser/macro/macro-in-attribute.stderr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index a4621a7e40bed..f7e97a2f4352c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1255,7 +1255,7 @@ impl StmtKind { StmtKind::Expr(_) => "expression", StmtKind::Semi(_) => "statement", StmtKind::Empty => "semicolon", - StmtKind::MacCall(_) => "macro", + StmtKind::MacCall(_) => "macro call", } } } diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs index efb7de9f01c4f..7a4b3b22baa91 100644 --- a/tests/ui/parser/macro/macro-in-attribute.rs +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -4,6 +4,6 @@ #[deprecated(note = concat!("a", "b"))] struct X; //~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found -//~| NOTE: macros are not allowed here +//~| NOTE: macro calls are not allowed here fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr index 08fb664407574..d057c93ede073 100644 --- a/tests/ui/parser/macro/macro-in-attribute.stderr +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro call --> $DIR/macro-in-attribute.rs:4:21 | LL | #[deprecated(note = concat!("a", "b"))] - | ^^^^^^^^^^^^^^^^^ macros are not allowed here + | ^^^^^^^^^^^^^^^^^ macro calls are not allowed here error: aborting due to 1 previous error