From cf5eb279101511fa9ee38988adab7cac9a57f0da Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 20 Jun 2025 16:50:20 -0400 Subject: [PATCH 01/11] mbe: Restructure `macro_metavar_expr` tests These tests have expanded beyond the RFC, so rename the directory `rfc-3086-metavar-expr` to `metavar-expressions`. `concat` (which wasn't part of the RFC) now fits in this group, so merge its tests into the `metavar-expressions` directory. Additionally rename some related `issue-*` tests. --- src/tools/tidy/src/issues.txt | 1 - .../concat-allowed-operations.rs} | 0 .../concat-hygiene.rs} | 0 .../concat-hygiene.stderr} | 2 +- .../concat-raw-identifiers.rs} | 0 .../concat-raw-identifiers.stderr} | 28 ++++---- .../concat-repetitions.rs} | 0 .../concat-repetitions.stderr} | 6 +- .../concat-syntax-errors.rs} | 0 .../concat-syntax-errors.stderr} | 66 +++++++++---------- .../concat-unicode-expansion.rs} | 0 .../count-and-length-are-distinct.rs | 0 .../count-empty-index-arg.rs} | 6 +- .../count-empty-index-arg.stderr} | 4 +- .../dollar-dollar-has-correct-behavior.rs | 0 .../feature-gate-macro_metavar_expr.rs | 0 .../macro-expansion.rs | 0 .../out-of-bounds-arguments.rs | 0 .../out-of-bounds-arguments.stderr | 0 .../required-feature.rs | 0 .../required-feature.stderr | 0 .../syntax-errors.rs | 0 .../syntax-errors.stderr | 0 23 files changed, 57 insertions(+), 56 deletions(-) rename tests/ui/macros/{macro-metavar-expr-concat/allowed-operations.rs => metavar-expressions/concat-allowed-operations.rs} (100%) rename tests/ui/macros/{macro-metavar-expr-concat/hygiene.rs => metavar-expressions/concat-hygiene.rs} (100%) rename tests/ui/macros/{macro-metavar-expr-concat/hygiene.stderr => metavar-expressions/concat-hygiene.stderr} (93%) rename tests/ui/macros/{macro-metavar-expr-concat/raw-identifiers.rs => metavar-expressions/concat-raw-identifiers.rs} (100%) rename tests/ui/macros/{macro-metavar-expr-concat/raw-identifiers.stderr => metavar-expressions/concat-raw-identifiers.stderr} (80%) rename tests/ui/macros/{macro-metavar-expr-concat/repetitions.rs => metavar-expressions/concat-repetitions.rs} (100%) rename tests/ui/macros/{macro-metavar-expr-concat/repetitions.stderr => metavar-expressions/concat-repetitions.stderr} (79%) rename tests/ui/macros/{macro-metavar-expr-concat/syntax-errors.rs => metavar-expressions/concat-syntax-errors.rs} (100%) rename tests/ui/macros/{macro-metavar-expr-concat/syntax-errors.stderr => metavar-expressions/concat-syntax-errors.stderr} (86%) rename tests/ui/macros/{macro-metavar-expr-concat/unicode-expansion.rs => metavar-expressions/concat-unicode-expansion.rs} (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/count-and-length-are-distinct.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr/issue-111904.rs => metavar-expressions/count-empty-index-arg.rs} (66%) rename tests/ui/macros/{rfc-3086-metavar-expr/issue-111904.stderr => metavar-expressions/count-empty-index-arg.stderr} (87%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/dollar-dollar-has-correct-behavior.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/feature-gate-macro_metavar_expr.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/macro-expansion.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/out-of-bounds-arguments.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/out-of-bounds-arguments.stderr (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/required-feature.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/required-feature.stderr (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/syntax-errors.rs (100%) rename tests/ui/macros/{rfc-3086-metavar-expr => metavar-expressions}/syntax-errors.stderr (100%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index b3517b2e9da08..0f908e4f551aa 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2849,7 +2849,6 @@ ui/macros/issue-98466.rs ui/macros/issue-99261.rs ui/macros/issue-99265.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-69341-malformed-derive-inert.rs ui/marker_trait_attr/issue-61651-type-mismatch.rs diff --git a/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs similarity index 100% rename from tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs rename to tests/ui/macros/metavar-expressions/concat-allowed-operations.rs diff --git a/tests/ui/macros/macro-metavar-expr-concat/hygiene.rs b/tests/ui/macros/metavar-expressions/concat-hygiene.rs similarity index 100% rename from tests/ui/macros/macro-metavar-expr-concat/hygiene.rs rename to tests/ui/macros/metavar-expressions/concat-hygiene.rs diff --git a/tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr b/tests/ui/macros/metavar-expressions/concat-hygiene.stderr similarity index 93% rename from tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr rename to tests/ui/macros/metavar-expressions/concat-hygiene.stderr index ef2326dce857f..f3150d385ee70 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/hygiene.stderr +++ b/tests/ui/macros/metavar-expressions/concat-hygiene.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `abcdef` in this scope - --> $DIR/hygiene.rs:5:10 + --> $DIR/concat-hygiene.rs:5:10 | LL | ${concat($lhs, $rhs)} | ^^^^^^^^^^^^^^^^^^^^ not found in this scope diff --git a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs similarity index 100% rename from tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs rename to tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs diff --git a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr similarity index 80% rename from tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr rename to tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr index 4e11e20acc551..7abab6a510358 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr +++ b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr @@ -1,47 +1,47 @@ 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)}: () = (); | ^^^^^ 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)}: () = (); | ^^^^^ 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)}: () = (); | ^^^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ @@ -49,31 +49,31 @@ LL | let ${concat($lhs, $rhs)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ 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)}: () = (); | ^^^ @@ -81,7 +81,7 @@ LL | let ${concat($lhs, $rhs)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: expected pattern, found `$` - --> $DIR/raw-identifiers.rs:28:13 + --> $DIR/concat-raw-identifiers.rs:28:13 | LL | let ${concat(r#abc, abc)}: () = (); | ^ expected pattern diff --git a/tests/ui/macros/macro-metavar-expr-concat/repetitions.rs b/tests/ui/macros/metavar-expressions/concat-repetitions.rs similarity index 100% rename from tests/ui/macros/macro-metavar-expr-concat/repetitions.rs rename to tests/ui/macros/metavar-expressions/concat-repetitions.rs diff --git a/tests/ui/macros/macro-metavar-expr-concat/repetitions.stderr b/tests/ui/macros/metavar-expressions/concat-repetitions.stderr similarity index 79% rename from tests/ui/macros/macro-metavar-expr-concat/repetitions.stderr rename to tests/ui/macros/metavar-expressions/concat-repetitions.stderr index c3006c4be5df2..18b0a90c1c8a7 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/repetitions.stderr +++ b/tests/ui/macros/metavar-expressions/concat-repetitions.stderr @@ -1,17 +1,17 @@ error: invalid syntax - --> $DIR/repetitions.rs:14:20 + --> $DIR/concat-repetitions.rs:14:20 | LL | const ${concat($a, Z)}: i32 = 3; | ^^^^^^^^^^^^^^^ error: invalid syntax - --> $DIR/repetitions.rs:22:17 + --> $DIR/concat-repetitions.rs:22:17 | LL | read::<${concat($t, $en)}>() | ^^^^^^^^^^^^^^^^^ error: invalid syntax - --> $DIR/repetitions.rs:22:17 + --> $DIR/concat-repetitions.rs:22:17 | LL | read::<${concat($t, $en)}>() | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs b/tests/ui/macros/metavar-expressions/concat-syntax-errors.rs similarity index 100% rename from tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs rename to tests/ui/macros/metavar-expressions/concat-syntax-errors.rs diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/concat-syntax-errors.stderr similarity index 86% rename from tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr rename to tests/ui/macros/metavar-expressions/concat-syntax-errors.stderr index 2de6d2b3ce3b8..3297de8018653 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-syntax-errors.stderr @@ -1,71 +1,71 @@ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:5:10 + --> $DIR/concat-syntax-errors.rs:5:10 | LL | ${concat()} | ^^^^^^^^^^ error: `concat` must have at least two elements - --> $DIR/syntax-errors.rs:8:11 + --> $DIR/concat-syntax-errors.rs:8:11 | LL | ${concat(aaaa)} | ^^^^^^ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:11:10 + --> $DIR/concat-syntax-errors.rs:11:10 | LL | ${concat(aaaa,)} | ^^^^^^^^^^^^^^^ error: expected comma - --> $DIR/syntax-errors.rs:16:10 + --> $DIR/concat-syntax-errors.rs:16:10 | LL | ${concat(aaaa aaaa)} | ^^^^^^^^^^^^^^^^^^^ error: `concat` must have at least two elements - --> $DIR/syntax-errors.rs:19:11 + --> $DIR/concat-syntax-errors.rs:19:11 | LL | ${concat($ex)} | ^^^^^^ error: expected comma - --> $DIR/syntax-errors.rs:25:10 + --> $DIR/concat-syntax-errors.rs:25:10 | LL | ${concat($ex, aaaa 123)} | ^^^^^^^^^^^^^^^^^^^^^^^ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:28:10 + --> $DIR/concat-syntax-errors.rs:28:10 | LL | ${concat($ex, aaaa,)} | ^^^^^^^^^^^^^^^^^^^^ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:88:26 + --> $DIR/concat-syntax-errors.rs:88:26 | LL | let ${concat(_a, 'b')}: () = (); | ^^^ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:91:26 + --> $DIR/concat-syntax-errors.rs:91:26 | LL | let ${concat(_a, 1)}: () = (); | ^ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:94:30 + --> $DIR/concat-syntax-errors.rs:94:30 | LL | let ${concat($ident, 'b')}: () = (); | ^^^ error: expected identifier or string literal - --> $DIR/syntax-errors.rs:96:30 + --> $DIR/concat-syntax-errors.rs:96:30 | LL | let ${concat($ident, 1)}: () = (); | ^ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:22:19 + --> $DIR/concat-syntax-errors.rs:22:19 | LL | ${concat($ex, aaaa)} | ^^ @@ -73,13 +73,13 @@ LL | ${concat($ex, aaaa)} = note: currently only string literals are supported error: variable `foo` is not recognized in meta-variable expression - --> $DIR/syntax-errors.rs:35:30 + --> $DIR/concat-syntax-errors.rs:35:30 | LL | const ${concat(FOO, $foo)}: i32 = 2; | ^^^ error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:42:14 + --> $DIR/concat-syntax-errors.rs:42:14 | LL | let ${concat("1", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:55:14 + --> $DIR/concat-syntax-errors.rs:55:14 | LL | let ${concat("\u{00BD}", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -101,7 +101,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:74:14 + --> $DIR/concat-syntax-errors.rs:74:14 | LL | let ${concat($ident, "\u{00BD}")}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,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) error: expected pattern, found `$` - --> $DIR/syntax-errors.rs:88:13 + --> $DIR/concat-syntax-errors.rs:88:13 | LL | let ${concat(_a, 'b')}: () = (); | ^ expected pattern @@ -123,7 +123,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:81:14 + --> $DIR/concat-syntax-errors.rs:81:14 | LL | let ${concat("", "")}: () = (); | ^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | empty!(); = 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 - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +200,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/syntax-errors.rs:103:16 + --> $DIR/concat-syntax-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -211,7 +211,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) error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:116:31 + --> $DIR/concat-syntax-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -219,7 +219,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:116:31 + --> $DIR/concat-syntax-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -228,7 +228,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:116:31 + --> $DIR/concat-syntax-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -237,7 +237,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:116:31 + --> $DIR/concat-syntax-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -246,7 +246,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:116:31 + --> $DIR/concat-syntax-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -255,7 +255,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:127:31 + --> $DIR/concat-syntax-errors.rs:127:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -263,7 +263,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:127:31 + --> $DIR/concat-syntax-errors.rs:127:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -272,7 +272,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/syntax-errors.rs:127:31 + --> $DIR/concat-syntax-errors.rs:127:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ diff --git a/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs b/tests/ui/macros/metavar-expressions/concat-unicode-expansion.rs similarity index 100% rename from tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs rename to tests/ui/macros/metavar-expressions/concat-unicode-expansion.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/tests/ui/macros/metavar-expressions/count-and-length-are-distinct.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs rename to tests/ui/macros/metavar-expressions/count-and-length-are-distinct.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs b/tests/ui/macros/metavar-expressions/count-empty-index-arg.rs similarity index 66% rename from tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs rename to tests/ui/macros/metavar-expressions/count-empty-index-arg.rs index 3000bfed6a887..69880ee7fa9aa 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs +++ b/tests/ui/macros/metavar-expressions/count-empty-index-arg.rs @@ -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)] macro_rules! foo { @@ -10,5 +13,4 @@ fn test() { foo!(a, a; b, b); } -fn main() { -} +fn main() {} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr b/tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr similarity index 87% rename from tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr rename to tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr index fd53c1686cf14..e1f9d020b7f86 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr +++ b/tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr @@ -1,11 +1,11 @@ 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,)} } | ^^^^^ error: expected expression, found `$` - --> $DIR/issue-111904.rs:4:35 + --> $DIR/count-empty-index-arg.rs:7:35 | LL | ( $( $($t:ident),* );* ) => { ${count($t,)} } | ^ expected expression diff --git a/tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs b/tests/ui/macros/metavar-expressions/dollar-dollar-has-correct-behavior.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/dollar-dollar-has-correct-behavior.rs rename to tests/ui/macros/metavar-expressions/dollar-dollar-has-correct-behavior.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/tests/ui/macros/metavar-expressions/feature-gate-macro_metavar_expr.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs rename to tests/ui/macros/metavar-expressions/feature-gate-macro_metavar_expr.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs b/tests/ui/macros/metavar-expressions/macro-expansion.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs rename to tests/ui/macros/metavar-expressions/macro-expansion.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs b/tests/ui/macros/metavar-expressions/out-of-bounds-arguments.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs rename to tests/ui/macros/metavar-expressions/out-of-bounds-arguments.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr b/tests/ui/macros/metavar-expressions/out-of-bounds-arguments.stderr similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr rename to tests/ui/macros/metavar-expressions/out-of-bounds-arguments.stderr diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/tests/ui/macros/metavar-expressions/required-feature.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs rename to tests/ui/macros/metavar-expressions/required-feature.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/tests/ui/macros/metavar-expressions/required-feature.stderr similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr rename to tests/ui/macros/metavar-expressions/required-feature.stderr diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs rename to tests/ui/macros/metavar-expressions/syntax-errors.rs diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr similarity index 100% rename from tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr rename to tests/ui/macros/metavar-expressions/syntax-errors.stderr From b2c6e5a77a2d4833a5928164e54e91a94cd61b54 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 23 Jun 2025 00:14:23 -0500 Subject: [PATCH 02/11] mbe: Split metavariable usage tests off from syntax tests `syntax-errors` currently contains both actual syntax error tests and tests (which don't need expansion) and tests for incorrect usage of the `count` metavariable expression (which dos need expansion). Split the expansion-dependent tests to a separate file, remove unneeded invocations from `syntax-errors` to ensure we are catching these before expansion. --- ...yntax-errors.rs => concat-usage-errors.rs} | 2 +- ...rors.stderr => concat-usage-errors.stderr} | 66 ++-- .../metavar-expressions/syntax-errors.rs | 125 ++----- .../metavar-expressions/syntax-errors.stderr | 310 ++++-------------- .../metavar-expressions/usage-errors.rs | 55 ++++ .../metavar-expressions/usage-errors.stderr | 71 ++++ 6 files changed, 252 insertions(+), 377 deletions(-) rename tests/ui/macros/metavar-expressions/{concat-syntax-errors.rs => concat-usage-errors.rs} (99%) rename tests/ui/macros/metavar-expressions/{concat-syntax-errors.stderr => concat-usage-errors.stderr} (86%) create mode 100644 tests/ui/macros/metavar-expressions/usage-errors.rs create mode 100644 tests/ui/macros/metavar-expressions/usage-errors.stderr diff --git a/tests/ui/macros/metavar-expressions/concat-syntax-errors.rs b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs similarity index 99% rename from tests/ui/macros/metavar-expressions/concat-syntax-errors.rs rename to tests/ui/macros/metavar-expressions/concat-usage-errors.rs index 7673bd3200fff..c8f5d2117d028 100644 --- a/tests/ui/macros/metavar-expressions/concat-syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs @@ -132,7 +132,7 @@ macro_rules! bad_tt_literal { } fn main() { - wrong_concat_declarations!(1); + syntax_errors!(1); dollar_sign_without_referenced_ident!(VAR); diff --git a/tests/ui/macros/metavar-expressions/concat-syntax-errors.stderr b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr similarity index 86% rename from tests/ui/macros/metavar-expressions/concat-syntax-errors.stderr rename to tests/ui/macros/metavar-expressions/concat-usage-errors.stderr index 3297de8018653..629843ecbdab8 100644 --- a/tests/ui/macros/metavar-expressions/concat-syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr @@ -1,71 +1,71 @@ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:5:10 + --> $DIR/concat-usage-errors.rs:5:10 | LL | ${concat()} | ^^^^^^^^^^ error: `concat` must have at least two elements - --> $DIR/concat-syntax-errors.rs:8:11 + --> $DIR/concat-usage-errors.rs:8:11 | LL | ${concat(aaaa)} | ^^^^^^ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:11:10 + --> $DIR/concat-usage-errors.rs:11:10 | LL | ${concat(aaaa,)} | ^^^^^^^^^^^^^^^ error: expected comma - --> $DIR/concat-syntax-errors.rs:16:10 + --> $DIR/concat-usage-errors.rs:16:10 | LL | ${concat(aaaa aaaa)} | ^^^^^^^^^^^^^^^^^^^ error: `concat` must have at least two elements - --> $DIR/concat-syntax-errors.rs:19:11 + --> $DIR/concat-usage-errors.rs:19:11 | LL | ${concat($ex)} | ^^^^^^ error: expected comma - --> $DIR/concat-syntax-errors.rs:25:10 + --> $DIR/concat-usage-errors.rs:25:10 | LL | ${concat($ex, aaaa 123)} | ^^^^^^^^^^^^^^^^^^^^^^^ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:28:10 + --> $DIR/concat-usage-errors.rs:28:10 | LL | ${concat($ex, aaaa,)} | ^^^^^^^^^^^^^^^^^^^^ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:88:26 + --> $DIR/concat-usage-errors.rs:88:26 | LL | let ${concat(_a, 'b')}: () = (); | ^^^ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:91:26 + --> $DIR/concat-usage-errors.rs:91:26 | LL | let ${concat(_a, 1)}: () = (); | ^ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:94:30 + --> $DIR/concat-usage-errors.rs:94:30 | LL | let ${concat($ident, 'b')}: () = (); | ^^^ error: expected identifier or string literal - --> $DIR/concat-syntax-errors.rs:96:30 + --> $DIR/concat-usage-errors.rs:96:30 | LL | let ${concat($ident, 1)}: () = (); | ^ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:22:19 + --> $DIR/concat-usage-errors.rs:22:19 | LL | ${concat($ex, aaaa)} | ^^ @@ -73,13 +73,13 @@ LL | ${concat($ex, aaaa)} = note: currently only string literals are supported error: variable `foo` is not recognized in meta-variable expression - --> $DIR/concat-syntax-errors.rs:35:30 + --> $DIR/concat-usage-errors.rs:35:30 | LL | const ${concat(FOO, $foo)}: i32 = 2; | ^^^ error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:42:14 + --> $DIR/concat-usage-errors.rs:42:14 | LL | let ${concat("1", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:55:14 + --> $DIR/concat-usage-errors.rs:55:14 | LL | let ${concat("\u{00BD}", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -101,7 +101,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:74:14 + --> $DIR/concat-usage-errors.rs:74:14 | LL | let ${concat($ident, "\u{00BD}")}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +112,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) error: expected pattern, found `$` - --> $DIR/concat-syntax-errors.rs:88:13 + --> $DIR/concat-usage-errors.rs:88:13 | LL | let ${concat(_a, 'b')}: () = (); | ^ expected pattern @@ -123,7 +123,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:81:14 + --> $DIR/concat-usage-errors.rs:81:14 | LL | let ${concat("", "")}: () = (); | ^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | empty!(); = 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 - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -156,7 +156,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,7 +167,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +189,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +200,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-syntax-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:103:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -211,7 +211,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) error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -219,7 +219,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -228,7 +228,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -237,7 +237,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -246,7 +246,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:116:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -255,7 +255,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:127:31 + --> $DIR/concat-usage-errors.rs:127:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -263,7 +263,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:127:31 + --> $DIR/concat-usage-errors.rs:127:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -272,7 +272,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-syntax-errors.rs:127:31 + --> $DIR/concat-usage-errors.rs:127:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs index 78cede92526ba..8735da352d86a 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/syntax-errors.rs @@ -1,62 +1,48 @@ -#![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) } }; -} +// 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. -macro_rules! curly__no_rhs_dollar__no_round { - ( $i:ident ) => { ${ count($i) } }; - //~^ ERROR `count` can not be placed inside the innermost repetition -} +#![feature(macro_metavar_expr)] -macro_rules! curly__rhs_dollar__no_round { - ( $i:ident ) => { ${ count($i) } }; - //~^ ERROR `count` can not be placed inside the innermost repetition +macro_rules! dollar_dollar_in_the_lhs { + ( $$ $a:ident ) => { + //~^ ERROR unexpected token: $ + }; } -#[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 +macro_rules! metavar_in_the_lhs { + ( ${ len() } ) => { + //~^ ERROR unexpected token: { + //~| ERROR expected one of: `*`, `+`, or `?` + }; } -#[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 +macro_rules! metavar_token_without_ident { + ( $( $i:ident ),* ) => { ${ ignore() } }; + //~^ ERROR meta-variable expressions must be referenced using a dollar sign } -#[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 +macro_rules! metavar_with_literal_suffix { + ( $( $i:ident ),* ) => { ${ index(1u32) } }; + //~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions } -#[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 +macro_rules! metavar_without_parens { + ( $( $i:ident ),* ) => { ${ count{i} } }; + //~^ ERROR meta-variable expression parameter must be wrapped in parentheses } -// Other scenarios - -macro_rules! dollar_dollar_in_the_lhs { - ( $$ $a:ident ) => { - //~^ ERROR unexpected token: $ - }; +#[rustfmt::skip] +macro_rules! open_brackets_without_tokens { + ( $( $i:ident ),* ) => { ${ {} } }; + //~^ ERROR expected identifier } 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)} @@ -85,46 +71,12 @@ 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 }; } @@ -132,33 +84,12 @@ 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); -} +fn main() {} diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr index d9646760cea92..291e27924c8a7 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/syntax-errors.stderr @@ -1,382 +1,200 @@ error: unexpected token: $ - --> $DIR/syntax-errors.rs:50:8 + --> $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:50:8 + --> $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{i} } }; + | ^^^^^ + error: unexpected token: a - --> $DIR/syntax-errors.rs:57:19 + --> $DIR/syntax-errors.rs:44:19 | LL | ${count() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:57:19 + --> $DIR/syntax-errors.rs:44:19 | LL | ${count() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:60:20 + --> $DIR/syntax-errors.rs:46:20 | LL | ${count($i a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:60:20 + --> $DIR/syntax-errors.rs:46:20 | LL | ${count($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:62:23 + --> $DIR/syntax-errors.rs:48:23 | LL | ${count($i, 1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:62:23 + --> $DIR/syntax-errors.rs:48:23 | LL | ${count($i, 1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:64:21 + --> $DIR/syntax-errors.rs:50:21 | LL | ${count($i) a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:64:21 + --> $DIR/syntax-errors.rs:50:21 | LL | ${count($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:67:22 + --> $DIR/syntax-errors.rs:53:22 | LL | ${ignore($i) a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:67:22 + --> $DIR/syntax-errors.rs:53:22 | LL | ${ignore($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:69:21 + --> $DIR/syntax-errors.rs:55:21 | LL | ${ignore($i a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:69:21 + --> $DIR/syntax-errors.rs:55:21 | LL | ${ignore($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:72:19 + --> $DIR/syntax-errors.rs:58:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:72:19 + --> $DIR/syntax-errors.rs:58:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:74:19 + --> $DIR/syntax-errors.rs:60:19 | LL | ${index(1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:74:19 + --> $DIR/syntax-errors.rs:60:19 | LL | ${index(1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:77:19 + --> $DIR/syntax-errors.rs:63:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:77:19 + --> $DIR/syntax-errors.rs:63:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:79:19 + --> $DIR/syntax-errors.rs:65:19 | LL | ${index(1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:79:19 + --> $DIR/syntax-errors.rs:65:19 | LL | ${index(1 a b c)} | ^ error: meta-variable expression depth must be a literal - --> $DIR/syntax-errors.rs:86:33 + --> $DIR/syntax-errors.rs:72: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 + --> $DIR/syntax-errors.rs:78:11 | LL | ${count(foo)} | ^^^^^ error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:133:11 + --> $DIR/syntax-errors.rs:85:11 | LL | ${ignore(bar)} | ^^^^^^ error: unrecognized meta-variable expression - --> $DIR/syntax-errors.rs:140:33 + --> $DIR/syntax-errors.rs:91: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 + --> $DIR/syntax-errors.rs:38: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 +error: aborting due to 21 previous errors -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/macros/metavar-expressions/usage-errors.rs b/tests/ui/macros/metavar-expressions/usage-errors.rs new file mode 100644 index 0000000000000..feff02e2ce470 --- /dev/null +++ b/tests/ui/macros/metavar-expressions/usage-errors.rs @@ -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() {} diff --git a/tests/ui/macros/metavar-expressions/usage-errors.stderr b/tests/ui/macros/metavar-expressions/usage-errors.stderr new file mode 100644 index 0000000000000..f66f522e23b96 --- /dev/null +++ b/tests/ui/macros/metavar-expressions/usage-errors.stderr @@ -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`. From 3efd7ec41ab1122c0e4ad1c00bd4e0cd33e04859 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 23 Jun 2025 00:42:06 -0500 Subject: [PATCH 03/11] mbe: Extend metavariable expression tests Add tests showing the current state to make it more clear when output gets updated later in refactoring. --- .../concat-trace-errors.rs | 33 +++++ .../concat-trace-errors.stderr | 24 ++++ .../concat-usage-errors.rs | 24 +++- .../concat-usage-errors.stderr | 128 +++++++++++++----- .../metavar-expressions/syntax-errors.rs | 25 +++- .../metavar-expressions/syntax-errors.stderr | 72 ++++++---- 6 files changed, 242 insertions(+), 64 deletions(-) create mode 100644 tests/ui/macros/metavar-expressions/concat-trace-errors.rs create mode 100644 tests/ui/macros/metavar-expressions/concat-trace-errors.stderr diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.rs b/tests/ui/macros/metavar-expressions/concat-trace-errors.rs new file mode 100644 index 0000000000000..45407f5e86d56 --- /dev/null +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.rs @@ -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() {} diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr new file mode 100644 index 0000000000000..dac8b58a15ce2 --- /dev/null +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr @@ -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 + diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs index c8f5d2117d028..7d8756de9e20b 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs @@ -1,6 +1,8 @@ +//@ edition: 2021 + #![feature(macro_metavar_expr_concat)] -macro_rules! wrong_concat_declarations { +macro_rules! syntax_errors { ($ex:expr) => { ${concat()} //~^ ERROR expected identifier @@ -90,11 +92,31 @@ macro_rules! unsupported_literals { //~| ERROR expected pattern let ${concat(_a, 1)}: () = (); //~^ 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')}: () = (); //~^ ERROR expected identifier or string literal let ${concat($ident, 1)}: () = (); //~^ 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 }}; } diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr index 629843ecbdab8..8be3e792ec3f2 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr @@ -1,71 +1,131 @@ error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:5:10 + --> $DIR/concat-usage-errors.rs:7:10 | LL | ${concat()} | ^^^^^^^^^^ error: `concat` must have at least two elements - --> $DIR/concat-usage-errors.rs:8:11 + --> $DIR/concat-usage-errors.rs:10:11 | LL | ${concat(aaaa)} | ^^^^^^ error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:11:10 + --> $DIR/concat-usage-errors.rs:13:10 | LL | ${concat(aaaa,)} | ^^^^^^^^^^^^^^^ error: expected comma - --> $DIR/concat-usage-errors.rs:16:10 + --> $DIR/concat-usage-errors.rs:18:10 | LL | ${concat(aaaa aaaa)} | ^^^^^^^^^^^^^^^^^^^ error: `concat` must have at least two elements - --> $DIR/concat-usage-errors.rs:19:11 + --> $DIR/concat-usage-errors.rs:21:11 | LL | ${concat($ex)} | ^^^^^^ error: expected comma - --> $DIR/concat-usage-errors.rs:25:10 + --> $DIR/concat-usage-errors.rs:27:10 | LL | ${concat($ex, aaaa 123)} | ^^^^^^^^^^^^^^^^^^^^^^^ error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:28:10 + --> $DIR/concat-usage-errors.rs:30:10 | LL | ${concat($ex, aaaa,)} | ^^^^^^^^^^^^^^^^^^^^ error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:88:26 + --> $DIR/concat-usage-errors.rs:90:26 | LL | let ${concat(_a, 'b')}: () = (); | ^^^ error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:91:26 + --> $DIR/concat-usage-errors.rs:93:26 | LL | let ${concat(_a, 1)}: () = (); | ^ error: expected identifier or string literal - --> $DIR/concat-usage-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')}: () = (); | ^^^ error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:96:30 + --> $DIR/concat-usage-errors.rs:108:30 | 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` - --> $DIR/concat-usage-errors.rs:22:19 + --> $DIR/concat-usage-errors.rs:24:19 | LL | ${concat($ex, aaaa)} | ^^ @@ -73,13 +133,13 @@ LL | ${concat($ex, aaaa)} = note: currently only string literals are supported error: variable `foo` is not recognized in meta-variable expression - --> $DIR/concat-usage-errors.rs:35:30 + --> $DIR/concat-usage-errors.rs:37:30 | LL | const ${concat(FOO, $foo)}: i32 = 2; | ^^^ error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:42:14 + --> $DIR/concat-usage-errors.rs:44:14 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:55:14 + --> $DIR/concat-usage-errors.rs:57:14 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:74:14 + --> $DIR/concat-usage-errors.rs:76:14 | 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) error: expected pattern, found `$` - --> $DIR/concat-usage-errors.rs:88:13 + --> $DIR/concat-usage-errors.rs:90:13 | LL | let ${concat(_a, 'b')}: () = (); | ^ 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:81:14 + --> $DIR/concat-usage-errors.rs:83:14 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:103:16 + --> $DIR/concat-usage-errors.rs:125:16 | 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) error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:138:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -219,7 +279,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:138:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -228,7 +288,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:138:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -237,7 +297,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:138:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -246,7 +306,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:116:31 + --> $DIR/concat-usage-errors.rs:138:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -255,7 +315,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:127:31 + --> $DIR/concat-usage-errors.rs:149:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -263,7 +323,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:127:31 + --> $DIR/concat-usage-errors.rs:149:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -272,7 +332,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:127:31 + --> $DIR/concat-usage-errors.rs:149:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -280,5 +340,5 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: currently only string literals are supported = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 33 previous errors +error: aborting due to 43 previous errors diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs index 8735da352d86a..b68a42065bf96 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/syntax-errors.rs @@ -28,13 +28,34 @@ macro_rules! metavar_with_literal_suffix { //~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions } -macro_rules! metavar_without_parens { +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)} } +} + #[rustfmt::skip] -macro_rules! open_brackets_without_tokens { +macro_rules! open_brackets_with_group { ( $( $i:ident ),* ) => { ${ {} } }; //~^ ERROR expected identifier } diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr index 291e27924c8a7..ced52f3fddf41 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/syntax-errors.stderr @@ -41,160 +41,178 @@ LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; | ^^^^^ error: meta-variable expression parameter must be wrapped in parentheses - --> $DIR/syntax-errors.rs:32:33 + --> $DIR/syntax-errors.rs:32:34 + | +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: unexpected token: a - --> $DIR/syntax-errors.rs:44:19 + --> $DIR/syntax-errors.rs:61:19 | LL | ${count() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:44:19 + --> $DIR/syntax-errors.rs:61:19 | LL | ${count() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:46:20 + --> $DIR/syntax-errors.rs:63:20 | LL | ${count($i a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:46:20 + --> $DIR/syntax-errors.rs:63:20 | LL | ${count($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:48:23 + --> $DIR/syntax-errors.rs:65:23 | LL | ${count($i, 1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:48:23 + --> $DIR/syntax-errors.rs:65:23 | LL | ${count($i, 1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:50:21 + --> $DIR/syntax-errors.rs:67:21 | LL | ${count($i) a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:50:21 + --> $DIR/syntax-errors.rs:67:21 | LL | ${count($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:53:22 + --> $DIR/syntax-errors.rs:70:22 | LL | ${ignore($i) a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:53:22 + --> $DIR/syntax-errors.rs:70:22 | LL | ${ignore($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:55:21 + --> $DIR/syntax-errors.rs:72:21 | LL | ${ignore($i a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:55:21 + --> $DIR/syntax-errors.rs:72:21 | LL | ${ignore($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:58:19 + --> $DIR/syntax-errors.rs:75:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:58:19 + --> $DIR/syntax-errors.rs:75:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:60:19 + --> $DIR/syntax-errors.rs:77:19 | LL | ${index(1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:60:19 + --> $DIR/syntax-errors.rs:77:19 | LL | ${index(1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:63:19 + --> $DIR/syntax-errors.rs:80:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:63:19 + --> $DIR/syntax-errors.rs:80:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:65:19 + --> $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:65:19 + --> $DIR/syntax-errors.rs:82:19 | LL | ${index(1 a b c)} | ^ error: meta-variable expression depth must be a literal - --> $DIR/syntax-errors.rs:72:33 + --> $DIR/syntax-errors.rs:89:33 | LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; | ^^^^^ error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:78:11 + --> $DIR/syntax-errors.rs:95:11 | LL | ${count(foo)} | ^^^^^ error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:85:11 + --> $DIR/syntax-errors.rs:102:11 | LL | ${ignore(bar)} | ^^^^^^ error: unrecognized meta-variable expression - --> $DIR/syntax-errors.rs:91:33 + --> $DIR/syntax-errors.rs:108: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:33 + --> $DIR/syntax-errors.rs:38:15 + | +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:55:33 | LL | ( $( $i:ident ),* ) => { ${ {} } }; | ^^ -error: aborting due to 21 previous errors +error: aborting due to 24 previous errors From 4c06a1f3b75ab7339a0b289e0acf8ea9a4583c93 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 21 Jun 2025 03:46:54 -0400 Subject: [PATCH 04/11] mbe: Shorten `MetaVarExpr` -> `Mve` in structural diagnostics More diagnostic structs related to metavariable expressions will be introduced. Introduce the abbreviation "mve" which is reasonably unambiguous (`rg Mve` and `rg '(\b|_|-)mve(\b|_|-)'` return no results outside of a Thumb target feature) and use it for these diagnostic types. A new module is also created. --- compiler/rustc_expand/messages.ftl | 6 +++--- compiler/rustc_expand/src/errors.rs | 21 +++++++++++++-------- compiler/rustc_expand/src/mbe/transcribe.rs | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 8b7c47dad991f..85ded855e6c59 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -109,9 +109,6 @@ expand_malformed_feature_attribute = 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 .note = fragment specifiers must be provided .suggestion_add_fragspec = try adding a specifier here @@ -136,6 +133,9 @@ expand_module_multiple_candidates = expand_must_repeat_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 = non-inline modules in proc macro input are unstable diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 714ba3bf0f4f2..0d77916d4cfdf 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -27,14 +27,6 @@ pub(crate) struct CountRepetitionMisplaced { 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)] #[diag(expand_var_still_repeating)] pub(crate) struct VarStillRepeating { @@ -500,3 +492,16 @@ pub(crate) struct ProcMacroBackCompat { pub crate_name: 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, + } +} diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 0520be5fbaee5..1781a0c077163 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -17,7 +17,7 @@ use rustc_span::{ use smallvec::{SmallVec, smallvec}; use crate::errors::{ - CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce, + CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoSyntaxVarsExprRepeat, VarStillRepeating, }; use crate::mbe::macro_parser::NamedMatch; @@ -879,7 +879,7 @@ where { let span = ident.span; 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 From 0c4b9b8aca684dab379612db3da4c8047130d413 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 20 Jun 2025 17:08:38 -0400 Subject: [PATCH 05/11] mbe: Factor `concat` metavariable handling out Move the `concat` implementation to a separate function so it is easier to work on. Other metavariable expressions are already split this way. This is a non-functional change. --- compiler/rustc_expand/src/mbe/metavar_expr.rs | 85 ++++++++++--------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 1ccb070f83a4b..396d65b6f9daf 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -47,46 +47,7 @@ impl MetaVarExpr { check_trailing_token(&mut iter, psess)?; let mut iter = args.iter(); let rslt = match ident.as_str() { - "concat" => { - 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()) - } + "concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?, "count" => parse_count(&mut iter, psess, ident.span)?, "ignore" => { eat_dollar(&mut iter, psess, ident.span)?; @@ -156,6 +117,50 @@ fn check_trailing_token<'psess>( } } +/// 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])` fn parse_count<'psess>( iter: &mut TokenStreamIter<'_>, From 44ef2e89842ab879b24598183f77c73351260acf Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 20 Jun 2025 17:10:57 -0400 Subject: [PATCH 06/11] mbe: Move `MetaVarExprConcatElem` closer to where it is used Move this structure directly above the `parse_` functions that return it to keep top-down flow. This is a non-functional change. --- compiler/rustc_expand/src/mbe/metavar_expr.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 396d65b6f9daf..ffd3548019a8e 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -87,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 ...)}` fn check_trailing_token<'psess>( iter: &mut TokenStreamIter<'_>, @@ -117,6 +103,20 @@ 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<'_>, From 218359719b61f4c01e93535c3649599074d9c437 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 20 Jun 2025 17:27:56 -0400 Subject: [PATCH 07/11] mbe: Refactor diagnostics for missing identifiers The current messages have the potential to be more accurate; "expected identifier or string literal" is printed in a few cases where only an identifier should be expected, and it suggests removing string literals when that might not solve the problem. Add a new diagnostic for these kind of errors that gives some more context. For `count` and `ignore` this should likely be combined with the diagnositcs for `eat_dollar` to produce a helpful error if they get anything other than a metavariable first argument. I am planning to do this in a followup. --- compiler/rustc_expand/messages.ftl | 8 ++ compiler/rustc_expand/src/errors.rs | 24 +++++ compiler/rustc_expand/src/mbe/metavar_expr.rs | 41 +++++++-- .../metavar-expressions/syntax-errors.rs | 7 +- .../metavar-expressions/syntax-errors.stderr | 91 +++++++++++-------- 5 files changed, 125 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 85ded855e6c59..02f6261d389de 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -133,6 +133,14 @@ expand_module_multiple_candidates = expand_must_repeat_once = this must repeat at least once +expand_mve_expected_ident = + expected an identifier + .not_ident = not a valid identifier + .expr_name = expected a metavariable expression name: `{"${expr( /* ... */ )}"}` + .expr_name_note = valid metavariable expressions are {$valid_expr_list} + .ignore_expr_note = `ignore` takes a metavariable argument + .count_expr_note = `count` takes a metavariable argument + expand_mve_unrecognized_var = variable `{$key}` is not recognized in meta-variable expression diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 0d77916d4cfdf..2042b8f20a364 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -497,6 +497,30 @@ pub(crate) use metavar_exprs::*; mod metavar_exprs { use super::*; + #[derive(Diagnostic)] + #[diag(expand_mve_expected_ident)] + pub(crate) struct MveExpectedIdent { + #[primary_span] + pub span: Span, + #[label(expand_not_ident)] + pub not_ident_label: Option, + /// This error is reused a handful of places, the context here tells us how to customize + /// the message. + #[subdiagnostic] + pub context: MveExpectedIdentContext, + } + + #[derive(Subdiagnostic)] + pub(crate) enum MveExpectedIdentContext { + #[note(expand_expr_name)] + #[note(expand_expr_name_note)] + ExprName { valid_expr_list: &'static str }, + #[note(expand_ignore_expr_note)] + Ignore, + #[note(expand_count_expr_note)] + Count, + } + #[derive(Diagnostic)] #[diag(expand_mve_unrecognized_var)] pub(crate) struct MveUnrecognizedVar { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index ffd3548019a8e..0a139b4597be6 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -7,9 +7,13 @@ use rustc_macros::{Decodable, Encodable}; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol}; +use crate::errors::{self, MveExpectedIdentContext}; + pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal"; +const VALID_METAVAR_EXPR_NAMES: &str = "`count`, `ignore`, `index`, `len`, and `concat`"; + /// A meta-variable expression, for expansions based on properties of meta-variables. #[derive(Debug, PartialEq, Encodable, Decodable)] pub(crate) enum MetaVarExpr { @@ -39,7 +43,12 @@ impl MetaVarExpr { psess: &'psess ParseSess, ) -> PResult<'psess, MetaVarExpr> { let mut iter = input.iter(); - let ident = parse_ident(&mut iter, psess, outer_span)?; + let ident = parse_ident( + &mut iter, + psess, + outer_span, + MveExpectedIdentContext::ExprName { valid_expr_list: VALID_METAVAR_EXPR_NAMES }, + )?; let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = iter.next() else { let msg = "meta-variable expression parameter must be wrapped in parentheses"; return Err(psess.dcx().struct_span_err(ident.span, msg)); @@ -51,7 +60,9 @@ impl MetaVarExpr { "count" => parse_count(&mut iter, psess, ident.span)?, "ignore" => { eat_dollar(&mut iter, psess, ident.span)?; - MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?) + let ident = + parse_ident(&mut iter, psess, outer_span, MveExpectedIdentContext::Ignore)?; + MetaVarExpr::Ignore(ident) } "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), @@ -168,7 +179,7 @@ fn parse_count<'psess>( span: Span, ) -> PResult<'psess, MetaVarExpr> { eat_dollar(iter, psess, span)?; - let ident = parse_ident(iter, psess, span)?; + let ident = parse_ident(iter, psess, span, MveExpectedIdentContext::Count)?; let depth = if try_eat_comma(iter) { if iter.peek().is_none() { return Err(psess.dcx().struct_span_err( @@ -206,14 +217,32 @@ fn parse_depth<'psess>( } } -/// Parses an generic ident +/// Tries to parse a generic ident. If this fails, create a missing identifier diagnostic with +/// `context` explanation. fn parse_ident<'psess>( iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, fallback_span: Span, + context: MveExpectedIdentContext, ) -> PResult<'psess, Ident> { - let token = parse_token(iter, psess, fallback_span)?; - parse_ident_from_token(psess, token) + let Some(tt) = iter.next() else { + let err = errors::MveExpectedIdent { span: fallback_span, not_ident_label: None, context }; + return Err(psess.dcx().create_err(err)); + }; + + let TokenTree::Token(token, _) = tt else { + let span = tt.span(); + let err = errors::MveExpectedIdent { span, not_ident_label: Some(span), context }; + return Err(psess.dcx().create_err(err)); + }; + + let Some((elem, _)) = token.ident() else { + let span = token.span; + let err = errors::MveExpectedIdent { span, not_ident_label: Some(span), context }; + return Err(psess.dcx().create_err(err)); + }; + + Ok(elem) } fn parse_ident_from_token<'psess>( diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs index b68a42065bf96..c75cfcd96880a 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/syntax-errors.rs @@ -36,13 +36,13 @@ macro_rules! mve_without_parens { #[rustfmt::skip] macro_rules! empty_expression { () => { ${} }; - //~^ ERROR expected identifier or string literal + //~^ ERROR expected an identifier } #[rustfmt::skip] macro_rules! open_brackets_with_lit { () => { ${ "hi" } }; - //~^ ERROR expected identifier + //~^ ERROR expected an identifier } macro_rules! mve_wrong_delim { @@ -52,12 +52,13 @@ macro_rules! mve_wrong_delim { macro_rules! invalid_metavar { () => { ${ignore($123)} } + //~^ ERROR expected an identifier } #[rustfmt::skip] macro_rules! open_brackets_with_group { ( $( $i:ident ),* ) => { ${ {} } }; - //~^ ERROR expected identifier + //~^ ERROR expected an identifier } macro_rules! extra_garbage_after_metavar { diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr index ced52f3fddf41..5b9b7a950a1b5 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/syntax-errors.stderr @@ -41,10 +41,10 @@ LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; | ^^^^^ error: meta-variable expression parameter must be wrapped in parentheses - --> $DIR/syntax-errors.rs:32:34 + --> $DIR/syntax-errors.rs:32:33 | -LL | ( $( $i:ident ),* ) => { ${ count } }; - | ^^^^^ +LL | ( $( $i:ident ),* ) => { ${ count } }; + | ^^^^^ error: meta-variable expression parameter must be wrapped in parentheses --> $DIR/syntax-errors.rs:49:33 @@ -52,167 +52,184 @@ error: meta-variable expression parameter must be wrapped in parentheses LL | ( $( $i:ident ),* ) => { ${ count{i} } }; | ^^^^^ +error: expected an identifier + --> $DIR/syntax-errors.rs:54:23 + | +LL | () => { ${ignore($123)} } + | ^^^ not a valid identifier + | + = note: `ignore` takes a metavariable argument + error: unexpected token: a - --> $DIR/syntax-errors.rs:61:19 + --> $DIR/syntax-errors.rs:66:19 | LL | ${count() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:61:19 + --> $DIR/syntax-errors.rs:66:19 | LL | ${count() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:63:20 + --> $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:63:20 + --> $DIR/syntax-errors.rs:68:20 | LL | ${count($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:65:23 + --> $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:65:23 + --> $DIR/syntax-errors.rs:70:23 | LL | ${count($i, 1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:67:21 + --> $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:67:21 + --> $DIR/syntax-errors.rs:72:21 | LL | ${count($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:70:22 + --> $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:70:22 + --> $DIR/syntax-errors.rs:75:22 | LL | ${ignore($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:72:21 + --> $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:72:21 + --> $DIR/syntax-errors.rs:77:21 | LL | ${ignore($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:75:19 + --> $DIR/syntax-errors.rs:80:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:75:19 + --> $DIR/syntax-errors.rs:80:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:77:19 + --> $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:77:19 + --> $DIR/syntax-errors.rs:82:19 | LL | ${index(1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:80:19 + --> $DIR/syntax-errors.rs:85:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:80:19 + --> $DIR/syntax-errors.rs:85:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:82:19 + --> $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:82:19 + --> $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:89:33 + --> $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:95:11 + --> $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:102:11 + --> $DIR/syntax-errors.rs:107:11 | LL | ${ignore(bar)} | ^^^^^^ error: unrecognized meta-variable expression - --> $DIR/syntax-errors.rs:108:33 + --> $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:15 +error: expected an identifier + --> $DIR/syntax-errors.rs:38:14 + | +LL | () => { ${} }; + | ^^ | -LL | () => { ${} }; - | ^^ + = note: expected a metavariable expression name: `${expr( /* ... */ )}` + = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` -error: expected identifier, found `"hi"` +error: expected an identifier --> $DIR/syntax-errors.rs:44:17 | LL | () => { ${ "hi" } }; - | ^^^^ help: try removing `"hi"` + | ^^^^ not a valid identifier + | + = note: expected a metavariable expression name: `${expr( /* ... */ )}` + = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` -error: expected identifier or string literal - --> $DIR/syntax-errors.rs:55:33 +error: expected an identifier + --> $DIR/syntax-errors.rs:60:33 | LL | ( $( $i:ident ),* ) => { ${ {} } }; - | ^^ + | ^^ not a valid identifier + | + = note: expected a metavariable expression name: `${expr( /* ... */ )}` + = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` -error: aborting due to 24 previous errors +error: aborting due to 25 previous errors From 17f5a09a56bcc81c63f44262c02e56496db9be25 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 21 Jun 2025 01:01:20 -0400 Subject: [PATCH 08/11] mbe: Refactor diagnostics for invalid metavar expression syntax Give a more user-friendly diagnostic about the following: * Invalid syntax within the `${...}` braces, including missing parentheses or trailing tokens. * Incorrect number of arguments passed to specific metavariable expressions. --- compiler/rustc_expand/messages.ftl | 19 +++ compiler/rustc_expand/src/errors.rs | 32 +++++ compiler/rustc_expand/src/mbe/metavar_expr.rs | 79 ++++++++--- .../metavar-expressions/syntax-errors.rs | 24 ++-- .../metavar-expressions/syntax-errors.stderr | 126 +++++++----------- 5 files changed, 172 insertions(+), 108 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 02f6261d389de..e9d1095ac7581 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -141,6 +141,25 @@ expand_mve_expected_ident = .ignore_expr_note = `ignore` takes a metavariable argument .count_expr_note = `count` takes a metavariable argument +expand_mve_extra_tokens_in_braces = + unexpected trailing tokens in metavariable expression braces + .suggestion = try removing these tokens + +expand_mve_extra_tokens_in_expr = + unexpected trailing tokens in metavariable expression + .label = for this metavariable expression + .note= the `{$name}` metavariable expression takes up to {$max} arguments + .suggestion = try removing {$count -> + [one] this token + *[other] these tokens + } + +expand_mve_missing_paren = + expected `(` + .label = for this this metavariable expression + .note = metavariable expressions use function-like parentheses syntax + .suggestion = try adding parentheses + expand_mve_unrecognized_var = variable `{$key}` is not recognized in meta-variable expression diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 2042b8f20a364..555152bbef222 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -521,6 +521,38 @@ mod metavar_exprs { Count, } + #[derive(Diagnostic)] + #[diag(expand_mve_extra_tokens_in_braces)] + pub(crate) struct MveExtraTokensInBraces { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + } + + #[derive(Diagnostic)] + #[note] + #[diag(expand_mve_extra_tokens_in_expr)] + pub(crate) struct MveExtraTokensInExpr { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub span: Span, + #[label] + pub ident_span: Span, + pub count: usize, + pub max: usize, + pub name: &'static str, + } + + #[derive(Diagnostic)] + #[note] + #[diag(expand_mve_missing_paren)] + pub(crate) struct MveMissingParen { + #[primary_span] + pub span: Span, + #[suggestion(code = "( /* ... */ )", applicability = "has-placeholders")] + pub insert_span: Option, + } + #[derive(Diagnostic)] #[diag(expand_mve_unrecognized_var)] pub(crate) struct MveUnrecognizedVar { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 0a139b4597be6..7b318e2087d23 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -12,8 +12,18 @@ use crate::errors::{self, MveExpectedIdentContext}; pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal"; +/// List of the below list for diagnostics. const VALID_METAVAR_EXPR_NAMES: &str = "`count`, `ignore`, `index`, `len`, and `concat`"; +/// Map from expression names to the maximum arg count. +const EXPR_NAME_ARG_MAP: &[(&str, Option)] = &[ + ("concat", None), + ("count", Some(2)), + ("ignore", Some(1)), + ("index", Some(2)), + ("len", Some(2)), +]; + /// A meta-variable expression, for expansions based on properties of meta-variables. #[derive(Debug, PartialEq, Encodable, Decodable)] pub(crate) enum MetaVarExpr { @@ -49,11 +59,26 @@ impl MetaVarExpr { outer_span, MveExpectedIdentContext::ExprName { valid_expr_list: VALID_METAVAR_EXPR_NAMES }, )?; - let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = iter.next() else { - let msg = "meta-variable expression parameter must be wrapped in parentheses"; - return Err(psess.dcx().struct_span_err(ident.span, msg)); + + let next = iter.next(); + let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = next else { + // No `()`; wrong or no delimiters + let (span, insert_span) = match next { + Some(TokenTree::Delimited(delim, ..)) => (delim.open, None), + Some(tt) => (tt.span(), Some(ident.span.shrink_to_hi())), + None => (ident.span.shrink_to_hi(), Some(ident.span.shrink_to_hi())), + }; + let err = errors::MveMissingParen { span, insert_span }; + return Err(psess.dcx().create_err(err)); }; - check_trailing_token(&mut iter, psess)?; + + // Ensure there are no other tokens in the + if iter.peek().is_some() { + let span = iter_span(&iter).expect("checked is_some above"); + let err = errors::MveExtraTokensInBraces { span }; + return Err(psess.dcx().create_err(err)); + } + let mut iter = args.iter(); let rslt = match ident.as_str() { "concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?, @@ -78,7 +103,7 @@ impl MetaVarExpr { return Err(err); } }; - check_trailing_token(&mut iter, psess)?; + check_trailing_tokens(&mut iter, psess, ident)?; Ok(rslt) } @@ -98,20 +123,44 @@ impl MetaVarExpr { } } -// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` -fn check_trailing_token<'psess>( +/// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}` +fn check_trailing_tokens<'psess>( iter: &mut TokenStreamIter<'_>, psess: &'psess ParseSess, + ident: Ident, ) -> PResult<'psess, ()> { - if let Some(tt) = iter.next() { - let mut diag = psess - .dcx() - .struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt))); - diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens"); - Err(diag) - } else { - Ok(()) + if iter.peek().is_none() { + // All tokens used, no problem + return Ok(()); } + + let (name, max) = EXPR_NAME_ARG_MAP + .iter() + .find(|(name, _)| *name == ident.as_str()) + .expect("called with an invalid name"); + + let Some(max) = *max else { + // For expressions like `concat`, all tokens should be consumed already + panic!("{name} takes unlimited tokens but didn't eat them all"); + }; + + let err = errors::MveExtraTokensInExpr { + span: iter_span(iter).expect("checked is_none above"), + ident_span: ident.span, + count: iter.count(), + max, + name, + }; + Err(psess.dcx().create_err(err)) +} + +/// Returns a span encompassing all tokens in the iterator if there is at least one item. +fn iter_span(iter: &TokenStreamIter<'_>) -> Option { + let mut iter = iter.clone(); // cloning is cheap + let first_sp = iter.next()?.span(); + let last_sp = iter.last().map(TokenTree::span).unwrap_or(first_sp); + let span = first_sp.with_hi(last_sp.hi()); + Some(span) } /// Indicates what is placed in a `concat` parameter. For example, literals diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs index c75cfcd96880a..ce9134cf9f171 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/syntax-errors.rs @@ -30,7 +30,7 @@ macro_rules! metavar_with_literal_suffix { macro_rules! mve_without_parens { ( $( $i:ident ),* ) => { ${ count } }; - //~^ ERROR meta-variable expression parameter must be wrapped in parentheses + //~^ ERROR expected `(` } #[rustfmt::skip] @@ -47,7 +47,7 @@ macro_rules! open_brackets_with_lit { macro_rules! mve_wrong_delim { ( $( $i:ident ),* ) => { ${ count{i} } }; - //~^ ERROR meta-variable expression parameter must be wrapped in parentheses + //~^ ERROR expected `(` } macro_rules! invalid_metavar { @@ -64,28 +64,28 @@ macro_rules! open_brackets_with_group { macro_rules! extra_garbage_after_metavar { ( $( $i:ident ),* ) => { ${count() a b c} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${count($i a b c)} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${count($i, 1 a b c)} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${count($i) a b c} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${ignore($i) a b c} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${ignore($i a b c)} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${index() a b c} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${index(1 a b c)} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${index() a b c} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens ${index(1 a b c)} - //~^ ERROR unexpected token: a + //~^ ERROR unexpected trailing tokens }; } diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr index 5b9b7a950a1b5..2c25ccb793740 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/syntax-errors.stderr @@ -40,17 +40,21 @@ error: only unsuffixes integer literals are supported in meta-variable expressio LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; | ^^^^^ -error: meta-variable expression parameter must be wrapped in parentheses - --> $DIR/syntax-errors.rs:32:33 +error: expected `(` + --> $DIR/syntax-errors.rs:32:38 | LL | ( $( $i:ident ),* ) => { ${ count } }; - | ^^^^^ + | ^ help: try adding parentheses: `( /* ... */ )` + | + = note: metavariable expressions use function-like parentheses syntax -error: meta-variable expression parameter must be wrapped in parentheses - --> $DIR/syntax-errors.rs:49:33 +error: expected `(` + --> $DIR/syntax-errors.rs:49:38 | LL | ( $( $i:ident ),* ) => { ${ count{i} } }; - | ^^^^^ + | ^ + | + = note: metavariable expressions use function-like parentheses syntax error: expected an identifier --> $DIR/syntax-errors.rs:54:23 @@ -60,125 +64,85 @@ LL | () => { ${ignore($123)} } | = note: `ignore` takes a metavariable argument -error: unexpected token: a - --> $DIR/syntax-errors.rs:66:19 - | -LL | ${count() a b c} - | ^ - | -note: meta-variable expression must not have trailing tokens +error: unexpected trailing tokens in metavariable expression braces --> $DIR/syntax-errors.rs:66:19 | LL | ${count() a b c} - | ^ + | ^^^^^ help: try removing these tokens -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression --> $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 + | ----- ^^^^^ help: try removing these tokens + | | + | for this metavariable expression | -LL | ${count($i a b c)} - | ^ + = note: the `count` metavariable expression takes up to 2 arguments -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression --> $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 + | ----- ^^^^^ help: try removing these tokens + | | + | for this metavariable expression | -LL | ${count($i, 1 a b c)} - | ^ + = note: the `count` metavariable expression takes up to 2 arguments -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 +error: unexpected trailing tokens in metavariable expression braces --> $DIR/syntax-errors.rs:72:21 | LL | ${count($i) a b c} - | ^ + | ^^^^^ help: try removing these tokens -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression braces --> $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} - | ^ + | ^^^^^ help: try removing these tokens -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression --> $DIR/syntax-errors.rs:77:21 | LL | ${ignore($i a b c)} - | ^ + | ------ ^^^^^ help: try removing these tokens + | | + | for this metavariable expression | -note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:77:21 - | -LL | ${ignore($i a b c)} - | ^ + = note: the `ignore` metavariable expression takes up to 1 arguments -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression braces --> $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} - | ^ + | ^^^^^ help: try removing these tokens -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression --> $DIR/syntax-errors.rs:82:19 | LL | ${index(1 a b c)} - | ^ + | ----- ^^^^^ help: try removing these tokens + | | + | for this metavariable expression | -note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:82:19 - | -LL | ${index(1 a b c)} - | ^ + = note: the `index` metavariable expression takes up to 2 arguments -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression braces --> $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} - | ^ + | ^^^^^ help: try removing these tokens -error: unexpected token: a +error: unexpected trailing tokens in metavariable expression --> $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 + | ----- ^^^^^ help: try removing these tokens + | | + | for this metavariable expression | -LL | ${index(1 a b c)} - | ^ + = note: the `index` metavariable expression takes up to 2 arguments error: meta-variable expression depth must be a literal --> $DIR/syntax-errors.rs:94:33 From 6f81ed369d55e1b1fa0270c492adda4edaa9dbe4 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 21 Jun 2025 02:59:14 -0400 Subject: [PATCH 09/11] mbe: Refactor the diagnostic for unrecognized metavariable expressions --- compiler/rustc_expand/messages.ftl | 5 +++++ compiler/rustc_expand/src/errors.rs | 10 ++++++++++ compiler/rustc_expand/src/mbe/metavar_expr.rs | 14 +++++--------- .../ui/macros/metavar-expressions/syntax-errors.rs | 2 +- .../metavar-expressions/syntax-errors.stderr | 6 ++++-- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index e9d1095ac7581..be7db1c0d69f5 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -160,6 +160,11 @@ expand_mve_missing_paren = .note = metavariable expressions use function-like parentheses syntax .suggestion = try adding parentheses +expand_mve_unrecognized_expr = + unrecognized metavariable expression + .label = not a valid metavariable expression + .note = valid metavariable expressions are {$valid_expr_list} + expand_mve_unrecognized_var = variable `{$key}` is not recognized in meta-variable expression diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 555152bbef222..4c28b844d5779 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -553,6 +553,16 @@ mod metavar_exprs { pub insert_span: Option, } + #[derive(Diagnostic)] + #[note] + #[diag(expand_mve_unrecognized_expr)] + pub(crate) struct MveUnrecognizedExpr { + #[primary_span] + #[label] + pub span: Span, + pub valid_expr_list: &'static str, + } + #[derive(Diagnostic)] #[diag(expand_mve_unrecognized_var)] pub(crate) struct MveUnrecognizedVar { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 7b318e2087d23..17b24786e7701 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -92,15 +92,11 @@ impl MetaVarExpr { "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), _ => { - let err_msg = "unrecognized meta-variable expression"; - let mut err = psess.dcx().struct_span_err(ident.span, err_msg); - err.span_suggestion( - ident.span, - "supported expressions are count, ignore, index and len", - "", - Applicability::MachineApplicable, - ); - return Err(err); + let err = errors::MveUnrecognizedExpr { + span: ident.span, + valid_expr_list: VALID_METAVAR_EXPR_NAMES, + }; + return Err(psess.dcx().create_err(err)); } }; check_trailing_tokens(&mut iter, psess, ident)?; diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs index ce9134cf9f171..dd6e0304e25c3 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/syntax-errors.rs @@ -111,7 +111,7 @@ macro_rules! unknown_ignore_ident { macro_rules! unknown_metavar { ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; - //~^ ERROR unrecognized meta-variable expression + //~^ ERROR unrecognized metavariable expression } fn main() {} diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr index 2c25ccb793740..ee5a25be42838 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/syntax-errors.stderr @@ -162,11 +162,13 @@ error: meta-variables within meta-variable expressions must be referenced using LL | ${ignore(bar)} | ^^^^^^ -error: unrecognized meta-variable expression +error: unrecognized metavariable expression --> $DIR/syntax-errors.rs:113:33 | LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; - | ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len + | ^^^^^^^^^^^^^^ not a valid metavariable expression + | + = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` error: expected an identifier --> $DIR/syntax-errors.rs:38:14 From 847b9f75260eb2934ddc3b49b4028771bf7e40de Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 18 Jun 2025 20:08:32 -0400 Subject: [PATCH 10/11] mbe: Refactor the logic for `${concat}` * Now accept numbers, chars * Suffixes are stripped (needs more testing) * Report specific locations of errors * TODO: handle idents the same for expanded tokens --- compiler/rustc_builtin_macros/src/concat.rs | 2 + compiler/rustc_expand/messages.ftl | 15 ++ compiler/rustc_expand/src/errors.rs | 43 ++++ compiler/rustc_expand/src/mbe/metavar_expr.rs | 160 +++++++----- compiler/rustc_expand/src/mbe/transcribe.rs | 25 +- compiler/rustc_session/src/errors.rs | 26 +- .../concat-allowed-operations.rs | 43 +++- .../concat-raw-identifiers.rs | 6 +- .../concat-raw-identifiers.stderr | 27 ++- .../concat-trace-errors.rs | 3 + .../concat-trace-errors.stderr | 45 +++- .../concat-usage-errors.rs | 41 ++-- .../concat-usage-errors.stderr | 228 ++++++++++++------ .../metavar-expressions/syntax-errors.rs | 22 +- .../metavar-expressions/syntax-errors.stderr | 72 +++--- 15 files changed, 524 insertions(+), 234 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index c200539e12872..f59849a03d6ce 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -24,6 +24,8 @@ pub(crate) fn expand_concat( let mut guar = None; for e in es { match e.kind { + // For consistent user experience, please keep this in sync with the handling of + // literals in `rustc_expand::mbe::metavar_expr` `${concat()}`! ExprKind::Lit(token_lit) => match LitKind::from_token_lit(token_lit) { Ok(LitKind::Str(s, _) | LitKind::Float(s, _)) => { accumulator.push_str(s.as_str()); diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index be7db1c0d69f5..0c37a91be8878 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -133,6 +133,21 @@ expand_module_multiple_candidates = expand_must_repeat_once = this must repeat at least once +expand_mve_concat_invalid = + invalid item within a `{"${concat(...)}"}` expression + .expr_ident = expanding this `concat(...)` expression + .invalid_ident = this literal produced an invalid identifier + .float_lit = float literals cannot be concatenated + .c_str_lit = C string literals cannot be concatenated + .b_str_lit = byte literals cannot be concatenated + .raw_ident = raw identifiers cannot be concatenated + .unsupported = unsupported input for `concat(...)` + .valid_types = `concat` can join {$valid} + .expected_metavar = expected an identifier; got `{$found}` + .expected_metavar_dollar = todo + .unexpected_group = todo + .hi_label = todo + expand_mve_expected_ident = expected an identifier .not_ident = not a valid identifier diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 4c28b844d5779..ff674ff512b09 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -497,6 +497,49 @@ pub(crate) use metavar_exprs::*; mod metavar_exprs { use super::*; + #[derive(Diagnostic)] + #[diag(expand_mve_concat_invalid)] + pub(crate) struct MveConcatInvalid { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub reason: MveConcatInvalidReason, + #[help(expand_expr_ident)] + pub ident_span: Span, + pub valid: &'static str, + } + + // TODO: can these be labels rather than notes? + #[derive(Subdiagnostic)] + pub(crate) enum MveConcatInvalidReason { + #[note(expand_invalid_ident)] + InvalidIdent, + #[note(expand_float_lit)] + #[help(expand_valid_types)] + FloatLit, + #[note(expand_c_str_lit)] + #[help(expand_valid_types)] + CStrLit, + #[note(expand_b_str_lit)] + #[help(expand_valid_types)] + ByteStrLit, + #[note(expand_expected_metavar)] + #[label(expand_expected_metavar_dollar)] + ExpectedMetavarIdent { + found: String, + #[primary_span] + dollar: Span, + }, + #[note(expand_raw_ident)] + RawIdentifier, + #[note(expand_unsupported)] + #[help(expand_valid_types)] + UnsupportedInput, + #[note(expand_unexpected_group)] + UnexpectedGroup, + InvalidLiteral, + } + #[derive(Diagnostic)] #[diag(expand_mve_expected_ident)] pub(crate) struct MveExpectedIdent { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 17b24786e7701..26211f9ac67e6 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -1,16 +1,19 @@ -use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; -use rustc_ast::{LitIntType, LitKind}; +use rustc_ast::{self as ast, LitIntType, LitKind}; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::PResult; +use rustc_lexer::is_id_continue; use rustc_macros::{Decodable, Encodable}; +use rustc_session::errors::create_lit_error; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol}; -use crate::errors::{self, MveExpectedIdentContext}; +use crate::errors::{self, MveConcatInvalidReason, MveExpectedIdentContext}; pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; -pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal"; +pub(crate) const VALID_EXPR_CONCAT_TYPES: &str = + "metavariables, identifiers, string literals, and integer literals"; /// List of the below list for diagnostics. const VALID_METAVAR_EXPR_NAMES: &str = "`count`, `ignore`, `index`, `len`, and `concat`"; @@ -165,7 +168,7 @@ fn iter_span(iter: &TokenStreamIter<'_>) -> Option { pub(crate) enum MetaVarExprConcatElem { /// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be /// interpreted as a literal. - Ident(Ident), + Ident(String), /// For example, a number or a string. Literal(Symbol), /// Identifier WITH a preceding dollar sign, which means that this identifier should be @@ -181,30 +184,92 @@ fn parse_concat<'psess>( expr_ident_span: Span, ) -> PResult<'psess, MetaVarExpr> { let mut result = Vec::new(); + let dcx = psess.dcx(); 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)); + let dollar = try_eat_dollar(iter); + let Some(tt) = iter.next() else { + // May be hit only with the first iteration (peek is otherwise checked at the end). + break; + }; + + let make_err = |reason| { + let err = errors::MveConcatInvalid { + span: tt.span(), + ident_span: expr_ident_span, + reason, + valid: VALID_EXPR_CONCAT_TYPES, + }; + Err(dcx.create_err(err)) + }; + + let token = match tt { + TokenTree::Token(token, _) => token, + TokenTree::Delimited(..) => { + return make_err(MveConcatInvalidReason::UnexpectedGroup); + } + }; + + let element = if let Some(dollar) = dollar { + // Expecting a metavar + let Some((ident, _)) = token.ident() else { + return make_err(MveConcatInvalidReason::ExpectedMetavarIdent { + found: pprust::token_to_string(token).into_owned(), + dollar, + }); + }; + + // Variables get passed untouched + MetaVarExprConcatElem::Var(ident) + } else if let TokenKind::Literal(lit) = token.kind { + // Preprocess with `from_token_lit` to handle unescaping, float / int literal suffix + // stripping. + // + // For consistent user experience, please keep this in sync with the handling of + // literals in `rustc_builtin_macros::concat`! + let s = match ast::LitKind::from_token_lit(lit.clone()) { + Ok(ast::LitKind::Str(s, _)) => s.to_string(), + Ok(ast::LitKind::Float(..)) => { + return make_err(MveConcatInvalidReason::FloatLit); + } + Ok(ast::LitKind::Char(c)) => c.to_string(), + Ok(ast::LitKind::Int(i, _)) => i.to_string(), + Ok(ast::LitKind::Bool(b)) => b.to_string(), + Ok(ast::LitKind::CStr(..)) => return make_err(MveConcatInvalidReason::CStrLit), + Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => { + return make_err(MveConcatInvalidReason::ByteStrLit); } - Ok(elem) => MetaVarExprConcatElem::Ident(elem), + Ok(ast::LitKind::Err(_guarantee)) => { + // REVIEW: a diagnostic was already emitted, should we just break? + return make_err(MveConcatInvalidReason::InvalidLiteral); + } + Err(err) => return Err(create_lit_error(psess, err, lit, token.span)), + }; + + if !s.chars().all(|ch| is_id_continue(ch)) { + // Check that all characters are valid in the middle of an identifier. This doesn't + // guarantee that the final identifier is valid (we still need to check it later), + // but it allows us to catch errors with specific arguments before expansion time; + // for example, string literal "foo.bar" gets flagged before the macro is invoked. + return make_err(MveConcatInvalidReason::InvalidIdent); + } + + MetaVarExprConcatElem::Ident(s) + } else if let Some((elem, is_raw)) = token.ident() { + if is_raw == IdentIsRaw::Yes { + return make_err(MveConcatInvalidReason::RawIdentifier); } + MetaVarExprConcatElem::Ident(elem.as_str().to_string()) + } else { + return make_err(MveConcatInvalidReason::UnsupportedInput); }; + result.push(element); + if iter.peek().is_none() { + // break before trying to eat the comma break; } + if !try_eat_comma(iter) { return Err(psess.dcx().struct_span_err(outer_span, "expected comma")); } @@ -290,43 +355,6 @@ fn parse_ident<'psess>( Ok(elem) } -fn parse_ident_from_token<'psess>( - psess: &'psess ParseSess, - token: &Token, -) -> PResult<'psess, Ident> { - if let Some((elem, is_raw)) = token.ident() { - if let IdentIsRaw::Yes = is_raw { - return Err(psess.dcx().struct_span_err(elem.span, RAW_IDENT_ERR)); - } - return Ok(elem); - } - let token_str = pprust::token_to_string(token); - let mut err = psess - .dcx() - .struct_span_err(token.span, format!("expected identifier, found `{token_str}`")); - err.span_suggestion( - token.span, - format!("try removing `{token_str}`"), - "", - Applicability::MaybeIncorrect, - ); - Err(err) -} - -fn parse_token<'psess, 't>( - iter: &mut TokenStreamIter<'t>, - psess: &'psess ParseSess, - fallback_span: Span, -) -> PResult<'psess, &'t Token> { - let Some(tt) = iter.next() else { - return Err(psess.dcx().struct_span_err(fallback_span, UNSUPPORTED_CONCAT_ELEM_ERR)); - }; - let TokenTree::Token(token, _) = tt else { - return Err(psess.dcx().struct_span_err(tt.span(), UNSUPPORTED_CONCAT_ELEM_ERR)); - }; - Ok(token) -} - /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the /// iterator is not modified and the result is `false`. fn try_eat_comma(iter: &mut TokenStreamIter<'_>) -> bool { @@ -337,14 +365,14 @@ fn try_eat_comma(iter: &mut TokenStreamIter<'_>) -> bool { false } -/// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the -/// iterator is not modified and the result is `false`. -fn try_eat_dollar(iter: &mut TokenStreamIter<'_>) -> bool { - if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.peek() { +/// Tries to move the iterator forward returning `Some(dollar_span)` if there is a dollar sign. If +/// not, then the iterator is not modified and the result is `None`. +fn try_eat_dollar(iter: &mut TokenStreamIter<'_>) -> Option { + if let Some(TokenTree::Token(Token { kind: token::Dollar, span }, _)) = iter.peek() { let _ = iter.next(); - return true; + return Some(*span); } - false + None } /// Expects that the next item is a dollar sign. @@ -353,7 +381,7 @@ fn eat_dollar<'psess>( psess: &'psess ParseSess, span: Span, ) -> PResult<'psess, ()> { - if try_eat_dollar(iter) { + if try_eat_dollar(iter).is_some() { return Ok(()); } Err(psess.dcx().struct_span_err( diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 1781a0c077163..a9907715d0342 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -545,9 +545,10 @@ fn metavar_expr_concat<'tx>( let dcx = tscx.psess.dcx(); let mut concatenated = String::new(); for element in elements.into_iter() { - let symbol = match element { - MetaVarExprConcatElem::Ident(elem) => elem.name, - MetaVarExprConcatElem::Literal(elem) => *elem, + let tmp_sym; + let sym_str = match element { + MetaVarExprConcatElem::Ident(elem) => elem.as_str(), + MetaVarExprConcatElem::Literal(elem) => elem.as_str(), MetaVarExprConcatElem::Var(ident) => { match matched_from_ident(dcx, *ident, tscx.interp)? { NamedMatch::MatchedSeq(named_matches) => { @@ -557,16 +558,20 @@ fn metavar_expr_concat<'tx>( match &named_matches[*curr_idx] { // FIXME(c410-f3r) Nested repetitions are unimplemented MatchedSeq(_) => unimplemented!(), - MatchedSingle(pnr) => extract_symbol_from_pnr(dcx, pnr, ident.span)?, + MatchedSingle(pnr) => { + tmp_sym = extract_symbol_from_pnr(tscx, pnr, ident.span)?; + tmp_sym.as_str() + } } } NamedMatch::MatchedSingle(pnr) => { - extract_symbol_from_pnr(dcx, pnr, ident.span)? + tmp_sym = extract_symbol_from_pnr(tscx, pnr, ident.span)?; + tmp_sym.as_str() } } } }; - concatenated.push_str(symbol.as_str()); + concatenated.push_str(sym_str); } let symbol = nfc_normalize(&concatenated); let concatenated_span = tscx.visited_dspan(dspan); @@ -900,11 +905,13 @@ fn out_of_bounds_err<'a>(dcx: DiagCtxtHandle<'a>, max: usize, span: Span, ty: &s } /// Extracts an metavariable symbol that can be an identifier, a token tree or a literal. -fn extract_symbol_from_pnr<'a>( - dcx: DiagCtxtHandle<'a>, +// TODO: use the same logic as for metavar_expr +fn extract_symbol_from_pnr<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, pnr: &ParseNtResult, span_err: Span, -) -> PResult<'a, Symbol> { +) -> PResult<'tx, Symbol> { + let dcx = tscx.psess.dcx(); match pnr { ParseNtResult::Ident(nt_ident, is_raw) => { if let IdentIsRaw::Yes = is_raw { diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index bf95014843d23..f9196abb3039f 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -378,12 +378,18 @@ pub(crate) struct UnsupportedCrateTypeForTarget<'a> { pub(crate) target_triple: &'a TargetTuple, } +/// Emit an error related to a literal. pub fn report_lit_error( psess: &ParseSess, err: LitError, lit: token::Lit, span: Span, ) -> ErrorGuaranteed { + create_lit_error(psess, err, lit, span).emit() +} + +/// Build an error related to a literal. +pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: Span) -> Diag<'_> { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) @@ -414,32 +420,32 @@ pub fn report_lit_error( let dcx = psess.dcx(); match err { LitError::InvalidSuffix(suffix) => { - dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) + dcx.create_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) } LitError::InvalidIntSuffix(suffix) => { let suf = suffix.as_str(); if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) + dcx.create_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) { - dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }) + dcx.create_err(InvalidNumLiteralBasePrefix { span, fixed }) } else { - dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) + dcx.create_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::InvalidFloatSuffix(suffix) => { let suf = suffix.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) + dcx.create_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) } else { - dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) + dcx.create_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::NonDecimalFloat(base) => match base { - 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), - 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), - 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), + 16 => dcx.create_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => dcx.create_err(OctalFloatLiteralNotSupported { span }), + 2 => dcx.create_err(BinaryFloatLiteralNotSupported { span }), _ => unreachable!(), }, LitError::IntTooLarge(base) => { @@ -450,7 +456,7 @@ pub fn report_lit_error( 16 => format!("{max:#x}"), _ => format!("{max}"), }; - dcx.emit_err(IntLiteralTooLarge { span, limit }) + dcx.create_err(IntLiteralTooLarge { span, limit }) } } } diff --git a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs index 695a752fe17d4..837687ffeb83e 100644 --- a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs +++ b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs @@ -38,7 +38,14 @@ macro_rules! without_dollar_sign_is_an_ident { } macro_rules! combinations { - ($ident:ident, $literal:literal, $tt_ident:tt, $tt_literal:tt) => {{ + ( + $ident:ident, + $literal:literal, + $char:literal, + $tt_ident:tt, + $tt_literal:tt, + $tt_char:tt + ) => {{ // tt ident let ${concat($tt_ident, b)} = (); let ${concat($tt_ident, _b)} = (); @@ -89,17 +96,39 @@ macro_rules! combinations { let ${concat($literal, $tt_literal)} = (); let ${concat($literal, $ident)} = (); let ${concat($literal, $literal)} = (); + + // char literal (adhoc) + let ${concat('a', b)} = (); + let ${concat('a', _b)} = (); + let ${concat('a', 'b')} = (); + let ${concat('a', $tt_ident)} = (); + let ${concat('a', $tt_literal)} = (); + let ${concat('a', $ident)} = (); + let ${concat('a', $literal)} = (); + // char literal (param) + let ${concat($literal, b)} = (); + let ${concat($literal, _b)} = (); + let ${concat($literal, 'b')} = (); + let ${concat($literal, $tt_ident)} = (); + let ${concat($literal, $tt_literal)} = (); + let ${concat($literal, $ident)} = (); + let ${concat($literal, $literal)} = (); }}; } +macro_rules! stripped_suffixes { + ($x:literal) => { + assert_eq!(stringify!(${concat("a", 40u32)}), "a40"); + // TODO + // assert_eq!(stringify!(${concat("a", $x)}), "a100"); + }; +} + fn main() { create_things!(behold); behold_separated_idents_in_a_fn(); let _ = behold_separated_idents_in_a_module::FOO; - let _ = behold_separated_idents_in_a_struct { - foo: 1, - behold_separated_idents_in_a_field: 2, - }; + let _ = behold_separated_idents_in_a_struct { foo: 1, behold_separated_idents_in_a_field: 2 }; many_idents!(A, C); assert_eq!(ABCD, 1); @@ -111,5 +140,7 @@ fn main() { assert_eq!(VARident, 1); assert_eq!(VAR_123, 2); - combinations!(_hello, "a", b, "b"); + combinations!(_hello, "a", 'a', b, "b", 'b'); + + stripped_suffixes!(100u32); } diff --git a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs index b1cb2141cc42f..3612ef20b5e5c 100644 --- a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs +++ b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs @@ -26,14 +26,14 @@ macro_rules! idents_11 { macro_rules! no_params { () => { let ${concat(r#abc, abc)}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression //~| ERROR expected pattern, found `$` let ${concat(abc, r#abc)}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat(r#abc, r#abc)}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression }; } diff --git a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr index 7abab6a510358..3d01e1325192b 100644 --- a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr +++ b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr @@ -1,20 +1,41 @@ -error: expected identifier or string literal +error: invalid item within a `${concat(...)}` expression --> $DIR/concat-raw-identifiers.rs:28:22 | LL | let ${concat(r#abc, abc)}: () = (); | ^^^^^ + | + = note: raw identifiers cannot be concatenated +help: expanding this `concat(...)` expression + --> $DIR/concat-raw-identifiers.rs:28:15 + | +LL | let ${concat(r#abc, abc)}: () = (); + | ^^^^^^ -error: expected identifier or string literal +error: invalid item within a `${concat(...)}` expression --> $DIR/concat-raw-identifiers.rs:32:27 | LL | let ${concat(abc, r#abc)}: () = (); | ^^^^^ + | + = note: raw identifiers cannot be concatenated +help: expanding this `concat(...)` expression + --> $DIR/concat-raw-identifiers.rs:32:15 + | +LL | let ${concat(abc, r#abc)}: () = (); + | ^^^^^^ -error: expected identifier or string literal +error: invalid item within a `${concat(...)}` expression --> $DIR/concat-raw-identifiers.rs:35:22 | LL | let ${concat(r#abc, r#abc)}: () = (); | ^^^^^ + | + = note: raw identifiers cannot be concatenated +help: expanding this `concat(...)` expression + --> $DIR/concat-raw-identifiers.rs:35:15 + | +LL | let ${concat(r#abc, r#abc)}: () = (); + | ^^^^^^ error: `${concat(..)}` currently does not support raw identifiers --> $DIR/concat-raw-identifiers.rs:5:28 diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.rs b/tests/ui/macros/metavar-expressions/concat-trace-errors.rs index 45407f5e86d56..75f01266eb4d2 100644 --- a/tests/ui/macros/metavar-expressions/concat-trace-errors.rs +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.rs @@ -7,8 +7,11 @@ macro_rules! pre_expansion { ($a:ident) => { ${concat("hi", " bye ")}; + //~^ ERROR invalid item within a `${concat(...)}` expression ${concat("hi", "-", "bye")}; + //~^ ERROR invalid item within a `${concat(...)}` expression ${concat($a, "-")}; + //~^ ERROR invalid item within a `${concat(...)}` expression } } diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr index dac8b58a15ce2..45ed5204dd24e 100644 --- a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr @@ -1,5 +1,44 @@ +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-trace-errors.rs:9:24 + | +LL | ${concat("hi", " bye ")}; + | ^^^^^^^ + | + = note: this literal produced an invalid identifier +help: expanding this `concat(...)` expression + --> $DIR/concat-trace-errors.rs:9:11 + | +LL | ${concat("hi", " bye ")}; + | ^^^^^^ + +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-trace-errors.rs:11:24 + | +LL | ${concat("hi", "-", "bye")}; + | ^^^ + | + = note: this literal produced an invalid identifier +help: expanding this `concat(...)` expression + --> $DIR/concat-trace-errors.rs:11:11 + | +LL | ${concat("hi", "-", "bye")}; + | ^^^^^^ + +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-trace-errors.rs:13:22 + | +LL | ${concat($a, "-")}; + | ^^^ + | + = note: this literal produced an invalid identifier +help: expanding this `concat(...)` expression + --> $DIR/concat-trace-errors.rs:13:11 + | +LL | ${concat($a, "-")}; + | ^^^^^^ + error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-trace-errors.rs:17:24 + --> $DIR/concat-trace-errors.rs:20:24 | LL | const _: () = ${concat("hi", $a, "bye")}; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +49,7 @@ LL | post_expansion!("!"); = 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:29:24 | LL | const _: () = ${concat($a, $b, $c, $d, $e)}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,5 +59,5 @@ LL | post_expansion_many!(a, b, c, ".d", e); | = 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 +error: aborting due to 5 previous errors diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs index 7d8756de9e20b..68857d3c33c2c 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs @@ -5,13 +5,13 @@ macro_rules! syntax_errors { ($ex:expr) => { ${concat()} - //~^ ERROR expected identifier + //~^ ERROR `concat` must have at least two elements ${concat(aaaa)} //~^ ERROR `concat` must have at least two elements ${concat(aaaa,)} - //~^ ERROR expected identifier + //~^ ERROR `concat` must have at least two elements ${concat(_, aaaa)} @@ -28,7 +28,6 @@ macro_rules! syntax_errors { //~^ ERROR expected comma ${concat($ex, aaaa,)} - //~^ ERROR expected identifier }; } @@ -55,7 +54,8 @@ macro_rules! starting_valid_unicode { macro_rules! starting_invalid_unicode { ($ident:ident) => {{ let ${concat("\u{00BD}", $ident)}: () = (); - //~^ ERROR `${concat(..)}` is not generating a valid identifier + //~^ ERROR invalid item within a `${concat(...)}` expression + //~| ERROR expected pattern }}; } @@ -74,7 +74,8 @@ macro_rules! ending_valid_unicode { macro_rules! ending_invalid_unicode { ($ident:ident) => {{ let ${concat($ident, "\u{00BD}")}: () = (); - //~^ ERROR `${concat(..)}` is not generating a valid identifier + //~^ ERROR invalid item within a `${concat(...)}` expression + //~| ERROR expected pattern }}; } @@ -87,36 +88,28 @@ macro_rules! empty { macro_rules! unsupported_literals { ($ident:ident) => {{ - let ${concat(_a, 'b')}: () = (); - //~^ ERROR expected identifier or string literal - //~| ERROR expected pattern - let ${concat(_a, 1)}: () = (); - //~^ ERROR expected identifier or string literal let ${concat(_a, 1.5)}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression + //~| ERROR expected pattern let ${concat(_a, c"hi")}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat(_a, b"hi")}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat(_a, b'b')}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat(_a, b'b')}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression - let ${concat($ident, 'b')}: () = (); - //~^ ERROR expected identifier or string literal - let ${concat($ident, 1)}: () = (); - //~^ ERROR expected identifier or string literal let ${concat($ident, 1.5)}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat($ident, c"hi")}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat($ident, b"hi")}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat($ident, b'b')}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression let ${concat($ident, b'b')}: () = (); - //~^ ERROR expected identifier or string literal + //~^ ERROR invalid item within a `${concat(...)}` expression }}; } diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr index 8be3e792ec3f2..ce16f2bef8d06 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr @@ -1,8 +1,8 @@ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:7:10 +error: `concat` must have at least two elements + --> $DIR/concat-usage-errors.rs:7:11 | LL | ${concat()} - | ^^^^^^^^^^ + | ^^^^^^ error: `concat` must have at least two elements --> $DIR/concat-usage-errors.rs:10:11 @@ -10,11 +10,11 @@ error: `concat` must have at least two elements LL | ${concat(aaaa)} | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:13:10 +error: `concat` must have at least two elements + --> $DIR/concat-usage-errors.rs:13:11 | LL | ${concat(aaaa,)} - | ^^^^^^^^^^^^^^^ + | ^^^^^^ error: expected comma --> $DIR/concat-usage-errors.rs:18:10 @@ -34,95 +34,171 @@ error: expected comma LL | ${concat($ex, aaaa 123)} | ^^^^^^^^^^^^^^^^^^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:30:10 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:56:22 | -LL | ${concat($ex, aaaa,)} - | ^^^^^^^^^^^^^^^^^^^^ - -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:90:26 +LL | let ${concat("\u{00BD}", $ident)}: () = (); + | ^^^^^^^^^^ | -LL | let ${concat(_a, 'b')}: () = (); - | ^^^ + = note: this literal produced an invalid identifier +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:56:15 + | +LL | let ${concat("\u{00BD}", $ident)}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:93:26 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:76:30 + | +LL | let ${concat($ident, "\u{00BD}")}: () = (); + | ^^^^^^^^^^ + | + = note: this literal produced an invalid identifier +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:76:15 | -LL | let ${concat(_a, 1)}: () = (); - | ^ +LL | let ${concat($ident, "\u{00BD}")}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:95:26 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:91:26 | LL | let ${concat(_a, 1.5)}: () = (); | ^^^ + | + = note: float literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:91:15 + | +LL | let ${concat(_a, 1.5)}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:97:26 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:94:26 | LL | let ${concat(_a, c"hi")}: () = (); | ^^^^^ + | + = note: C string literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:94:15 + | +LL | let ${concat(_a, c"hi")}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:99:26 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:96:26 | LL | let ${concat(_a, b"hi")}: () = (); | ^^^^^ + | + = note: byte literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:96:15 + | +LL | let ${concat(_a, b"hi")}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:101:26 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:98:26 | LL | let ${concat(_a, b'b')}: () = (); | ^^^^ + | + = note: byte literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:98:15 + | +LL | let ${concat(_a, b'b')}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:103:26 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:100: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')}: () = (); - | ^^^ - -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:108:30 + = note: byte literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:100:15 | -LL | let ${concat($ident, 1)}: () = (); - | ^ +LL | let ${concat(_a, b'b')}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:110:30 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:103:30 | LL | let ${concat($ident, 1.5)}: () = (); | ^^^ + | + = note: float literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:103:15 + | +LL | let ${concat($ident, 1.5)}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:112:30 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:105:30 | LL | let ${concat($ident, c"hi")}: () = (); | ^^^^^ + | + = note: C string literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:105:15 + | +LL | let ${concat($ident, c"hi")}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:114:30 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:107:30 | LL | let ${concat($ident, b"hi")}: () = (); | ^^^^^ + | + = note: byte literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:107:15 + | +LL | let ${concat($ident, b"hi")}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:116:30 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:109:30 | LL | let ${concat($ident, b'b')}: () = (); | ^^^^ + | + = note: byte literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:109:15 + | +LL | let ${concat($ident, b'b')}: () = (); + | ^^^^^^ -error: expected identifier or string literal - --> $DIR/concat-usage-errors.rs:118:30 +error: invalid item within a `${concat(...)}` expression + --> $DIR/concat-usage-errors.rs:111:30 | LL | let ${concat($ident, b'b')}: () = (); | ^^^^ + | + = note: byte literals cannot be concatenated + = help: `concat` can join metavariables, identifiers, string literals, and integer literals +help: expanding this `concat(...)` expression + --> $DIR/concat-usage-errors.rs:111:15 + | +LL | let ${concat($ident, b'b')}: () = (); + | ^^^^^^ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` --> $DIR/concat-usage-errors.rs:24:19 @@ -133,13 +209,13 @@ LL | ${concat($ex, aaaa)} = note: currently only string literals are supported error: variable `foo` is not recognized in meta-variable expression - --> $DIR/concat-usage-errors.rs:37:30 + --> $DIR/concat-usage-errors.rs:36:30 | LL | const ${concat(FOO, $foo)}: i32 = 2; | ^^^ error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:44:14 + --> $DIR/concat-usage-errors.rs:43:14 | LL | let ${concat("1", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^ @@ -149,22 +225,22 @@ LL | starting_number!(_abc); | = 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 - --> $DIR/concat-usage-errors.rs:57:14 +error: expected pattern, found `$` + --> $DIR/concat-usage-errors.rs:56:13 | LL | let ${concat("\u{00BD}", $ident)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected pattern ... LL | starting_invalid_unicode!(_abc); | ------------------------------- in this macro invocation | = 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 - --> $DIR/concat-usage-errors.rs:76:14 +error: expected pattern, found `$` + --> $DIR/concat-usage-errors.rs:76:13 | LL | let ${concat($ident, "\u{00BD}")}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected pattern ... LL | ending_invalid_unicode!(_abc); | ----------------------------- in this macro invocation @@ -172,9 +248,9 @@ 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) error: expected pattern, found `$` - --> $DIR/concat-usage-errors.rs:90:13 + --> $DIR/concat-usage-errors.rs:91:13 | -LL | let ${concat(_a, 'b')}: () = (); +LL | let ${concat(_a, 1.5)}: () = (); | ^ expected pattern ... LL | unsupported_literals!(_abc); @@ -183,7 +259,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:83:14 + --> $DIR/concat-usage-errors.rs:84:14 | LL | let ${concat("", "")}: () = (); | ^^^^^^^^^^^^^^^^ @@ -194,7 +270,7 @@ LL | empty!(); = 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 - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +281,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -216,7 +292,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -227,7 +303,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +314,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -249,7 +325,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -260,7 +336,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) error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-usage-errors.rs:125:16 + --> $DIR/concat-usage-errors.rs:118:16 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +347,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) error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:138:31 + --> $DIR/concat-usage-errors.rs:131:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -279,7 +355,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:138:31 + --> $DIR/concat-usage-errors.rs:131:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -288,7 +364,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:138:31 + --> $DIR/concat-usage-errors.rs:131:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -297,7 +373,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:138:31 + --> $DIR/concat-usage-errors.rs:131:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -306,7 +382,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:138:31 + --> $DIR/concat-usage-errors.rs:131:31 | LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^ @@ -315,7 +391,7 @@ LL | const ${concat(_foo, $literal)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:149:31 + --> $DIR/concat-usage-errors.rs:142:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -323,7 +399,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: currently only string literals are supported error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:149:31 + --> $DIR/concat-usage-errors.rs:142:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -332,7 +408,7 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:149:31 + --> $DIR/concat-usage-errors.rs:142:31 | LL | const ${concat(_foo, $tt)}: () = (); | ^^ @@ -340,5 +416,5 @@ LL | const ${concat(_foo, $tt)}: () = (); = note: currently only string literals are supported = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 43 previous errors +error: aborting due to 40 previous errors diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.rs b/tests/ui/macros/metavar-expressions/syntax-errors.rs index dd6e0304e25c3..af3dc036a69a4 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.rs +++ b/tests/ui/macros/metavar-expressions/syntax-errors.rs @@ -18,12 +18,7 @@ macro_rules! metavar_in_the_lhs { }; } -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 { +macro_rules! mve_with_literal_suffix { ( $( $i:ident ),* ) => { ${ index(1u32) } }; //~^ ERROR only unsuffixes integer literals are supported in meta-variable expressions } @@ -55,6 +50,16 @@ macro_rules! invalid_metavar { //~^ ERROR expected an identifier } +macro_rules! mve_wrong_delim { + ( $( $i:ident ),* ) => { ${ count{i} } }; + //~^ ERROR expected `(` +} + +macro_rules! invalid_metavar { + () => { ${ignore($123)} } + //~^ ERROR expected an identifier +} + #[rustfmt::skip] macro_rules! open_brackets_with_group { ( $( $i:ident ),* ) => { ${ {} } }; @@ -109,6 +114,11 @@ macro_rules! unknown_ignore_ident { }; } +macro_rules! ignore_no_ident { + ( $( $i:ident ),* ) => { ${ ignore() } }; + //~^ ERROR meta-variable expressions must be referenced using a dollar sign +} + macro_rules! unknown_metavar { ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; //~^ ERROR unrecognized metavariable expression diff --git a/tests/ui/macros/metavar-expressions/syntax-errors.stderr b/tests/ui/macros/metavar-expressions/syntax-errors.stderr index ee5a25be42838..e41ee37afc9f3 100644 --- a/tests/ui/macros/metavar-expressions/syntax-errors.stderr +++ b/tests/ui/macros/metavar-expressions/syntax-errors.stderr @@ -28,20 +28,14 @@ error: expected one of: `*`, `+`, or `?` 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 + --> $DIR/syntax-errors.rs:22:33 | LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; | ^^^^^ error: expected `(` - --> $DIR/syntax-errors.rs:32:38 + --> $DIR/syntax-errors.rs:27:38 | LL | ( $( $i:ident ),* ) => { ${ count } }; | ^ help: try adding parentheses: `( /* ... */ )` @@ -49,7 +43,23 @@ LL | ( $( $i:ident ),* ) => { ${ count } }; = note: metavariable expressions use function-like parentheses syntax error: expected `(` - --> $DIR/syntax-errors.rs:49:38 + --> $DIR/syntax-errors.rs:44:38 + | +LL | ( $( $i:ident ),* ) => { ${ count{i} } }; + | ^ + | + = note: metavariable expressions use function-like parentheses syntax + +error: expected an identifier + --> $DIR/syntax-errors.rs:49:23 + | +LL | () => { ${ignore($123)} } + | ^^^ not a valid identifier + | + = note: `ignore` takes a metavariable argument + +error: expected `(` + --> $DIR/syntax-errors.rs:54:38 | LL | ( $( $i:ident ),* ) => { ${ count{i} } }; | ^ @@ -57,7 +67,7 @@ LL | ( $( $i:ident ),* ) => { ${ count{i} } }; = note: metavariable expressions use function-like parentheses syntax error: expected an identifier - --> $DIR/syntax-errors.rs:54:23 + --> $DIR/syntax-errors.rs:59:23 | LL | () => { ${ignore($123)} } | ^^^ not a valid identifier @@ -65,13 +75,13 @@ LL | () => { ${ignore($123)} } = note: `ignore` takes a metavariable argument error: unexpected trailing tokens in metavariable expression braces - --> $DIR/syntax-errors.rs:66:19 + --> $DIR/syntax-errors.rs:71:19 | LL | ${count() a b c} | ^^^^^ help: try removing these tokens error: unexpected trailing tokens in metavariable expression - --> $DIR/syntax-errors.rs:68:20 + --> $DIR/syntax-errors.rs:73:20 | LL | ${count($i a b c)} | ----- ^^^^^ help: try removing these tokens @@ -81,7 +91,7 @@ LL | ${count($i a b c)} = note: the `count` metavariable expression takes up to 2 arguments error: unexpected trailing tokens in metavariable expression - --> $DIR/syntax-errors.rs:70:23 + --> $DIR/syntax-errors.rs:75:23 | LL | ${count($i, 1 a b c)} | ----- ^^^^^ help: try removing these tokens @@ -91,19 +101,19 @@ LL | ${count($i, 1 a b c)} = note: the `count` metavariable expression takes up to 2 arguments error: unexpected trailing tokens in metavariable expression braces - --> $DIR/syntax-errors.rs:72:21 + --> $DIR/syntax-errors.rs:77:21 | LL | ${count($i) a b c} | ^^^^^ help: try removing these tokens error: unexpected trailing tokens in metavariable expression braces - --> $DIR/syntax-errors.rs:75:22 + --> $DIR/syntax-errors.rs:80:22 | LL | ${ignore($i) a b c} | ^^^^^ help: try removing these tokens error: unexpected trailing tokens in metavariable expression - --> $DIR/syntax-errors.rs:77:21 + --> $DIR/syntax-errors.rs:82:21 | LL | ${ignore($i a b c)} | ------ ^^^^^ help: try removing these tokens @@ -113,13 +123,13 @@ LL | ${ignore($i a b c)} = note: the `ignore` metavariable expression takes up to 1 arguments error: unexpected trailing tokens in metavariable expression braces - --> $DIR/syntax-errors.rs:80:19 + --> $DIR/syntax-errors.rs:85:19 | LL | ${index() a b c} | ^^^^^ help: try removing these tokens error: unexpected trailing tokens in metavariable expression - --> $DIR/syntax-errors.rs:82:19 + --> $DIR/syntax-errors.rs:87:19 | LL | ${index(1 a b c)} | ----- ^^^^^ help: try removing these tokens @@ -129,13 +139,13 @@ LL | ${index(1 a b c)} = note: the `index` metavariable expression takes up to 2 arguments error: unexpected trailing tokens in metavariable expression braces - --> $DIR/syntax-errors.rs:85:19 + --> $DIR/syntax-errors.rs:90:19 | LL | ${index() a b c} | ^^^^^ help: try removing these tokens error: unexpected trailing tokens in metavariable expression - --> $DIR/syntax-errors.rs:87:19 + --> $DIR/syntax-errors.rs:92:19 | LL | ${index(1 a b c)} | ----- ^^^^^ help: try removing these tokens @@ -145,25 +155,31 @@ LL | ${index(1 a b c)} = note: the `index` metavariable expression takes up to 2 arguments error: meta-variable expression depth must be a literal - --> $DIR/syntax-errors.rs:94:33 + --> $DIR/syntax-errors.rs:99: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 + --> $DIR/syntax-errors.rs:105:11 | LL | ${count(foo)} | ^^^^^ error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:107:11 + --> $DIR/syntax-errors.rs:112:11 | LL | ${ignore(bar)} | ^^^^^^ +error: meta-variables within meta-variable expressions must be referenced using a dollar sign + --> $DIR/syntax-errors.rs:118:33 + | +LL | ( $( $i:ident ),* ) => { ${ ignore() } }; + | ^^^^^^ + error: unrecognized metavariable expression - --> $DIR/syntax-errors.rs:113:33 + --> $DIR/syntax-errors.rs:123:33 | LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; | ^^^^^^^^^^^^^^ not a valid metavariable expression @@ -171,7 +187,7 @@ LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` error: expected an identifier - --> $DIR/syntax-errors.rs:38:14 + --> $DIR/syntax-errors.rs:33:14 | LL | () => { ${} }; | ^^ @@ -180,7 +196,7 @@ LL | () => { ${} }; = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` error: expected an identifier - --> $DIR/syntax-errors.rs:44:17 + --> $DIR/syntax-errors.rs:39:17 | LL | () => { ${ "hi" } }; | ^^^^ not a valid identifier @@ -189,7 +205,7 @@ LL | () => { ${ "hi" } }; = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` error: expected an identifier - --> $DIR/syntax-errors.rs:60:33 + --> $DIR/syntax-errors.rs:65:33 | LL | ( $( $i:ident ),* ) => { ${ {} } }; | ^^ not a valid identifier @@ -197,5 +213,5 @@ LL | ( $( $i:ident ),* ) => { ${ {} } }; = note: expected a metavariable expression name: `${expr( /* ... */ )}` = note: valid metavariable expressions are `count`, `ignore`, `index`, `len`, and `concat` -error: aborting due to 25 previous errors +error: aborting due to 27 previous errors From b576c49ec15a01df91244aa6a3d538b342807607 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 24 Jun 2025 02:27:43 -0400 Subject: [PATCH 11/11] mbe: Refactor concat diagnostics --- compiler/rustc_expand/messages.ftl | 21 +- compiler/rustc_expand/src/errors.rs | 38 ++- compiler/rustc_expand/src/mbe/metavar_expr.rs | 121 ++++--- compiler/rustc_expand/src/mbe/transcribe.rs | 76 ++--- compiler/rustc_parse/src/parser/mod.rs | 21 ++ .../concat-raw-identifiers.rs | 26 +- .../concat-raw-identifiers.stderr | 121 +++---- .../concat-trace-errors.rs | 6 +- .../concat-trace-errors.stderr | 49 +-- .../concat-usage-errors.rs | 26 +- .../concat-usage-errors.stderr | 299 ++++++------------ 11 files changed, 362 insertions(+), 442 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 0c37a91be8878..b08eafba470cd 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -133,20 +133,23 @@ expand_module_multiple_candidates = expand_must_repeat_once = this must repeat at least once -expand_mve_concat_invalid = - invalid item within a `{"${concat(...)}"}` expression - .expr_ident = expanding this `concat(...)` expression - .invalid_ident = this literal produced an invalid identifier +expand_mve_concat_invalid_in = + invalid item within a {"`${concat(..)}`"} expression + .metavar_label = expanding this metavariable .float_lit = float literals cannot be concatenated .c_str_lit = C string literals cannot be concatenated .b_str_lit = byte literals cannot be concatenated .raw_ident = raw identifiers cannot be concatenated - .unsupported = unsupported input for `concat(...)` + .unsupported = unsupported input for `concat(..)` .valid_types = `concat` can join {$valid} - .expected_metavar = expected an identifier; got `{$found}` - .expected_metavar_dollar = todo - .unexpected_group = todo - .hi_label = todo + .expected_metavar = expected an identifier + .expected_metavar_dollar = `$` indicates the start of a metavariable + .invalid_metavar = expanding something + .valid_metavars = {"`${concat(..)}`"} can join metavariables of type {$valid} + +expand_mve_concat_invalid_out = + invalid item within a {"`${concat(..)}`"} would produce an invalid identifier + .label = todo expand_mve_expected_ident = expected an identifier diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index ff674ff512b09..449d1cea3fb56 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -498,48 +498,58 @@ mod metavar_exprs { use super::*; #[derive(Diagnostic)] - #[diag(expand_mve_concat_invalid)] - pub(crate) struct MveConcatInvalid { + #[diag(expand_mve_concat_invalid_in)] + pub(crate) struct MveConcatInvalidTy { #[primary_span] + // #[label] pub span: Span, + #[label(expand_metavar_label)] + pub metavar_span: Option, #[subdiagnostic] - pub reason: MveConcatInvalidReason, - #[help(expand_expr_ident)] - pub ident_span: Span, + pub reason: MveConcatInvalidTyReason, pub valid: &'static str, } // TODO: can these be labels rather than notes? #[derive(Subdiagnostic)] - pub(crate) enum MveConcatInvalidReason { - #[note(expand_invalid_ident)] + pub(crate) enum MveConcatInvalidTyReason { InvalidIdent, #[note(expand_float_lit)] - #[help(expand_valid_types)] + #[note(expand_valid_types)] FloatLit, #[note(expand_c_str_lit)] - #[help(expand_valid_types)] + #[note(expand_valid_types)] CStrLit, #[note(expand_b_str_lit)] - #[help(expand_valid_types)] + #[note(expand_valid_types)] ByteStrLit, #[note(expand_expected_metavar)] #[label(expand_expected_metavar_dollar)] ExpectedMetavarIdent { - found: String, #[primary_span] dollar: Span, }, #[note(expand_raw_ident)] RawIdentifier, #[note(expand_unsupported)] - #[help(expand_valid_types)] + #[note(expand_valid_types)] UnsupportedInput, - #[note(expand_unexpected_group)] - UnexpectedGroup, + #[note(expand_invalid_metavar)] + #[note(expand_valid_metavars)] + InvalidMetavarTy, + /// Nothing to point out because an error was already emitted. InvalidLiteral, } + #[derive(Diagnostic)] + #[note] + #[diag(expand_mve_concat_invalid_out)] + pub(crate) struct MveConcatInvalidOut { + #[primary_span] + #[label] + pub span: Span, + } + #[derive(Diagnostic)] #[diag(expand_mve_expected_ident)] pub(crate) struct MveExpectedIdent { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 26211f9ac67e6..f4e11e5b851e7 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -2,16 +2,15 @@ use rustc_ast::token::{self, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; use rustc_ast::{self as ast, LitIntType, LitKind}; use rustc_ast_pretty::pprust; -use rustc_errors::PResult; +use rustc_errors::{DiagCtxtHandle, PResult}; use rustc_lexer::is_id_continue; use rustc_macros::{Decodable, Encodable}; use rustc_session::errors::create_lit_error; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol}; -use crate::errors::{self, MveConcatInvalidReason, MveExpectedIdentContext}; +use crate::errors::{self, MveConcatInvalidTyReason, MveExpectedIdentContext}; -pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; pub(crate) const VALID_EXPR_CONCAT_TYPES: &str = "metavariables, identifiers, string literals, and integer literals"; @@ -193,9 +192,9 @@ fn parse_concat<'psess>( }; let make_err = |reason| { - let err = errors::MveConcatInvalid { + let err = errors::MveConcatInvalidTy { span: tt.span(), - ident_span: expr_ident_span, + metavar_span: None, reason, valid: VALID_EXPR_CONCAT_TYPES, }; @@ -203,64 +202,22 @@ fn parse_concat<'psess>( }; let token = match tt { - TokenTree::Token(token, _) => token, + TokenTree::Token(token, _) => *token, TokenTree::Delimited(..) => { - return make_err(MveConcatInvalidReason::UnexpectedGroup); + return make_err(MveConcatInvalidTyReason::UnsupportedInput); } }; let element = if let Some(dollar) = dollar { // Expecting a metavar let Some((ident, _)) = token.ident() else { - return make_err(MveConcatInvalidReason::ExpectedMetavarIdent { - found: pprust::token_to_string(token).into_owned(), - dollar, - }); + return make_err(MveConcatInvalidTyReason::ExpectedMetavarIdent { dollar }); }; // Variables get passed untouched MetaVarExprConcatElem::Var(ident) - } else if let TokenKind::Literal(lit) = token.kind { - // Preprocess with `from_token_lit` to handle unescaping, float / int literal suffix - // stripping. - // - // For consistent user experience, please keep this in sync with the handling of - // literals in `rustc_builtin_macros::concat`! - let s = match ast::LitKind::from_token_lit(lit.clone()) { - Ok(ast::LitKind::Str(s, _)) => s.to_string(), - Ok(ast::LitKind::Float(..)) => { - return make_err(MveConcatInvalidReason::FloatLit); - } - Ok(ast::LitKind::Char(c)) => c.to_string(), - Ok(ast::LitKind::Int(i, _)) => i.to_string(), - Ok(ast::LitKind::Bool(b)) => b.to_string(), - Ok(ast::LitKind::CStr(..)) => return make_err(MveConcatInvalidReason::CStrLit), - Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => { - return make_err(MveConcatInvalidReason::ByteStrLit); - } - Ok(ast::LitKind::Err(_guarantee)) => { - // REVIEW: a diagnostic was already emitted, should we just break? - return make_err(MveConcatInvalidReason::InvalidLiteral); - } - Err(err) => return Err(create_lit_error(psess, err, lit, token.span)), - }; - - if !s.chars().all(|ch| is_id_continue(ch)) { - // Check that all characters are valid in the middle of an identifier. This doesn't - // guarantee that the final identifier is valid (we still need to check it later), - // but it allows us to catch errors with specific arguments before expansion time; - // for example, string literal "foo.bar" gets flagged before the macro is invoked. - return make_err(MveConcatInvalidReason::InvalidIdent); - } - - MetaVarExprConcatElem::Ident(s) - } else if let Some((elem, is_raw)) = token.ident() { - if is_raw == IdentIsRaw::Yes { - return make_err(MveConcatInvalidReason::RawIdentifier); - } - MetaVarExprConcatElem::Ident(elem.as_str().to_string()) } else { - return make_err(MveConcatInvalidReason::UnsupportedInput); + MetaVarExprConcatElem::Ident(parse_tok_for_concat(psess, token)?) }; result.push(element); @@ -327,6 +284,68 @@ fn parse_depth<'psess>( } } +/// Validate that a token can be concatenated as an identifier, then stringify it. +pub(super) fn parse_tok_for_concat<'psess>( + psess: &'psess ParseSess, + token: Token, +) -> PResult<'psess, String> { + let dcx = psess.dcx(); + let make_err = |reason| { + let err = errors::MveConcatInvalidTy { + span: token.span, + metavar_span: None, + reason, + valid: VALID_EXPR_CONCAT_TYPES, + }; + Err(dcx.create_err(err)) + }; + + let elem = if let TokenKind::Literal(lit) = token.kind { + // Preprocess with `from_token_lit` to handle unescaping, float / int literal suffix + // stripping. + // + // For consistent user experience, please keep this in sync with the handling of + // literals in `rustc_builtin_macros::concat`! + let s = match ast::LitKind::from_token_lit(lit.clone()) { + Ok(ast::LitKind::Str(s, _)) => s.to_string(), + Ok(ast::LitKind::Float(..)) => { + return make_err(MveConcatInvalidTyReason::FloatLit); + } + Ok(ast::LitKind::Char(c)) => c.to_string(), + Ok(ast::LitKind::Int(i, _)) => i.to_string(), + Ok(ast::LitKind::Bool(b)) => b.to_string(), + Ok(ast::LitKind::CStr(..)) => return make_err(MveConcatInvalidTyReason::CStrLit), + Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => { + return make_err(MveConcatInvalidTyReason::ByteStrLit); + } + Ok(ast::LitKind::Err(_guarantee)) => { + // REVIEW: a diagnostic was already emitted, should we just break? + return make_err(MveConcatInvalidTyReason::InvalidLiteral); + } + Err(err) => return Err(create_lit_error(psess, err, lit, token.span)), + }; + + if !s.chars().all(|ch| is_id_continue(ch)) { + // Check that all characters are valid in the middle of an identifier. This doesn't + // guarantee that the final identifier is valid (we still need to check it later), + // but it allows us to catch errors with specific arguments before expansion time; + // for example, string literal "foo.bar" gets flagged before the macro is invoked. + return make_err(MveConcatInvalidTyReason::InvalidIdent); + } + + s + } else if let Some((elem, is_raw)) = token.ident() { + if is_raw == IdentIsRaw::Yes { + return make_err(MveConcatInvalidTyReason::RawIdentifier); + } + elem.as_str().to_string() + } else { + return make_err(MveConcatInvalidTyReason::UnsupportedInput); + }; + + Ok(elem) +} + /// Tries to parse a generic ident. If this fails, create a missing identifier diagnostic with /// `context` explanation. fn parse_ident<'psess>( diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index a9907715d0342..02688a4d8eb93 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -16,15 +16,18 @@ use rustc_span::{ }; use smallvec::{SmallVec, smallvec}; +use super::metavar_expr::parse_tok_for_concat; use crate::errors::{ - CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, + self, CountRepetitionMisplaced, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoSyntaxVarsExprRepeat, VarStillRepeating, }; use crate::mbe::macro_parser::NamedMatch; use crate::mbe::macro_parser::NamedMatch::*; -use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR}; +use crate::mbe::metavar_expr::{MetaVarExprConcatElem, VALID_EXPR_CONCAT_TYPES}; use crate::mbe::{self, KleeneOp, MetaVarExpr}; +const VALID_METAVAR_CONCAT_TYPES: &str = "`ident`, `literal`, and `tt`"; + /// Context needed to perform transcription of metavariable expressions. struct TranscrCtx<'psess, 'itp> { psess: &'psess ParseSess, @@ -905,48 +908,37 @@ fn out_of_bounds_err<'a>(dcx: DiagCtxtHandle<'a>, max: usize, span: Span, ty: &s } /// Extracts an metavariable symbol that can be an identifier, a token tree or a literal. -// TODO: use the same logic as for metavar_expr fn extract_symbol_from_pnr<'tx>( tscx: &mut TranscrCtx<'tx, '_>, pnr: &ParseNtResult, - span_err: Span, -) -> PResult<'tx, Symbol> { - let dcx = tscx.psess.dcx(); - match pnr { - ParseNtResult::Ident(nt_ident, is_raw) => { - if let IdentIsRaw::Yes = is_raw { - Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) - } else { - Ok(nt_ident.name) - } - } - ParseNtResult::Tt(TokenTree::Token( - Token { kind: TokenKind::Ident(symbol, is_raw), .. }, - _, - )) => { - if let IdentIsRaw::Yes = is_raw { - Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) - } else { - Ok(*symbol) - } + metavar_span: Span, +) -> PResult<'tx, String> { + // Reconstruct a `Token` so we can share logic with expression parsing. + let token = match pnr { + ParseNtResult::Tt(TokenTree::Token(tok, _)) => *tok, + ParseNtResult::Ident(Ident { name, span }, ident_is_raw) => { + Token { kind: TokenKind::Ident(*name, *ident_is_raw), span: *span } + } + + ParseNtResult::Literal(l) if let ExprKind::Lit(lit) = l.kind => { + Token { kind: TokenKind::Literal(lit), span: l.span } + } + _ => { + let err = errors::MveConcatInvalidTy { + span: pnr.span(), + metavar_span: Some(metavar_span), + reason: errors::MveConcatInvalidTyReason::InvalidMetavarTy, + valid: VALID_METAVAR_CONCAT_TYPES, + }; + return Err(tscx.psess.dcx().create_err(err)); } - ParseNtResult::Tt(TokenTree::Token( - Token { - kind: TokenKind::Literal(Lit { kind: LitKind::Str, symbol, suffix: None }), - .. - }, - _, - )) => Ok(*symbol), - ParseNtResult::Literal(expr) - if let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind => - { - Ok(*symbol) - } - _ => Err(dcx - .struct_err( - "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`", - ) - .with_note("currently only string literals are supported") - .with_span(span_err)), - } + }; + + parse_tok_for_concat(tscx.psess, token) + // _ => Err(dcx + // .struct_err( + // "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`", + // ) + // .with_note("currently only string literals are supported") + // .with_span(span_err)), } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b2e902513672d..3556b9b0a99e9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1657,3 +1657,24 @@ pub enum ParseNtResult { Path(P), Vis(P), } + +impl ParseNtResult { + #[inline] + pub fn span(&self) -> Span { + match self { + ParseNtResult::Tt(token_tree) => token_tree.span(), + ParseNtResult::Ident(ident, ..) => ident.span, + ParseNtResult::Lifetime(ident, ..) => ident.span, + ParseNtResult::Item(item) => item.span, + ParseNtResult::Block(block) => block.span, + ParseNtResult::Stmt(stmt) => stmt.span, + ParseNtResult::Pat(pat, ..) => pat.span, + ParseNtResult::Expr(expr, ..) => expr.span, + ParseNtResult::Literal(expr) => expr.span, + ParseNtResult::Ty(ty) => ty.span, + ParseNtResult::Meta(attr_item) => attr_item.span(), + ParseNtResult::Path(path) => path.span, + ParseNtResult::Vis(visibility) => visibility.span, + } + } +} diff --git a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs index 3612ef20b5e5c..aedf1038daa08 100644 --- a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs +++ b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.rs @@ -3,60 +3,60 @@ macro_rules! idents_01 { ($rhs:ident) => { let ${concat(abc, $rhs)}: () = (); - //~^ ERROR `${concat(..)}` currently does not support raw identifiers + //~^ ERROR invalid item within a `${concat(..)}` expression }; } macro_rules! idents_10 { ($lhs:ident) => { let ${concat($lhs, abc)}: () = (); - //~^ ERROR `${concat(..)}` currently does not support raw identifiers + //~^ ERROR invalid item within a `${concat(..)}` expression }; } macro_rules! idents_11 { ($lhs:ident, $rhs:ident) => { let ${concat($lhs, $rhs)}: () = (); - //~^ ERROR `${concat(..)}` currently does not support raw identifiers - //~| ERROR `${concat(..)}` currently does not support raw identifiers - //~| ERROR `${concat(..)}` currently does not support raw identifiers + //~^ ERROR invalid item within a `${concat(..)}` expression + //~| ERROR invalid item within a `${concat(..)}` expression + //~| ERROR invalid item within a `${concat(..)}` expression }; } macro_rules! no_params { () => { let ${concat(r#abc, abc)}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression //~| ERROR expected pattern, found `$` let ${concat(abc, r#abc)}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat(r#abc, r#abc)}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression }; } macro_rules! tts_01 { ($rhs:tt) => { let ${concat(abc, $rhs)}: () = (); - //~^ ERROR `${concat(..)}` currently does not support raw identifiers + //~^ ERROR invalid item within a `${concat(..)}` expression }; } macro_rules! tts_10 { ($lhs:tt) => { let ${concat($lhs, abc)}: () = (); - //~^ ERROR `${concat(..)}` currently does not support raw identifiers + //~^ ERROR invalid item within a `${concat(..)}` expression }; } macro_rules! tts_11 { ($lhs:tt, $rhs:tt) => { let ${concat($lhs, $rhs)}: () = (); - //~^ ERROR `${concat(..)}` currently does not support raw identifiers - //~| ERROR `${concat(..)}` currently does not support raw identifiers - //~| ERROR `${concat(..)}` currently does not support raw identifiers + //~^ ERROR invalid item within a `${concat(..)}` expression + //~| ERROR invalid item within a `${concat(..)}` expression + //~| ERROR invalid item within a `${concat(..)}` expression }; } diff --git a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr index 3d01e1325192b..f3211bf658b03 100644 --- a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr +++ b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr @@ -1,105 +1,106 @@ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-raw-identifiers.rs:28:22 | LL | let ${concat(r#abc, abc)}: () = (); | ^^^^^ | = note: raw identifiers cannot be concatenated -help: expanding this `concat(...)` expression - --> $DIR/concat-raw-identifiers.rs:28:15 - | -LL | let ${concat(r#abc, abc)}: () = (); - | ^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-raw-identifiers.rs:32:27 | LL | let ${concat(abc, r#abc)}: () = (); | ^^^^^ | = note: raw identifiers cannot be concatenated -help: expanding this `concat(...)` expression - --> $DIR/concat-raw-identifiers.rs:32:15 - | -LL | let ${concat(abc, r#abc)}: () = (); - | ^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-raw-identifiers.rs:35:22 | LL | let ${concat(r#abc, r#abc)}: () = (); | ^^^^^ | = note: raw identifiers cannot be concatenated -help: expanding this `concat(...)` expression - --> $DIR/concat-raw-identifiers.rs:35:15 - | -LL | let ${concat(r#abc, r#abc)}: () = (); - | ^^^^^^ -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:5:28 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:64:16 | -LL | let ${concat(abc, $rhs)}: () = (); - | ^^^ +LL | idents_01!(r#_c); + | ^^^^ + | + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:12:23 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:66:16 + | +LL | idents_10!(r#_c); + | ^^^^ | -LL | let ${concat($lhs, abc)}: () = (); - | ^^^ + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:19:23 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:68:16 + | +LL | idents_11!(r#_c, d); + | ^^^^ | -LL | let ${concat($lhs, $rhs)}: () = (); - | ^^^ + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:19:29 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:69:20 | -LL | let ${concat($lhs, $rhs)}: () = (); - | ^^^ +LL | idents_11!(_e, r#f); + | ^^^ + | + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:19:23 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:70:16 | -LL | let ${concat($lhs, $rhs)}: () = (); - | ^^^ +LL | idents_11!(r#_g, r#h); + | ^^^^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:42:28 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:72:13 | -LL | let ${concat(abc, $rhs)}: () = (); - | ^^^ +LL | tts_01!(r#_c); + | ^^^^ + | + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:49:23 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:74:13 + | +LL | tts_10!(r#_c); + | ^^^^ | -LL | let ${concat($lhs, abc)}: () = (); - | ^^^ + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:56:23 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:76:13 + | +LL | tts_11!(r#_c, d); + | ^^^^ | -LL | let ${concat($lhs, $rhs)}: () = (); - | ^^^ + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:56:29 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:77:17 | -LL | let ${concat($lhs, $rhs)}: () = (); - | ^^^ +LL | tts_11!(_e, r#f); + | ^^^ + | + = note: raw identifiers cannot be concatenated -error: `${concat(..)}` currently does not support raw identifiers - --> $DIR/concat-raw-identifiers.rs:56:23 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-raw-identifiers.rs:78:13 | -LL | let ${concat($lhs, $rhs)}: () = (); - | ^^^ +LL | tts_11!(r#_g, r#h); + | ^^^^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: raw identifiers cannot be concatenated error: expected pattern, found `$` --> $DIR/concat-raw-identifiers.rs:28:13 diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.rs b/tests/ui/macros/metavar-expressions/concat-trace-errors.rs index 75f01266eb4d2..8636b0b1edf10 100644 --- a/tests/ui/macros/metavar-expressions/concat-trace-errors.rs +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.rs @@ -7,11 +7,11 @@ macro_rules! pre_expansion { ($a:ident) => { ${concat("hi", " bye ")}; - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression ${concat("hi", "-", "bye")}; - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression ${concat($a, "-")}; - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression } } diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr index 45ed5204dd24e..e16d8e9e1b0ca 100644 --- a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr @@ -1,63 +1,32 @@ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-trace-errors.rs:9:24 | LL | ${concat("hi", " bye ")}; | ^^^^^^^ - | - = note: this literal produced an invalid identifier -help: expanding this `concat(...)` expression - --> $DIR/concat-trace-errors.rs:9:11 - | -LL | ${concat("hi", " bye ")}; - | ^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-trace-errors.rs:11:24 | LL | ${concat("hi", "-", "bye")}; | ^^^ - | - = note: this literal produced an invalid identifier -help: expanding this `concat(...)` expression - --> $DIR/concat-trace-errors.rs:11:11 - | -LL | ${concat("hi", "-", "bye")}; - | ^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-trace-errors.rs:13:22 | LL | ${concat($a, "-")}; | ^^^ - | - = note: this literal produced an invalid identifier -help: expanding this `concat(...)` expression - --> $DIR/concat-trace-errors.rs:13:11 - | -LL | ${concat($a, "-")}; - | ^^^^^^ -error: `${concat(..)}` is not generating a valid identifier - --> $DIR/concat-trace-errors.rs:20:24 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-trace-errors.rs:25:17 | -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:29:24 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-trace-errors.rs:34:31 | -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 5 previous errors diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs index 68857d3c33c2c..7dfa76e4f9bbf 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs @@ -22,7 +22,7 @@ macro_rules! syntax_errors { //~^ ERROR `concat` must have at least two elements ${concat($ex, aaaa)} - //~^ ERROR metavariables of `${concat(..)}` must be of type + //~^ ERROR invalid item within a `${concat(..)}` expression ${concat($ex, aaaa 123)} //~^ ERROR expected comma @@ -54,7 +54,7 @@ macro_rules! starting_valid_unicode { macro_rules! starting_invalid_unicode { ($ident:ident) => {{ let ${concat("\u{00BD}", $ident)}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression //~| ERROR expected pattern }}; } @@ -74,7 +74,7 @@ macro_rules! ending_valid_unicode { macro_rules! ending_invalid_unicode { ($ident:ident) => {{ let ${concat($ident, "\u{00BD}")}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression //~| ERROR expected pattern }}; } @@ -89,27 +89,27 @@ macro_rules! empty { macro_rules! unsupported_literals { ($ident:ident) => {{ let ${concat(_a, 1.5)}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression //~| ERROR expected pattern let ${concat(_a, c"hi")}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat(_a, b"hi")}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat(_a, b'b')}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat(_a, b'b')}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat($ident, 1.5)}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat($ident, c"hi")}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat($ident, b"hi")}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat($ident, b'b')}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression let ${concat($ident, b'b')}: () = (); - //~^ ERROR invalid item within a `${concat(...)}` expression + //~^ ERROR invalid item within a `${concat(..)}` expression }}; } diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr index ce16f2bef8d06..93615fa90eb0e 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr @@ -34,179 +34,119 @@ error: expected comma LL | ${concat($ex, aaaa 123)} | ^^^^^^^^^^^^^^^^^^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:56:22 | LL | let ${concat("\u{00BD}", $ident)}: () = (); | ^^^^^^^^^^ - | - = note: this literal produced an invalid identifier -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:56:15 - | -LL | let ${concat("\u{00BD}", $ident)}: () = (); - | ^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:76:30 | LL | let ${concat($ident, "\u{00BD}")}: () = (); | ^^^^^^^^^^ - | - = note: this literal produced an invalid identifier -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:76:15 - | -LL | let ${concat($ident, "\u{00BD}")}: () = (); - | ^^^^^^ -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:91:26 | LL | let ${concat(_a, 1.5)}: () = (); | ^^^ | = note: float literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:91:15 - | -LL | let ${concat(_a, 1.5)}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:94:26 | LL | let ${concat(_a, c"hi")}: () = (); | ^^^^^ | = note: C string literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:94:15 - | -LL | let ${concat(_a, c"hi")}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:96:26 | LL | let ${concat(_a, b"hi")}: () = (); | ^^^^^ | = note: byte literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:96:15 - | -LL | let ${concat(_a, b"hi")}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:98:26 | LL | let ${concat(_a, b'b')}: () = (); | ^^^^ | = note: byte literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:98:15 - | -LL | let ${concat(_a, b'b')}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:100:26 | LL | let ${concat(_a, b'b')}: () = (); | ^^^^ | = note: byte literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:100:15 - | -LL | let ${concat(_a, b'b')}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:103:30 | LL | let ${concat($ident, 1.5)}: () = (); | ^^^ | = note: float literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:103:15 - | -LL | let ${concat($ident, 1.5)}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:105:30 | LL | let ${concat($ident, c"hi")}: () = (); | ^^^^^ | = note: C string literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:105:15 - | -LL | let ${concat($ident, c"hi")}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:107:30 | LL | let ${concat($ident, b"hi")}: () = (); | ^^^^^ | = note: byte literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:107:15 - | -LL | let ${concat($ident, b"hi")}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:109:30 | LL | let ${concat($ident, b'b')}: () = (); | ^^^^ | = note: byte literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:109:15 - | -LL | let ${concat($ident, b'b')}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: invalid item within a `${concat(...)}` expression +error: invalid item within a `${concat(..)}` expression --> $DIR/concat-usage-errors.rs:111:30 | LL | let ${concat($ident, b'b')}: () = (); | ^^^^ | = note: byte literals cannot be concatenated - = help: `concat` can join metavariables, identifiers, string literals, and integer literals -help: expanding this `concat(...)` expression - --> $DIR/concat-usage-errors.rs:111:15 - | -LL | let ${concat($ident, b'b')}: () = (); - | ^^^^^^ + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:24:19 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:150:20 | LL | ${concat($ex, aaaa)} - | ^^ + | -- expanding this metavariable +... +LL | syntax_errors!(1); + | ^ | - = note: currently only string literals are supported + = note: expanding something + = note: `${concat(..)}` can join metavariables of type `ident`, `literal`, and `tt` error: variable `foo` is not recognized in meta-variable expression --> $DIR/concat-usage-errors.rs:36:30 @@ -269,152 +209,117 @@ LL | empty!(); | = 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 - --> $DIR/concat-usage-errors.rs:118:16 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:165:25 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | bad_literal_string!("\u{00BD}"); - | ------------------------------- in this macro invocation - | - = 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 - --> $DIR/concat-usage-errors.rs:118:16 - | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | bad_literal_string!("\x41"); - | --------------------------- in this macro invocation - | - = 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 - --> $DIR/concat-usage-errors.rs:118:16 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:167:25 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | bad_literal_string!("🤷"); - | ------------------------- in this macro invocation - | - = 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 - --> $DIR/concat-usage-errors.rs:118:16 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:168:25 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | bad_literal_string!("d[-_-]b"); - | ------------------------------ in this macro invocation - | - = 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 - --> $DIR/concat-usage-errors.rs:118:16 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:170:25 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | bad_literal_string!("-1"); - | ------------------------- in this macro invocation - | - = 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 - --> $DIR/concat-usage-errors.rs:118:16 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:171:25 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | bad_literal_string!("1.0"); - | -------------------------- in this macro invocation - | - = 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 - --> $DIR/concat-usage-errors.rs:118:16 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:172:25 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... LL | bad_literal_string!("'1'"); - | -------------------------- in this macro invocation - | - = 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` - --> $DIR/concat-usage-errors.rs:131:31 - | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^ - | - = note: currently only string literals are supported + | ^^^^^ -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:131:31 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:175:29 | LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^ + | ------- expanding this metavariable +... +LL | bad_literal_non_string!(-1); + | ^^ | - = note: currently only string literals are supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: expanding something + = note: `${concat(..)}` can join metavariables of type `ident`, `literal`, and `tt` -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:131:31 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:176:29 | -LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^ +LL | bad_literal_non_string!(1.0); + | ^^^ | - = note: currently only string literals are supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: float literals cannot be concatenated + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:131:31 +error[E0428]: the name `_foo1` is defined multiple times + --> $DIR/concat-usage-errors.rs:131:9 | LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^ + | ^^^^^^^ + | | + | `_foo1` redefined here + | previous definition of the value `_foo1` here +... +LL | bad_literal_non_string!(1); + | -------------------------- in this macro invocation | - = note: currently only string literals are supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: `_foo1` must be defined only once in the value namespace of this block + = note: this error originates in the macro `bad_literal_non_string` (in Nightly builds, run with -Z macro-backtrace for more info) -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:131:31 +error[E0428]: the name `_foo1` is defined multiple times + --> $DIR/concat-usage-errors.rs:142:9 | LL | const ${concat(_foo, $literal)}: () = (); - | ^^^^^^^ - | - = note: currently only string literals are supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:142:31 - | + | ------- previous definition of the value `_foo1` here +... LL | const ${concat(_foo, $tt)}: () = (); - | ^^ + | ^^^^^^^ `_foo1` redefined here +... +LL | bad_tt_literal!(1); + | ------------------ in this macro invocation | - = note: currently only string literals are supported + = note: `_foo1` must be defined only once in the value namespace of this block + = note: this error originates in the macro `bad_tt_literal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:142:31 +error: invalid item within a `${concat(..)}` expression + --> $DIR/concat-usage-errors.rs:181:21 | -LL | const ${concat(_foo, $tt)}: () = (); - | ^^ +LL | bad_tt_literal!(1.0); + | ^^^ | - = note: currently only string literals are supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: float literals cannot be concatenated + = note: `concat` can join metavariables, identifiers, string literals, and integer literals -error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` - --> $DIR/concat-usage-errors.rs:142:31 +error[E0428]: the name `_foo1` is defined multiple times + --> $DIR/concat-usage-errors.rs:142:9 | +LL | const ${concat(_foo, $literal)}: () = (); + | ------- previous definition of the value `_foo1` here +... LL | const ${concat(_foo, $tt)}: () = (); - | ^^ + | ^^^^^^^ `_foo1` redefined here +... +LL | bad_tt_literal!('1'); + | -------------------- in this macro invocation | - = note: currently only string literals are supported - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: `_foo1` must be defined only once in the value namespace of this block + = note: this error originates in the macro `bad_tt_literal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 40 previous errors +error: aborting due to 37 previous errors +For more information about this error, try `rustc --explain E0428`.