Rollup merge of #143245 - tgross35:metavariable-expr-organization, r=petrochenkov

mbe: Add tests and restructure metavariable expressions

Add tests that show better diagnostics, and factor `concat` handling to a separate function. Each commit message has further details.

This performs the nonfunctional perparation for further changes such as https://github.com/rust-lang/rust/pull/142950 and https://github.com/rust-lang/rust/pull/142975 .
This commit is contained in:
Matthias Krüger
2025-07-01 04:25:36 +02:00
committed by GitHub
33 changed files with 743 additions and 672 deletions

View File

@@ -109,9 +109,6 @@ expand_malformed_feature_attribute =
expand_meta_var_dif_seq_matchers = {$msg} expand_meta_var_dif_seq_matchers = {$msg}
expand_meta_var_expr_unrecognized_var =
variable `{$key}` is not recognized in meta-variable expression
expand_missing_fragment_specifier = missing fragment specifier expand_missing_fragment_specifier = missing fragment specifier
.note = fragment specifiers must be provided .note = fragment specifiers must be provided
.suggestion_add_fragspec = try adding a specifier here .suggestion_add_fragspec = try adding a specifier here
@@ -136,6 +133,9 @@ expand_module_multiple_candidates =
expand_must_repeat_once = expand_must_repeat_once =
this must repeat at least once this must repeat at least once
expand_mve_unrecognized_var =
variable `{$key}` is not recognized in meta-variable expression
expand_non_inline_modules_in_proc_macro_input_are_unstable = expand_non_inline_modules_in_proc_macro_input_are_unstable =
non-inline modules in proc macro input are unstable non-inline modules in proc macro input are unstable

View File

@@ -27,14 +27,6 @@ pub(crate) struct CountRepetitionMisplaced {
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[diag(expand_meta_var_expr_unrecognized_var)]
pub(crate) struct MetaVarExprUnrecognizedVar {
#[primary_span]
pub span: Span,
pub key: MacroRulesNormalizedIdent,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(expand_var_still_repeating)] #[diag(expand_var_still_repeating)]
pub(crate) struct VarStillRepeating { pub(crate) struct VarStillRepeating {
@@ -499,3 +491,16 @@ pub(crate) struct ProcMacroBackCompat {
pub crate_name: String, pub crate_name: String,
pub fixed_version: String, pub fixed_version: String,
} }
pub(crate) use metavar_exprs::*;
mod metavar_exprs {
use super::*;
#[derive(Diagnostic)]
#[diag(expand_mve_unrecognized_var)]
pub(crate) struct MveUnrecognizedVar {
#[primary_span]
pub span: Span,
pub key: MacroRulesNormalizedIdent,
}
}

View File

@@ -47,46 +47,7 @@ impl MetaVarExpr {
check_trailing_token(&mut iter, psess)?; check_trailing_token(&mut iter, psess)?;
let mut iter = args.iter(); let mut iter = args.iter();
let rslt = match ident.as_str() { let rslt = match ident.as_str() {
"concat" => { "concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?,
let mut result = Vec::new();
loop {
let is_var = try_eat_dollar(&mut iter);
let token = parse_token(&mut iter, psess, outer_span)?;
let element = if is_var {
MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
} else if let TokenKind::Literal(Lit {
kind: token::LitKind::Str,
symbol,
suffix: None,
}) = token.kind
{
MetaVarExprConcatElem::Literal(symbol)
} else {
match parse_ident_from_token(psess, token) {
Err(err) => {
err.cancel();
return Err(psess
.dcx()
.struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
}
Ok(elem) => MetaVarExprConcatElem::Ident(elem),
}
};
result.push(element);
if iter.peek().is_none() {
break;
}
if !try_eat_comma(&mut iter) {
return Err(psess.dcx().struct_span_err(outer_span, "expected comma"));
}
}
if result.len() < 2 {
return Err(psess
.dcx()
.struct_span_err(ident.span, "`concat` must have at least two elements"));
}
MetaVarExpr::Concat(result.into())
}
"count" => parse_count(&mut iter, psess, ident.span)?, "count" => parse_count(&mut iter, psess, ident.span)?,
"ignore" => { "ignore" => {
eat_dollar(&mut iter, psess, ident.span)?; eat_dollar(&mut iter, psess, ident.span)?;
@@ -126,20 +87,6 @@ impl MetaVarExpr {
} }
} }
/// Indicates what is placed in a `concat` parameter. For example, literals
/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
#[derive(Debug, Decodable, Encodable, PartialEq)]
pub(crate) enum MetaVarExprConcatElem {
/// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
/// interpreted as a literal.
Ident(Ident),
/// For example, a number or a string.
Literal(Symbol),
/// Identifier WITH a preceding dollar sign, which means that this identifier should be
/// expanded and interpreted as a variable.
Var(Ident),
}
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
fn check_trailing_token<'psess>( fn check_trailing_token<'psess>(
iter: &mut TokenStreamIter<'_>, iter: &mut TokenStreamIter<'_>,
@@ -156,6 +103,64 @@ fn check_trailing_token<'psess>(
} }
} }
/// Indicates what is placed in a `concat` parameter. For example, literals
/// (`${concat("foo", "bar")}`) or adhoc identifiers (`${concat(foo, bar)}`).
#[derive(Debug, Decodable, Encodable, PartialEq)]
pub(crate) enum MetaVarExprConcatElem {
/// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
/// interpreted as a literal.
Ident(Ident),
/// For example, a number or a string.
Literal(Symbol),
/// Identifier WITH a preceding dollar sign, which means that this identifier should be
/// expanded and interpreted as a variable.
Var(Ident),
}
/// Parse a meta-variable `concat` expression: `concat($metavar, ident, ...)`.
fn parse_concat<'psess>(
iter: &mut TokenStreamIter<'_>,
psess: &'psess ParseSess,
outer_span: Span,
expr_ident_span: Span,
) -> PResult<'psess, MetaVarExpr> {
let mut result = Vec::new();
loop {
let is_var = try_eat_dollar(iter);
let token = parse_token(iter, psess, outer_span)?;
let element = if is_var {
MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
} else if let TokenKind::Literal(Lit { kind: token::LitKind::Str, symbol, suffix: None }) =
token.kind
{
MetaVarExprConcatElem::Literal(symbol)
} else {
match parse_ident_from_token(psess, token) {
Err(err) => {
err.cancel();
return Err(psess
.dcx()
.struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
}
Ok(elem) => MetaVarExprConcatElem::Ident(elem),
}
};
result.push(element);
if iter.peek().is_none() {
break;
}
if !try_eat_comma(iter) {
return Err(psess.dcx().struct_span_err(outer_span, "expected comma"));
}
}
if result.len() < 2 {
return Err(psess
.dcx()
.struct_span_err(expr_ident_span, "`concat` must have at least two elements"));
}
Ok(MetaVarExpr::Concat(result.into()))
}
/// Parse a meta-variable `count` expression: `count(ident[, depth])` /// Parse a meta-variable `count` expression: `count(ident[, depth])`
fn parse_count<'psess>( fn parse_count<'psess>(
iter: &mut TokenStreamIter<'_>, iter: &mut TokenStreamIter<'_>,

View File

@@ -17,7 +17,7 @@ use rustc_span::{
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
use crate::errors::{ use crate::errors::{
CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce, CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar,
NoSyntaxVarsExprRepeat, VarStillRepeating, NoSyntaxVarsExprRepeat, VarStillRepeating,
}; };
use crate::mbe::macro_parser::NamedMatch; use crate::mbe::macro_parser::NamedMatch;
@@ -879,7 +879,7 @@ where
{ {
let span = ident.span; let span = ident.span;
let key = MacroRulesNormalizedIdent::new(ident); let key = MacroRulesNormalizedIdent::new(ident);
interp.get(&key).ok_or_else(|| dcx.create_err(MetaVarExprUnrecognizedVar { span, key })) interp.get(&key).ok_or_else(|| dcx.create_err(MveUnrecognizedVar { span, key }))
} }
/// Used by meta-variable expressions when an user input is out of the actual declared bounds. For /// Used by meta-variable expressions when an user input is out of the actual declared bounds. For

View File

@@ -2846,7 +2846,6 @@ ui/macros/issue-98466.rs
ui/macros/issue-99261.rs ui/macros/issue-99261.rs
ui/macros/issue-99265.rs ui/macros/issue-99265.rs
ui/macros/issue-99907.rs ui/macros/issue-99907.rs
ui/macros/rfc-3086-metavar-expr/issue-111904.rs
ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs
ui/malformed/issue-69341-malformed-derive-inert.rs ui/malformed/issue-69341-malformed-derive-inert.rs
ui/marker_trait_attr/issue-61651-type-mismatch.rs ui/marker_trait_attr/issue-61651-type-mismatch.rs

View File

@@ -1,5 +1,5 @@
error[E0425]: cannot find value `abcdef` in this scope error[E0425]: cannot find value `abcdef` in this scope
--> $DIR/hygiene.rs:5:10 --> $DIR/concat-hygiene.rs:5:10
| |
LL | ${concat($lhs, $rhs)} LL | ${concat($lhs, $rhs)}
| ^^^^^^^^^^^^^^^^^^^^ not found in this scope | ^^^^^^^^^^^^^^^^^^^^ not found in this scope

View File

@@ -1,47 +1,47 @@
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/raw-identifiers.rs:28:22 --> $DIR/concat-raw-identifiers.rs:28:22
| |
LL | let ${concat(r#abc, abc)}: () = (); LL | let ${concat(r#abc, abc)}: () = ();
| ^^^^^ | ^^^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/raw-identifiers.rs:32:27 --> $DIR/concat-raw-identifiers.rs:32:27
| |
LL | let ${concat(abc, r#abc)}: () = (); LL | let ${concat(abc, r#abc)}: () = ();
| ^^^^^ | ^^^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/raw-identifiers.rs:35:22 --> $DIR/concat-raw-identifiers.rs:35:22
| |
LL | let ${concat(r#abc, r#abc)}: () = (); LL | let ${concat(r#abc, r#abc)}: () = ();
| ^^^^^ | ^^^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:5:28 --> $DIR/concat-raw-identifiers.rs:5:28
| |
LL | let ${concat(abc, $rhs)}: () = (); LL | let ${concat(abc, $rhs)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:12:23 --> $DIR/concat-raw-identifiers.rs:12:23
| |
LL | let ${concat($lhs, abc)}: () = (); LL | let ${concat($lhs, abc)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:19:23 --> $DIR/concat-raw-identifiers.rs:19:23
| |
LL | let ${concat($lhs, $rhs)}: () = (); LL | let ${concat($lhs, $rhs)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:19:29 --> $DIR/concat-raw-identifiers.rs:19:29
| |
LL | let ${concat($lhs, $rhs)}: () = (); LL | let ${concat($lhs, $rhs)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:19:23 --> $DIR/concat-raw-identifiers.rs:19:23
| |
LL | let ${concat($lhs, $rhs)}: () = (); LL | let ${concat($lhs, $rhs)}: () = ();
| ^^^ | ^^^
@@ -49,31 +49,31 @@ LL | let ${concat($lhs, $rhs)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:42:28 --> $DIR/concat-raw-identifiers.rs:42:28
| |
LL | let ${concat(abc, $rhs)}: () = (); LL | let ${concat(abc, $rhs)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:49:23 --> $DIR/concat-raw-identifiers.rs:49:23
| |
LL | let ${concat($lhs, abc)}: () = (); LL | let ${concat($lhs, abc)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:56:23 --> $DIR/concat-raw-identifiers.rs:56:23
| |
LL | let ${concat($lhs, $rhs)}: () = (); LL | let ${concat($lhs, $rhs)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:56:29 --> $DIR/concat-raw-identifiers.rs:56:29
| |
LL | let ${concat($lhs, $rhs)}: () = (); LL | let ${concat($lhs, $rhs)}: () = ();
| ^^^ | ^^^
error: `${concat(..)}` currently does not support raw identifiers error: `${concat(..)}` currently does not support raw identifiers
--> $DIR/raw-identifiers.rs:56:23 --> $DIR/concat-raw-identifiers.rs:56:23
| |
LL | let ${concat($lhs, $rhs)}: () = (); LL | let ${concat($lhs, $rhs)}: () = ();
| ^^^ | ^^^
@@ -81,7 +81,7 @@ LL | let ${concat($lhs, $rhs)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: expected pattern, found `$` error: expected pattern, found `$`
--> $DIR/raw-identifiers.rs:28:13 --> $DIR/concat-raw-identifiers.rs:28:13
| |
LL | let ${concat(r#abc, abc)}: () = (); LL | let ${concat(r#abc, abc)}: () = ();
| ^ expected pattern | ^ expected pattern

View File

@@ -1,17 +1,17 @@
error: invalid syntax error: invalid syntax
--> $DIR/repetitions.rs:14:20 --> $DIR/concat-repetitions.rs:14:20
| |
LL | const ${concat($a, Z)}: i32 = 3; LL | const ${concat($a, Z)}: i32 = 3;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: invalid syntax error: invalid syntax
--> $DIR/repetitions.rs:22:17 --> $DIR/concat-repetitions.rs:22:17
| |
LL | read::<${concat($t, $en)}>() LL | read::<${concat($t, $en)}>()
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: invalid syntax error: invalid syntax
--> $DIR/repetitions.rs:22:17 --> $DIR/concat-repetitions.rs:22:17
| |
LL | read::<${concat($t, $en)}>() LL | read::<${concat($t, $en)}>()
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^

View File

@@ -0,0 +1,33 @@
// Our diagnostics should be able to point to a specific input that caused an invalid
// identifier.
#![feature(macro_metavar_expr_concat)]
// See what we can do without expanding anything
macro_rules! pre_expansion {
($a:ident) => {
${concat("hi", " bye ")};
${concat("hi", "-", "bye")};
${concat($a, "-")};
}
}
macro_rules! post_expansion {
($a:literal) => {
const _: () = ${concat("hi", $a, "bye")};
//~^ ERROR is not generating a valid identifier
}
}
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
}
}
post_expansion_many!(a, b, c, ".d", e);
fn main() {}

View File

@@ -0,0 +1,24 @@
error: `${concat(..)}` is not generating a valid identifier
--> $DIR/concat-trace-errors.rs:17:24
|
LL | const _: () = ${concat("hi", $a, "bye")};
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | post_expansion!("!");
| -------------------- in this macro invocation
|
= 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
|
LL | const _: () = ${concat($a, $b, $c, $d, $e)};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | post_expansion_many!(a, b, c, ".d", e);
| -------------------------------------- in this macro invocation
|
= 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

View File

@@ -1,6 +1,8 @@
//@ edition: 2021
#![feature(macro_metavar_expr_concat)] #![feature(macro_metavar_expr_concat)]
macro_rules! wrong_concat_declarations { macro_rules! syntax_errors {
($ex:expr) => { ($ex:expr) => {
${concat()} ${concat()}
//~^ ERROR expected identifier //~^ ERROR expected identifier
@@ -90,11 +92,31 @@ macro_rules! unsupported_literals {
//~| ERROR expected pattern //~| ERROR expected pattern
let ${concat(_a, 1)}: () = (); let ${concat(_a, 1)}: () = ();
//~^ ERROR expected identifier or string literal //~^ ERROR expected identifier or string literal
let ${concat(_a, 1.5)}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat(_a, c"hi")}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat(_a, b"hi")}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat(_a, b'b')}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat(_a, b'b')}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat($ident, 'b')}: () = (); let ${concat($ident, 'b')}: () = ();
//~^ ERROR expected identifier or string literal //~^ ERROR expected identifier or string literal
let ${concat($ident, 1)}: () = (); let ${concat($ident, 1)}: () = ();
//~^ ERROR expected identifier or string literal //~^ ERROR expected identifier or string literal
let ${concat($ident, 1.5)}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat($ident, c"hi")}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat($ident, b"hi")}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat($ident, b'b')}: () = ();
//~^ ERROR expected identifier or string literal
let ${concat($ident, b'b')}: () = ();
//~^ ERROR expected identifier or string literal
}}; }};
} }
@@ -132,7 +154,7 @@ macro_rules! bad_tt_literal {
} }
fn main() { fn main() {
wrong_concat_declarations!(1); syntax_errors!(1);
dollar_sign_without_referenced_ident!(VAR); dollar_sign_without_referenced_ident!(VAR);

View File

@@ -1,71 +1,131 @@
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:5:10 --> $DIR/concat-usage-errors.rs:7:10
| |
LL | ${concat()} LL | ${concat()}
| ^^^^^^^^^^ | ^^^^^^^^^^
error: `concat` must have at least two elements error: `concat` must have at least two elements
--> $DIR/syntax-errors.rs:8:11 --> $DIR/concat-usage-errors.rs:10:11
| |
LL | ${concat(aaaa)} LL | ${concat(aaaa)}
| ^^^^^^ | ^^^^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:11:10 --> $DIR/concat-usage-errors.rs:13:10
| |
LL | ${concat(aaaa,)} LL | ${concat(aaaa,)}
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: expected comma error: expected comma
--> $DIR/syntax-errors.rs:16:10 --> $DIR/concat-usage-errors.rs:18:10
| |
LL | ${concat(aaaa aaaa)} LL | ${concat(aaaa aaaa)}
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: `concat` must have at least two elements error: `concat` must have at least two elements
--> $DIR/syntax-errors.rs:19:11 --> $DIR/concat-usage-errors.rs:21:11
| |
LL | ${concat($ex)} LL | ${concat($ex)}
| ^^^^^^ | ^^^^^^
error: expected comma error: expected comma
--> $DIR/syntax-errors.rs:25:10 --> $DIR/concat-usage-errors.rs:27:10
| |
LL | ${concat($ex, aaaa 123)} LL | ${concat($ex, aaaa 123)}
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:28:10 --> $DIR/concat-usage-errors.rs:30:10
| |
LL | ${concat($ex, aaaa,)} LL | ${concat($ex, aaaa,)}
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:88:26 --> $DIR/concat-usage-errors.rs:90:26
| |
LL | let ${concat(_a, 'b')}: () = (); LL | let ${concat(_a, 'b')}: () = ();
| ^^^ | ^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:91:26 --> $DIR/concat-usage-errors.rs:93:26
| |
LL | let ${concat(_a, 1)}: () = (); LL | let ${concat(_a, 1)}: () = ();
| ^ | ^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:94:30 --> $DIR/concat-usage-errors.rs:95:26
|
LL | let ${concat(_a, 1.5)}: () = ();
| ^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:97:26
|
LL | let ${concat(_a, c"hi")}: () = ();
| ^^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:99:26
|
LL | let ${concat(_a, b"hi")}: () = ();
| ^^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:101:26
|
LL | let ${concat(_a, b'b')}: () = ();
| ^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:103:26
|
LL | let ${concat(_a, b'b')}: () = ();
| ^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:106:30
| |
LL | let ${concat($ident, 'b')}: () = (); LL | let ${concat($ident, 'b')}: () = ();
| ^^^ | ^^^
error: expected identifier or string literal error: expected identifier or string literal
--> $DIR/syntax-errors.rs:96:30 --> $DIR/concat-usage-errors.rs:108:30
| |
LL | let ${concat($ident, 1)}: () = (); LL | let ${concat($ident, 1)}: () = ();
| ^ | ^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:110:30
|
LL | let ${concat($ident, 1.5)}: () = ();
| ^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:112:30
|
LL | let ${concat($ident, c"hi")}: () = ();
| ^^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:114:30
|
LL | let ${concat($ident, b"hi")}: () = ();
| ^^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:116:30
|
LL | let ${concat($ident, b'b')}: () = ();
| ^^^^
error: expected identifier or string literal
--> $DIR/concat-usage-errors.rs:118:30
|
LL | let ${concat($ident, b'b')}: () = ();
| ^^^^
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:22:19 --> $DIR/concat-usage-errors.rs:24:19
| |
LL | ${concat($ex, aaaa)} LL | ${concat($ex, aaaa)}
| ^^ | ^^
@@ -73,13 +133,13 @@ LL | ${concat($ex, aaaa)}
= note: currently only string literals are supported = note: currently only string literals are supported
error: variable `foo` is not recognized in meta-variable expression error: variable `foo` is not recognized in meta-variable expression
--> $DIR/syntax-errors.rs:35:30 --> $DIR/concat-usage-errors.rs:37:30
| |
LL | const ${concat(FOO, $foo)}: i32 = 2; LL | const ${concat(FOO, $foo)}: i32 = 2;
| ^^^ | ^^^
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:42:14 --> $DIR/concat-usage-errors.rs:44:14
| |
LL | let ${concat("1", $ident)}: () = (); LL | let ${concat("1", $ident)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +150,7 @@ LL | starting_number!(_abc);
= note: this error originates in the macro `starting_number` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `starting_number` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:55:14 --> $DIR/concat-usage-errors.rs:57:14
| |
LL | let ${concat("\u{00BD}", $ident)}: () = (); LL | let ${concat("\u{00BD}", $ident)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -101,7 +161,7 @@ LL | starting_invalid_unicode!(_abc);
= note: this error originates in the macro `starting_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `starting_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:74:14 --> $DIR/concat-usage-errors.rs:76:14
| |
LL | let ${concat($ident, "\u{00BD}")}: () = (); LL | let ${concat($ident, "\u{00BD}")}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +172,7 @@ LL | ending_invalid_unicode!(_abc);
= note: this error originates in the macro `ending_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `ending_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected pattern, found `$` error: expected pattern, found `$`
--> $DIR/syntax-errors.rs:88:13 --> $DIR/concat-usage-errors.rs:90:13
| |
LL | let ${concat(_a, 'b')}: () = (); LL | let ${concat(_a, 'b')}: () = ();
| ^ expected pattern | ^ expected pattern
@@ -123,7 +183,7 @@ LL | unsupported_literals!(_abc);
= note: this error originates in the macro `unsupported_literals` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `unsupported_literals` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:81:14 --> $DIR/concat-usage-errors.rs:83:14
| |
LL | let ${concat("", "")}: () = (); LL | let ${concat("", "")}: () = ();
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
@@ -134,7 +194,7 @@ LL | empty!();
= note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -145,7 +205,7 @@ LL | bad_literal_string!("\u{00BD}");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -156,7 +216,7 @@ LL | bad_literal_string!("\x41");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -167,7 +227,7 @@ LL | bad_literal_string!("🤷");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -178,7 +238,7 @@ LL | bad_literal_string!("d[-_-]b");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -189,7 +249,7 @@ LL | bad_literal_string!("-1");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -200,7 +260,7 @@ LL | bad_literal_string!("1.0");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `${concat(..)}` is not generating a valid identifier error: `${concat(..)}` is not generating a valid identifier
--> $DIR/syntax-errors.rs:103:16 --> $DIR/concat-usage-errors.rs:125:16
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -211,7 +271,7 @@ LL | bad_literal_string!("'1'");
= note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info)
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:116:31 --> $DIR/concat-usage-errors.rs:138:31
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^ | ^^^^^^^
@@ -219,7 +279,7 @@ LL | const ${concat(_foo, $literal)}: () = ();
= note: currently only string literals are supported = note: currently only string literals are supported
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:116:31 --> $DIR/concat-usage-errors.rs:138:31
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^ | ^^^^^^^
@@ -228,7 +288,7 @@ LL | const ${concat(_foo, $literal)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:116:31 --> $DIR/concat-usage-errors.rs:138:31
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^ | ^^^^^^^
@@ -237,7 +297,7 @@ LL | const ${concat(_foo, $literal)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:116:31 --> $DIR/concat-usage-errors.rs:138:31
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^ | ^^^^^^^
@@ -246,7 +306,7 @@ LL | const ${concat(_foo, $literal)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:116:31 --> $DIR/concat-usage-errors.rs:138:31
| |
LL | const ${concat(_foo, $literal)}: () = (); LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^ | ^^^^^^^
@@ -255,7 +315,7 @@ LL | const ${concat(_foo, $literal)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:127:31 --> $DIR/concat-usage-errors.rs:149:31
| |
LL | const ${concat(_foo, $tt)}: () = (); LL | const ${concat(_foo, $tt)}: () = ();
| ^^ | ^^
@@ -263,7 +323,7 @@ LL | const ${concat(_foo, $tt)}: () = ();
= note: currently only string literals are supported = note: currently only string literals are supported
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:127:31 --> $DIR/concat-usage-errors.rs:149:31
| |
LL | const ${concat(_foo, $tt)}: () = (); LL | const ${concat(_foo, $tt)}: () = ();
| ^^ | ^^
@@ -272,7 +332,7 @@ LL | const ${concat(_foo, $tt)}: () = ();
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/syntax-errors.rs:127:31 --> $DIR/concat-usage-errors.rs:149:31
| |
LL | const ${concat(_foo, $tt)}: () = (); LL | const ${concat(_foo, $tt)}: () = ();
| ^^ | ^^
@@ -280,5 +340,5 @@ LL | const ${concat(_foo, $tt)}: () = ();
= note: currently only string literals are supported = note: currently only string literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 33 previous errors error: aborting due to 43 previous errors

View File

@@ -1,3 +1,6 @@
// Issue: https://github.com/rust-lang/rust/issues/111904
// Ensure that a trailing `,` is not interpreted as a `0`.
#![feature(macro_metavar_expr)] #![feature(macro_metavar_expr)]
macro_rules! foo { macro_rules! foo {
@@ -10,5 +13,4 @@ fn test() {
foo!(a, a; b, b); foo!(a, a; b, b);
} }
fn main() { fn main() {}
}

View File

@@ -1,11 +1,11 @@
error: `count` followed by a comma must have an associated index indicating its depth error: `count` followed by a comma must have an associated index indicating its depth
--> $DIR/issue-111904.rs:4:37 --> $DIR/count-empty-index-arg.rs:7:37
| |
LL | ( $( $($t:ident),* );* ) => { ${count($t,)} } LL | ( $( $($t:ident),* );* ) => { ${count($t,)} }
| ^^^^^ | ^^^^^
error: expected expression, found `$` error: expected expression, found `$`
--> $DIR/issue-111904.rs:4:35 --> $DIR/count-empty-index-arg.rs:7:35
| |
LL | ( $( $($t:ident),* );* ) => { ${count($t,)} } LL | ( $( $($t:ident),* );* ) => { ${count($t,)} }
| ^ expected expression | ^ expected expression

View File

@@ -0,0 +1,117 @@
// General syntax errors that apply to all matavariable expressions
//
// We don't invoke the macros here to ensure code gets rejected at the definition rather than
// only when expanded.
#![feature(macro_metavar_expr)]
macro_rules! dollar_dollar_in_the_lhs {
( $$ $a:ident ) => {
//~^ ERROR unexpected token: $
};
}
macro_rules! metavar_in_the_lhs {
( ${ len() } ) => {
//~^ ERROR unexpected token: {
//~| ERROR expected one of: `*`, `+`, or `?`
};
}
macro_rules! metavar_token_without_ident {
( $( $i:ident ),* ) => { ${ ignore() } };
//~^ ERROR meta-variable expressions must be referenced using a dollar sign
}
macro_rules! metavar_with_literal_suffix {
( $( $i:ident ),* ) => { ${ index(1u32) } };
//~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions
}
macro_rules! mve_without_parens {
( $( $i:ident ),* ) => { ${ count } };
//~^ ERROR meta-variable expression parameter must be wrapped in parentheses
}
#[rustfmt::skip]
macro_rules! empty_expression {
() => { ${} };
//~^ ERROR expected identifier or string literal
}
#[rustfmt::skip]
macro_rules! open_brackets_with_lit {
() => { ${ "hi" } };
//~^ ERROR expected identifier
}
macro_rules! mve_wrong_delim {
( $( $i:ident ),* ) => { ${ count{i} } };
//~^ ERROR meta-variable expression parameter must be wrapped in parentheses
}
macro_rules! invalid_metavar {
() => { ${ignore($123)} }
//~^ ERROR expected identifier, found `123`
}
#[rustfmt::skip]
macro_rules! open_brackets_with_group {
( $( $i:ident ),* ) => { ${ {} } };
//~^ ERROR expected identifier
}
macro_rules! extra_garbage_after_metavar {
( $( $i:ident ),* ) => {
${count() a b c}
//~^ ERROR unexpected token: a
${count($i a b c)}
//~^ ERROR unexpected token: a
${count($i, 1 a b c)}
//~^ ERROR unexpected token: a
${count($i) a b c}
//~^ ERROR unexpected token: a
${ignore($i) a b c}
//~^ ERROR unexpected token: a
${ignore($i a b c)}
//~^ ERROR unexpected token: a
${index() a b c}
//~^ ERROR unexpected token: a
${index(1 a b c)}
//~^ ERROR unexpected token: a
${index() a b c}
//~^ ERROR unexpected token: a
${index(1 a b c)}
//~^ ERROR unexpected token: a
};
}
const IDX: usize = 1;
macro_rules! metavar_depth_is_not_literal {
( $( $i:ident ),* ) => { ${ index(IDX) } };
//~^ ERROR meta-variable expression depth must be a literal
}
macro_rules! unknown_count_ident {
( $( $i:ident )* ) => {
${count(foo)}
//~^ ERROR meta-variable expressions must be referenced using a dollar sign
};
}
macro_rules! unknown_ignore_ident {
( $( $i:ident )* ) => {
${ignore(bar)}
//~^ ERROR meta-variable expressions must be referenced using a dollar sign
};
}
macro_rules! unknown_metavar {
( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
//~^ ERROR unrecognized meta-variable expression
}
fn main() {}

View File

@@ -0,0 +1,224 @@
error: unexpected token: $
--> $DIR/syntax-errors.rs:9:8
|
LL | ( $$ $a:ident ) => {
| ^
note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
--> $DIR/syntax-errors.rs:9:8
|
LL | ( $$ $a:ident ) => {
| ^
error: unexpected token: {
--> $DIR/syntax-errors.rs:15:8
|
LL | ( ${ len() } ) => {
| ^^^^^^^^^
note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
--> $DIR/syntax-errors.rs:15:8
|
LL | ( ${ len() } ) => {
| ^^^^^^^^^
error: expected one of: `*`, `+`, or `?`
--> $DIR/syntax-errors.rs:15:8
|
LL | ( ${ len() } ) => {
| ^^^^^^^^^
error: meta-variables within meta-variable expressions must be referenced using a dollar sign
--> $DIR/syntax-errors.rs:22:33
|
LL | ( $( $i:ident ),* ) => { ${ ignore() } };
| ^^^^^^
error: only unsuffixes integer literals are supported in meta-variable expressions
--> $DIR/syntax-errors.rs:27:33
|
LL | ( $( $i:ident ),* ) => { ${ index(1u32) } };
| ^^^^^
error: meta-variable expression parameter must be wrapped in parentheses
--> $DIR/syntax-errors.rs:32:33
|
LL | ( $( $i:ident ),* ) => { ${ count } };
| ^^^^^
error: meta-variable expression parameter must be wrapped in parentheses
--> $DIR/syntax-errors.rs:49:33
|
LL | ( $( $i:ident ),* ) => { ${ count{i} } };
| ^^^^^
error: expected identifier, found `123`
--> $DIR/syntax-errors.rs:54:23
|
LL | () => { ${ignore($123)} }
| ^^^ help: try removing `123`
error: unexpected token: a
--> $DIR/syntax-errors.rs:66:19
|
LL | ${count() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:66:19
|
LL | ${count() a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:68:20
|
LL | ${count($i a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:68:20
|
LL | ${count($i a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:70:23
|
LL | ${count($i, 1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:70:23
|
LL | ${count($i, 1 a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:72:21
|
LL | ${count($i) a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:72:21
|
LL | ${count($i) a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:75:22
|
LL | ${ignore($i) a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:75:22
|
LL | ${ignore($i) a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:77:21
|
LL | ${ignore($i a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:77:21
|
LL | ${ignore($i a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:80:19
|
LL | ${index() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:80:19
|
LL | ${index() a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:82:19
|
LL | ${index(1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:82:19
|
LL | ${index(1 a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:85:19
|
LL | ${index() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:85:19
|
LL | ${index() a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:87:19
|
LL | ${index(1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:87:19
|
LL | ${index(1 a b c)}
| ^
error: meta-variable expression depth must be a literal
--> $DIR/syntax-errors.rs:94:33
|
LL | ( $( $i:ident ),* ) => { ${ index(IDX) } };
| ^^^^^
error: meta-variables within meta-variable expressions must be referenced using a dollar sign
--> $DIR/syntax-errors.rs:100:11
|
LL | ${count(foo)}
| ^^^^^
error: meta-variables within meta-variable expressions must be referenced using a dollar sign
--> $DIR/syntax-errors.rs:107:11
|
LL | ${ignore(bar)}
| ^^^^^^
error: unrecognized meta-variable expression
--> $DIR/syntax-errors.rs:113:33
|
LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
| ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len
error: expected identifier or string literal
--> $DIR/syntax-errors.rs:38:14
|
LL | () => { ${} };
| ^^
error: expected identifier, found `"hi"`
--> $DIR/syntax-errors.rs:44:17
|
LL | () => { ${ "hi" } };
| ^^^^ help: try removing `"hi"`
error: expected identifier or string literal
--> $DIR/syntax-errors.rs:60:33
|
LL | ( $( $i:ident ),* ) => { ${ {} } };
| ^^
error: aborting due to 25 previous errors

View File

@@ -0,0 +1,55 @@
// Errors for the `count` and `length` metavariable expressions
#![feature(macro_metavar_expr)]
// `curly` = Right hand side curly brackets
// `no_rhs_dollar` = No dollar sign at the right hand side meta variable "function"
// `round` = Left hand side round brackets
macro_rules! curly__no_rhs_dollar__round {
( $( $i:ident ),* ) => { ${ count($i) } };
}
const _: u32 = curly__no_rhs_dollar__round!(a, b, c);
macro_rules! curly__no_rhs_dollar__no_round {
( $i:ident ) => { ${ count($i) } };
//~^ ERROR `count` can not be placed inside the innermost repetition
}
curly__no_rhs_dollar__no_round!(a);
macro_rules! curly__rhs_dollar__no_round {
( $i:ident ) => { ${ count($i) } };
//~^ ERROR `count` can not be placed inside the innermost repetition
}
curly__rhs_dollar__no_round !(a);
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__no_rhs_dollar__round {
( $( $i:ident ),* ) => { count(i) };
//~^ ERROR missing `fn` or `struct` for function or struct definition
}
no_curly__no_rhs_dollar__round !(a, b, c);
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__no_rhs_dollar__no_round {
( $i:ident ) => { count(i) };
//~^ ERROR missing `fn` or `struct` for function or struct definition
}
no_curly__no_rhs_dollar__no_round !(a);
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__rhs_dollar__round {
( $( $i:ident ),* ) => { count($i) };
//~^ ERROR variable `i` is still repeating at this depth
}
no_curly__rhs_dollar__round! (a);
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__rhs_dollar__no_round {
( $i:ident ) => { count($i) };
//~^ ERROR cannot find function `count` in this scope
}
const _: u32 = no_curly__rhs_dollar__no_round! (a);
//~^ ERROR cannot find value `a` in this scope
fn main() {}

View File

@@ -0,0 +1,71 @@
error: `count` can not be placed inside the innermost repetition
--> $DIR/usage-errors.rs:15:24
|
LL | ( $i:ident ) => { ${ count($i) } };
| ^^^^^^^^^^^^^
error: `count` can not be placed inside the innermost repetition
--> $DIR/usage-errors.rs:21:24
|
LL | ( $i:ident ) => { ${ count($i) } };
| ^^^^^^^^^^^^^
error: missing `fn` or `struct` for function or struct definition
--> $DIR/usage-errors.rs:28:30
|
LL | ( $( $i:ident ),* ) => { count(i) };
| ^^^^^
...
LL | no_curly__no_rhs_dollar__round !(a, b, c);
| ----------------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
help: if you meant to call a macro, try
|
LL | ( $( $i:ident ),* ) => { count!(i) };
| +
error: missing `fn` or `struct` for function or struct definition
--> $DIR/usage-errors.rs:35:23
|
LL | ( $i:ident ) => { count(i) };
| ^^^^^
...
LL | no_curly__no_rhs_dollar__no_round !(a);
| -------------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
help: if you meant to call a macro, try
|
LL | ( $i:ident ) => { count!(i) };
| +
error: variable `i` is still repeating at this depth
--> $DIR/usage-errors.rs:42:36
|
LL | ( $( $i:ident ),* ) => { count($i) };
| ^^
error[E0425]: cannot find value `a` in this scope
--> $DIR/usage-errors.rs:52:49
|
LL | ( $i:ident ) => { count($i) };
| -- due to this macro variable
...
LL | const _: u32 = no_curly__rhs_dollar__no_round! (a);
| ^ not found in this scope
error[E0425]: cannot find function `count` in this scope
--> $DIR/usage-errors.rs:49:23
|
LL | ( $i:ident ) => { count($i) };
| ^^^^^ not found in this scope
...
LL | const _: u32 = no_curly__rhs_dollar__no_round! (a);
| ----------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0425`.

View File

@@ -1,164 +0,0 @@
#![feature(macro_metavar_expr)]
// `curly` = Right hand side curly brackets
// `no_rhs_dollar` = No dollar sign at the right hand side meta variable "function"
// `round` = Left hand side round brackets
macro_rules! curly__no_rhs_dollar__round {
( $( $i:ident ),* ) => { ${ count($i) } };
}
macro_rules! curly__no_rhs_dollar__no_round {
( $i:ident ) => { ${ count($i) } };
//~^ ERROR `count` can not be placed inside the innermost repetition
}
macro_rules! curly__rhs_dollar__no_round {
( $i:ident ) => { ${ count($i) } };
//~^ ERROR `count` can not be placed inside the innermost repetition
}
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__no_rhs_dollar__round {
( $( $i:ident ),* ) => { count(i) };
//~^ ERROR cannot find function `count` in this scope
//~| ERROR cannot find value `i` in this scope
}
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__no_rhs_dollar__no_round {
( $i:ident ) => { count(i) };
//~^ ERROR cannot find function `count` in this scope
//~| ERROR cannot find value `i` in this scope
}
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__rhs_dollar__round {
( $( $i:ident ),* ) => { count($i) };
//~^ ERROR variable `i` is still repeating at this depth
}
#[rustfmt::skip] // autoformatters can break a few of the error traces
macro_rules! no_curly__rhs_dollar__no_round {
( $i:ident ) => { count($i) };
//~^ ERROR cannot find function `count` in this scope
}
// Other scenarios
macro_rules! dollar_dollar_in_the_lhs {
( $$ $a:ident ) => {
//~^ ERROR unexpected token: $
};
}
macro_rules! extra_garbage_after_metavar {
( $( $i:ident ),* ) => {
${count() a b c}
//~^ ERROR unexpected token: a
//~| ERROR expected expression, found `$`
${count($i a b c)}
//~^ ERROR unexpected token: a
${count($i, 1 a b c)}
//~^ ERROR unexpected token: a
${count($i) a b c}
//~^ ERROR unexpected token: a
${ignore($i) a b c}
//~^ ERROR unexpected token: a
${ignore($i a b c)}
//~^ ERROR unexpected token: a
${index() a b c}
//~^ ERROR unexpected token: a
${index(1 a b c)}
//~^ ERROR unexpected token: a
${index() a b c}
//~^ ERROR unexpected token: a
${index(1 a b c)}
//~^ ERROR unexpected token: a
};
}
const IDX: usize = 1;
macro_rules! metavar_depth_is_not_literal {
( $( $i:ident ),* ) => { ${ index(IDX) } };
//~^ ERROR meta-variable expression depth must be a literal
//~| ERROR expected expression, found `$`
}
macro_rules! metavar_in_the_lhs {
( ${ len() } ) => {
//~^ ERROR unexpected token: {
//~| ERROR expected one of: `*`, `+`, or `?`
};
}
macro_rules! metavar_token_without_ident {
( $( $i:ident ),* ) => { ${ ignore() } };
//~^ ERROR meta-variable expressions must be referenced using a dollar sign
//~| ERROR expected expression
}
macro_rules! metavar_with_literal_suffix {
( $( $i:ident ),* ) => { ${ index(1u32) } };
//~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions
//~| ERROR expected expression, found `$`
}
macro_rules! metavar_without_parens {
( $( $i:ident ),* ) => { ${ count{i} } };
//~^ ERROR meta-variable expression parameter must be wrapped in parentheses
//~| ERROR expected expression, found `$`
}
#[rustfmt::skip]
macro_rules! open_brackets_without_tokens {
( $( $i:ident ),* ) => { ${ {} } };
//~^ ERROR expected expression, found `$`
//~| ERROR expected identifier
}
macro_rules! unknown_count_ident {
( $( $i:ident )* ) => {
${count(foo)}
//~^ ERROR meta-variable expressions must be referenced using a dollar sign
//~| ERROR expected expression
};
}
macro_rules! unknown_ignore_ident {
( $( $i:ident )* ) => {
${ignore(bar)}
//~^ ERROR meta-variable expressions must be referenced using a dollar sign
//~| ERROR expected expression
};
}
macro_rules! unknown_metavar {
( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
//~^ ERROR unrecognized meta-variable expression
//~| ERROR expected expression
}
fn main() {
curly__no_rhs_dollar__round!(a, b, c);
curly__no_rhs_dollar__no_round!(a);
curly__rhs_dollar__no_round!(a);
no_curly__no_rhs_dollar__round!(a, b, c);
no_curly__no_rhs_dollar__no_round!(a);
no_curly__rhs_dollar__round!(a, b, c);
no_curly__rhs_dollar__no_round!(a);
//~^ ERROR cannot find value `a` in this scope
extra_garbage_after_metavar!(a);
metavar_depth_is_not_literal!(a);
metavar_token_without_ident!(a);
metavar_with_literal_suffix!(a);
metavar_without_parens!(a);
open_brackets_without_tokens!(a);
unknown_count_ident!(a);
unknown_ignore_ident!(a);
unknown_metavar!(a);
}

View File

@@ -1,382 +0,0 @@
error: unexpected token: $
--> $DIR/syntax-errors.rs:50:8
|
LL | ( $$ $a:ident ) => {
| ^
note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
--> $DIR/syntax-errors.rs:50:8
|
LL | ( $$ $a:ident ) => {
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:57:19
|
LL | ${count() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:57:19
|
LL | ${count() a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:60:20
|
LL | ${count($i a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:60:20
|
LL | ${count($i a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:62:23
|
LL | ${count($i, 1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:62:23
|
LL | ${count($i, 1 a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:64:21
|
LL | ${count($i) a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:64:21
|
LL | ${count($i) a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:67:22
|
LL | ${ignore($i) a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:67:22
|
LL | ${ignore($i) a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:69:21
|
LL | ${ignore($i a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:69:21
|
LL | ${ignore($i a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:72:19
|
LL | ${index() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:72:19
|
LL | ${index() a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:74:19
|
LL | ${index(1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:74:19
|
LL | ${index(1 a b c)}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:77:19
|
LL | ${index() a b c}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:77:19
|
LL | ${index() a b c}
| ^
error: unexpected token: a
--> $DIR/syntax-errors.rs:79:19
|
LL | ${index(1 a b c)}
| ^
|
note: meta-variable expression must not have trailing tokens
--> $DIR/syntax-errors.rs:79:19
|
LL | ${index(1 a b c)}
| ^
error: meta-variable expression depth must be a literal
--> $DIR/syntax-errors.rs:86:33
|
LL | ( $( $i:ident ),* ) => { ${ index(IDX) } };
| ^^^^^
error: unexpected token: {
--> $DIR/syntax-errors.rs:92:8
|
LL | ( ${ len() } ) => {
| ^^^^^^^^^
note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions
--> $DIR/syntax-errors.rs:92:8
|
LL | ( ${ len() } ) => {
| ^^^^^^^^^
error: expected one of: `*`, `+`, or `?`
--> $DIR/syntax-errors.rs:92:8
|
LL | ( ${ len() } ) => {
| ^^^^^^^^^
error: meta-variables within meta-variable expressions must be referenced using a dollar sign
--> $DIR/syntax-errors.rs:99:33
|
LL | ( $( $i:ident ),* ) => { ${ ignore() } };
| ^^^^^^
error: only unsuffixes integer literals are supported in meta-variable expressions
--> $DIR/syntax-errors.rs:105:33
|
LL | ( $( $i:ident ),* ) => { ${ index(1u32) } };
| ^^^^^
error: meta-variable expression parameter must be wrapped in parentheses
--> $DIR/syntax-errors.rs:111:33
|
LL | ( $( $i:ident ),* ) => { ${ count{i} } };
| ^^^^^
error: meta-variables within meta-variable expressions must be referenced using a dollar sign
--> $DIR/syntax-errors.rs:125:11
|
LL | ${count(foo)}
| ^^^^^
error: meta-variables within meta-variable expressions must be referenced using a dollar sign
--> $DIR/syntax-errors.rs:133:11
|
LL | ${ignore(bar)}
| ^^^^^^
error: unrecognized meta-variable expression
--> $DIR/syntax-errors.rs:140:33
|
LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
| ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len
error: expected identifier or string literal
--> $DIR/syntax-errors.rs:118:33
|
LL | ( $( $i:ident ),* ) => { ${ {} } };
| ^^
error: `count` can not be placed inside the innermost repetition
--> $DIR/syntax-errors.rs:12:24
|
LL | ( $i:ident ) => { ${ count($i) } };
| ^^^^^^^^^^^^^
error: `count` can not be placed inside the innermost repetition
--> $DIR/syntax-errors.rs:17:24
|
LL | ( $i:ident ) => { ${ count($i) } };
| ^^^^^^^^^^^^^
error: variable `i` is still repeating at this depth
--> $DIR/syntax-errors.rs:37:36
|
LL | ( $( $i:ident ),* ) => { count($i) };
| ^^
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:57:9
|
LL | ${count() a b c}
| ^ expected expression
...
LL | extra_garbage_after_metavar!(a);
| ------------------------------- in this macro invocation
|
= note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:86:30
|
LL | ( $( $i:ident ),* ) => { ${ index(IDX) } };
| ^ expected expression
...
LL | metavar_depth_is_not_literal!(a);
| -------------------------------- in this macro invocation
|
= note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:99:30
|
LL | ( $( $i:ident ),* ) => { ${ ignore() } };
| ^ expected expression
...
LL | metavar_token_without_ident!(a);
| ------------------------------- in this macro invocation
|
= note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:105:30
|
LL | ( $( $i:ident ),* ) => { ${ index(1u32) } };
| ^ expected expression
...
LL | metavar_with_literal_suffix!(a);
| ------------------------------- in this macro invocation
|
= note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:111:30
|
LL | ( $( $i:ident ),* ) => { ${ count{i} } };
| ^ expected expression
...
LL | metavar_without_parens!(a);
| -------------------------- in this macro invocation
|
= note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:118:30
|
LL | ( $( $i:ident ),* ) => { ${ {} } };
| ^ expected expression
...
LL | open_brackets_without_tokens!(a);
| -------------------------------- in this macro invocation
|
= note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:125:9
|
LL | ${count(foo)}
| ^ expected expression
...
LL | unknown_count_ident!(a);
| ----------------------- in this macro invocation
|
= note: this error originates in the macro `unknown_count_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:133:9
|
LL | ${ignore(bar)}
| ^ expected expression
...
LL | unknown_ignore_ident!(a);
| ------------------------ in this macro invocation
|
= note: this error originates in the macro `unknown_ignore_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected expression, found `$`
--> $DIR/syntax-errors.rs:140:30
|
LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
| ^ expected expression
...
LL | unknown_metavar!(a);
| ------------------- in this macro invocation
|
= note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `i` in this scope
--> $DIR/syntax-errors.rs:23:36
|
LL | ( $( $i:ident ),* ) => { count(i) };
| ^ not found in this scope
...
LL | no_curly__no_rhs_dollar__round!(a, b, c);
| ---------------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `i` in this scope
--> $DIR/syntax-errors.rs:30:29
|
LL | ( $i:ident ) => { count(i) };
| ^ not found in this scope
...
LL | no_curly__no_rhs_dollar__no_round!(a);
| ------------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `a` in this scope
--> $DIR/syntax-errors.rs:152:37
|
LL | ( $i:ident ) => { count($i) };
| -- due to this macro variable
...
LL | no_curly__rhs_dollar__no_round!(a);
| ^ not found in this scope
error[E0425]: cannot find function `count` in this scope
--> $DIR/syntax-errors.rs:23:30
|
LL | ( $( $i:ident ),* ) => { count(i) };
| ^^^^^ not found in this scope
...
LL | no_curly__no_rhs_dollar__round!(a, b, c);
| ---------------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find function `count` in this scope
--> $DIR/syntax-errors.rs:30:23
|
LL | ( $i:ident ) => { count(i) };
| ^^^^^ not found in this scope
...
LL | no_curly__no_rhs_dollar__no_round!(a);
| ------------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find function `count` in this scope
--> $DIR/syntax-errors.rs:43:23
|
LL | ( $i:ident ) => { count($i) };
| ^^^^^ not found in this scope
...
LL | no_curly__rhs_dollar__no_round!(a);
| ---------------------------------- in this macro invocation
|
= note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 39 previous errors
For more information about this error, try `rustc --explain E0425`.