d54a8ac8e2
Improve the error message when forwarding a matched fragment to another macro Adds a link to [Forwarding a matched fragment](https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment) section of the Rust Reference, and suggests a possible fix (using `:tt` instead in the macro definition). Also removes typos from the original message, it should be `:lifetime` instead of `$lifetime`. ## Motivation When trying to write a macro which uses a literal in the matcher from the outer macro, like the following one, using a fragment specified that isn't one of `:ident`, `:lifetime`, or `:tt` currently results in a hard to understand message. ```rs macro_rules! make_t_for_all_tokens { ($($name:literal as $variant:expr,)*) => { macro_rules! t { $( ($name) => { $variant }; )* } }; } make_t_for_all_tokens! { "fn" as Token::Fn, "return" as Token::Return, "let" as Token::Let, } // This creates // // macro_rules! t { // ("fn") => { // Token::Fn // }; // ("return") => { // Token::Return // }; // ("let") => { // Token::Let // }; // } t!["fn"]; ``` ### Before ``` error: no rules expected the token `"fn"` --> src/main.rs:103:10 | 32 | macro_rules! t { | -------------- when calling this macro ... 103 | t!["fn"]; | ^^^^ no rules expected this token in macro call | note: while trying to match `"fn"` --> src/main.rs:34:6 | 34 | ($name) => { | ^^^^^ ... 58 | / make_t_for_all_tokens! { 59 | | "fn" as Token::Fn, 60 | | "return" as Token::Return, 61 | | "let" as Token::Let, 62 | | } | |_- in this macro invocation = note: captured metavariables except for `$tt`, `$ident` and `$lifetime` cannot be compared to other tokens = note: this error originates in the macro `make_t_for_all_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) ``` ### After ``` error: no rules expected the token `"fn"` --> src/main.rs:103:10 | 32 | macro_rules! t { | -------------- when calling this macro ... 103 | t!["fn"]; | ^^^^ no rules expected this token in macro call | note: while trying to match `"fn"` --> src/main.rs:34:6 | 34 | ($name) => { | ^^^^^ ... 58 | / make_t_for_all_tokens! { 59 | | "fn" as Token::Fn, 60 | | "return" as Token::Return, 61 | | "let" as Token::Let, 62 | | } | |_- in this macro invocation = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens = note: see https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment for more information = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `make_t_for_all_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) ``` ## Unresolved questions - Preferrably the suggestion should be attached to the `$name:literal` part of the outer macro, instead of being in the notes section at the end. But I'm not familiar with how the compiler works at all, and I have no idea how to approach this kind of solution. - `@Nilstrieb` raised a question that the suggestion of adding `:tt` isn't accurate when there's more than `tt` being matched, for example when the input is an `item`. |
||
---|---|---|
.. | ||
src | ||
Cargo.toml | ||
messages.ftl |