Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions compiler/rustc_expand/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,49 @@ mod metavar_exprs {
pub span: Span,
pub key: MacroRulesNormalizedIdent,
}

#[derive(Diagnostic)]
#[diag(r#"`${"{"}concat(..){"}"}` is not generating a valid identifier"#)]
pub(crate) struct ConcatInvalidIdent {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub reason: InvalidIdentReason,
}

#[derive(Subdiagnostic)]
pub(crate) enum InvalidIdentReason {
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated an empty ident"#)]
Empty,
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$start} is not either '_' or XID_Start"#)]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$start} is not either '_' or XID_Start"#)]
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$start} is not '_' and does not have property XID_Start"#)]

on your taste

Suggested change
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$start} is not either '_' or XID_Start"#)]
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$start} is neither '_' nor XID_Start"#)]

#[note(
"see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers"
)]
InvalidStart { symbol: Symbol, start: char },
#[note(r#"this `${"{"}concat(..){"}"}` invocation generated `{$symbol}`, but {$not_continue} is not XID_Continue"#)]
#[note(
"see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers"
)]
InvalidContinue { symbol: Symbol, not_continue: char },
}

impl InvalidIdentReason {
pub(crate) fn new(symbol: Symbol) -> Self {
let mut chars = symbol.as_str().chars();
if let Some(start) = chars.next() {
if rustc_lexer::is_id_start(start) {
let not_continue = chars
.find(|c| !rustc_lexer::is_id_continue(*c))
.expect("InvalidIdentReason: cannot find invalid ident reason");
InvalidIdentReason::InvalidContinue { symbol, not_continue }
} else {
InvalidIdentReason::InvalidStart { symbol, start }
}
} else {
InvalidIdentReason::Empty
}
}
}
}

#[derive(Diagnostic)]
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_expand/src/mbe/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ use rustc_span::{
use smallvec::{SmallVec, smallvec};

use crate::errors::{
CountRepetitionMisplaced, MacroVarStillRepeating, MetaVarsDifSeqMatchers, MustRepeatOnce,
MveUnrecognizedVar, NoRepeatableVar, NoSyntaxVarsExprRepeat, VarNoTypo,
VarTypoSuggestionRepeatable, VarTypoSuggestionUnrepeatable, VarTypoSuggestionUnrepeatableLabel,
ConcatInvalidIdent, CountRepetitionMisplaced, InvalidIdentReason, MacroVarStillRepeating,
MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoRepeatableVar,
NoSyntaxVarsExprRepeat, VarNoTypo, VarTypoSuggestionRepeatable, VarTypoSuggestionUnrepeatable,
VarTypoSuggestionUnrepeatableLabel,
};
use crate::mbe::macro_parser::NamedMatch;
use crate::mbe::macro_parser::NamedMatch::*;
Expand Down Expand Up @@ -656,10 +657,10 @@ fn metavar_expr_concat<'tx>(
let symbol = nfc_normalize(&concatenated);
let concatenated_span = tscx.visited_dspan(dspan);
if !rustc_lexer::is_ident(symbol.as_str()) {
return Err(dcx.struct_span_err(
concatenated_span,
"`${concat(..)}` is not generating a valid identifier",
));
return Err(dcx.create_err(ConcatInvalidIdent {
span: concatenated_span,
reason: InvalidIdentReason::new(symbol),
}));
}
tscx.psess.symbol_gallery.insert(symbol, concatenated_span);

Expand Down
10 changes: 10 additions & 0 deletions tests/ui/macros/metavar-expressions/concat-trace-errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,28 @@ macro_rules! post_expansion {
($a:literal) => {
const _: () = ${concat("hi", $a, "bye")};
//~^ ERROR is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated `hi!bye`, but '!' is not XID_Continue
//~| NOTE see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers
}
}

post_expansion!("!");
//~^ NOTE in this expansion of post_expansion!
//~| NOTE in this expansion of post_expansion!
//~| NOTE in this expansion of post_expansion!

macro_rules! post_expansion_many {
($a:ident, $b:ident, $c:ident, $d:literal, $e:ident) => {
const _: () = ${concat($a, $b, $c, $d, $e)};
//~^ ERROR is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated `abc.de`, but '.' is not XID_Continue
//~| NOTE see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers
}
}

post_expansion_many!(a, b, c, ".d", e);
//~^ NOTE in this expansion of post_expansion_many!
//~| NOTE in this expansion of post_expansion_many!
//~| NOTE in this expansion of post_expansion_many!

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ LL | const _: () = ${concat("hi", $a, "bye")};
LL | post_expansion!("!");
| -------------------- in this macro invocation
|
= note: this `${concat(..)}` invocation generated `hi!bye`, but '!' is not XID_Continue
= note: see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers
= note: this error originates in the macro `post_expansion` (in Nightly builds, run with -Z macro-backtrace for more info)

error: `${concat(..)}` is not generating a valid identifier
--> $DIR/concat-trace-errors.rs:26:24
--> $DIR/concat-trace-errors.rs:31:24
|
LL | const _: () = ${concat($a, $b, $c, $d, $e)};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | post_expansion_many!(a, b, c, ".d", e);
| -------------------------------------- in this macro invocation
|
= note: this `${concat(..)}` invocation generated `abc.de`, but '.' is not XID_Continue
= note: see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers
= note: this error originates in the macro `post_expansion_many` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/macros/metavar-expressions/concat-usage-errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@ edition: 2021
//@ dont-require-annotations: NOTE

#![feature(macro_metavar_expr_concat)]

Expand Down Expand Up @@ -43,6 +44,7 @@ macro_rules! starting_number {
($ident:ident) => {{
let ${concat("1", $ident)}: () = ();
//~^ ERROR `${concat(..)}` is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated `1_abc`, but '1' is not either '_' or XID_Start
}};
}

Expand All @@ -56,6 +58,8 @@ macro_rules! starting_invalid_unicode {
($ident:ident) => {{
let ${concat("\u{00BD}", $ident)}: () = ();
//~^ ERROR `${concat(..)}` is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated `\u{00BD}_abc`, but '\' is not either '_' or XID_Start
//~| NOTE see <https://doc.rust-lang.org/reference/identifiers.html> for the definition of valid identifiers
}};
}

Expand All @@ -75,13 +79,15 @@ macro_rules! ending_invalid_unicode {
($ident:ident) => {{
let ${concat($ident, "\u{00BD}")}: () = ();
//~^ ERROR `${concat(..)}` is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated `_abc\u{00BD}`, but '\' is not XID_Continue
}};
}

macro_rules! empty {
() => {{
let ${concat("", "")}: () = ();
//~^ ERROR `${concat(..)}` is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated an empty ident
}};
}

Expand Down Expand Up @@ -130,6 +136,8 @@ macro_rules! bad_literal_string {
//~| ERROR `${concat(..)}` is not generating a valid identifier
//~| ERROR `${concat(..)}` is not generating a valid identifier
//~| ERROR `${concat(..)}` is not generating a valid identifier
//~| NOTE this `${concat(..)}` invocation generated `_foo🤷`, but '🤷' is not XID_Continue
//~| NOTE this `${concat(..)}` invocation generated `_foo-1`, but '-' is not XID_Continue
}
}

Expand Down
Loading
Loading