Skip to content

Diagnostic improvement of macros #97108

Open

Description

@frank-king

Given the following code:

macro_rules! m {
    () => {};
    ( $name:ident; ($tt:tt)* ) => {
        m!{ @ $name }
        m!{ $($tt)* }
    };
    (@ $name:ident) => { struct $name; };
}

m! {
    A;
    B;
}

m! { C; }

Playground.

The current output is:

error: no rules expected the token `B`
  --> src/lib.rs:12:5
   |
1  | macro_rules! m {
   | -------------- when calling this macro
...
12 |     B;
   |     ^ no rules expected this token in macro call

error: unexpected end of macro invocation
  --> src/lib.rs:15:8
   |
1  | macro_rules! m {
   | -------------- when calling this macro
...
15 | m! { C; }
   |        ^ missing tokens in macro arguments

error: could not compile `playground` due to 2 previous errors

Ideally the output should look like:

error: no rules expected the token `B`
  --> src/lib.rs:12:5
   |
1  | macro_rules! m {
   | -------------- when calling this macro
...
12 |     B;
   |     ^ no rules expected this token in macro call

note: expected `(` but found `B`.
  --> src/lib.rs:3:20
   |
3  |    ( $name:ident; ($tt:tt)* ) => {
   |                   ^ expected token `(`.
...
12 |     B;
   |     ^ But found `B`.
help: do you mean this?
  --> src/lib.rs:3:20
   |
3  |    ( $name:ident; ($tt:tt)* ) => {
   +                   $($tt:tt)* ) => {
   |                   ^ Add `$` here.


error: unexpected end of macro invocation
  --> src/lib.rs:15:8
   |
1  | macro_rules! m {
   | -------------- when calling this macro
...
15 | m! { C; }
   |        ^ missing tokens in macro arguments

note: missing `(` but found nothing.
  --> src/lib.rs:3:20
   |
3  |    ( $name:ident; ($tt:tt)* ) => {
   |                   ^ expected token `(`.
...
15 | m! { C; }
   |        ^ missing tokens in macro arguments

help: do you mean this?
  --> src/lib.rs:3:20
   |
3  |    ( $name:ident; ($tt:tt)* ) => {
   +                   $($tt:tt)* ) => {
   |                   ^ Add `$` here.
error: could not compile `playground` due to 2 previous errors

The expect error message is written by hand.

The original problem comes from here. It has wasted me a couple of hours to find out the error (a missing $ in the macro rules), so I hope the diagnostic message can be improved, to avoid another one being stuck by this.

If the compiler can not report that I missed a $, I hope at least it can report that the next expected token ( doesn't match the actual arguments.

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on May 17, 2022
  2. est31 commented on May 17, 2022

    @est31
    Member

    Right now, macro_rules is a macro itself, and also reuses the same logic for parsing macro declarations that normal macro_rules matchers use. That's probably why the errors are so bad. One could think about turning macro_rules into something "properly" parsed, then it can give better errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions