rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.79k stars 12.66k forks source link

Bad macro usage error message does not include correct error location #31022

Open SimonSapin opened 8 years ago

SimonSapin commented 8 years ago

Consider this reduced test case:

macro_rules! match_ignore_ascii_case {
    (@inner $value:expr) => { () };
    ( $($rest:tt)* ) => { match_ignore_ascii_case!(@inner $($rest)*) };
}

fn main() {
    // This is fine
    match_ignore_ascii_case!(1);

    // This causes an error as it doesn’t match the expected syntax
    // but the error message does not the location of the actual error.
    match_ignore_ascii_case!(2 => 3);
}

The @inner indirection exists because the non-reduced macro is recursive:

This fails to compile (as it should) but the error message does not include the real location of the error, which is line 12. It can be hard to track down in a large crate with many users of the macro.

a.rs:3:52: 3:53 error: unexpected token: `@`
a.rs:3     ( $($rest:tt)* ) => { match_ignore_ascii_case!(@inner $($rest)*) };

The error message looks even worse when the macro is used (with incorrect syntax) from another crate

<cssparser macros>:12:1: 12:2 error: unexpected token: `@`
<cssparser macros>:12 @ inner $ value , ( $ ( $ rest ) * ) -> (
durka commented 8 years ago

When the expanded code contains a non-macro-related error (say, a type mismatch), it at least shows a macro expansion backtrace. It's very hard to read, but gives spans at least. I guess that would be a start.

durka commented 8 years ago

The trouble is you get the same error if you screw up writing the macro, e.g. misspell @inner or order something backwards in one of the arms. It isn't the caller's fault for sure.

SimonSapin commented 8 years ago

Yes, I don’t have an example at hand to copy/past but I see the kind of error message you mean. It may be the caller’s fault even if it isn’t necessarily. A macro expansion backtrace would be useful here.

estebank commented 7 years ago

Current output:

error: recursion limit reached while expanding the macro `match_ignore_ascii_case`
  --> src/main.rs:3:27
   |
3  |     ( $($rest:tt)* ) => { match_ignore_ascii_case!(@inner $($rest)*) };
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
12 |     match_ignore_ascii_case!(2 => 3);
   |     --------------------------------- in this macro invocation
   |
   = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
estebank commented 5 years ago

Triage: no change.

estebank commented 2 years ago

Triage: no change.

estebank commented 1 year ago

Triage: no change.