Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useless errors with macro in a separate crate #39413

Closed
durka opened this issue Jan 30, 2017 · 15 comments · Fixed by #45545
Closed

useless errors with macro in a separate crate #39413

durka opened this issue Jan 30, 2017 · 15 comments · Fixed by #45545
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@durka
Copy link
Contributor

durka commented Jan 30, 2017

TL;DR: I'm annoyed about note: this error originates in a macro outside of the current crate and want a way to turn it off and get back the error backtrace that tells me where the problem is.

I separated some of my utility code and macros into a utils crate for faster compile times. In this error, I have a macro in there rpc!, which invokes another macro, guilty!. This requires the crate that invokes rpc! to also import the crate that defines guilty!, but I forgot to do that. However, the error message gives me no way to find that out because it doesn't show where the error actually occurs within the rpc! macro:

error: macro undefined: 'guilty!'
   --> crates/back/flow/src/lib.rs:374:17
    |
374 |                 assert!(rpc!(tx, CmdFrom::Start, service.clone(), data.clone()).unwrap());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this error originates in a macro outside of the current crate

In this case I wrote all the crates in question. But even if I didn't, and I were going to submit a bug to the author of rpc!, there's no useful information in this error message. Can there be a way to get back the error information, either by a compiler switch or using cargo's workspace feature or something?

cc @jonathandturner

@Arnavion
Copy link

I'm not in a position to try atm, but does

#![feature(trace_macros)]

trace_macros!(true);

help?

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 31, 2017
@durka
Copy link
Contributor Author

durka commented Feb 7, 2017

@Arnavion it doesn't help because you just see the expansion steps up until it looks at the body of rpc!, at which point it reports the undefined macro. trace_macros doesn't give source location information, anyway.

@durka
Copy link
Contributor Author

durka commented Feb 13, 2017

This issue came up again today with a different macro crate and I'm really at a loss as to how I can possibly debug. The removal of this information, with no way to get it back, is a real low blow to macro authors.

@sophiajt
Copy link
Contributor

The long-term hope here is to have macro debuggers. Since macros are still rapidly changing, I suspect it may take a little while to get to that point.

The macro backtrace is still available from the compiler, though I believe it's currently most readily available in the JSON output. Definitely not a perfect solution.

Definitely no ill-will towards macro authors.

@durka
Copy link
Contributor Author

durka commented Feb 13, 2017

I share that optimism towards a future macro-expanding RLS (or something), and I know the team didn't mean to cause any trouble, but I maintain it was at least unwise to remove the backtraces before there is any other macro debugging facility available. Would a PR be considered to add a -Z all-macros-are-local?

@sophiajt
Copy link
Contributor

I'd definitely consider it. cc @nikomatsakis and @nrc in case they have thoughts.

@nrc
Copy link
Member

nrc commented Feb 14, 2017

I would be happy to have a flag which showed macro errors in upstream crates. (I'd call it show-dep-macro-errors or something like that).

@nikomatsakis
Copy link
Contributor

@durka I'd be ok with a flag. It seems like we have a collection of "crappy but useful tools for helping macro authors" (e.g., the Rust pretty printer -- maybe a few others?). I wonder if it worth trying to expose them in some way besides random -Z flags? Would we even consider stabilizing them (if not their output)?

@nikomatsakis
Copy link
Contributor

@durka I'd probably call it -Z macro-backtrace or something though.

@jseyfried jseyfried self-assigned this Feb 18, 2017
@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@abonander
Copy link
Contributor

This error isn't helpful when trying to debug macros in examples, either. 😒

@Mark-Simulacrum Mark-Simulacrum added the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Jun 13, 2017
@durka
Copy link
Contributor Author

durka commented Jul 19, 2017

Can anyone write up mentoring instructions on where to find this information in the compiler?

@durka
Copy link
Contributor Author

durka commented Jul 19, 2017

Anyone who doesn't think this is worthwhile is welcome to diagnose the warning in the attached gist. Relevant macro-expanded code is provided. https://gist.github.com/durka/c4a7adb095ac76209c6e7385bfd9e3ee

@nrc
Copy link
Member

nrc commented Jul 20, 2017

@durka this:

fn fix_multispan_in_std_macros(&mut self, span: &mut MultiSpan) -> bool {
is where we elide the macro backtrace, I think. I'd guess you could just check the flag in there somewhere. I don't know this code in detail though, sorry.

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 26, 2017
@fschutt
Copy link
Contributor

fschutt commented Oct 10, 2017

I personally wish I could just see what the code is that cargo outputs for one specific file.

If I use rustc -Z unstable-options --pretty=expanded errors.rs, I can't use any macros that are not defined in the current crate. I've tried cargo expand, it does nothing (i.e. on failure, it doesn't output the expanded file).

Like, just an option to take a my_macros.rs. I don't necessarily need a backtrace, just to write the expanded file (or the point up to which the macro could be expanded) to a .rs.expanded or stdout.

Currently, all I get is something like this:

error: no rules expected the token `TUPLE`
  --> src/errors.rs:3:1
   |
3  | / error_chain! {
4  | |     
5  | |     foreign_links {
6  | |         IoError(::std::io::Error);
...  |
28 | |     }
29 | | }
   | |_^
   |
   = note: this error originates in a macro outside of the current crate

error: aborting due to previous error

... which isn't particularly helpful.

@roblabla
Copy link
Contributor

Is there still no way to do this ? I'm currently toying around with relm (which heavily relies on proc macros), and the situation is very bad there :(.

bors added a commit that referenced this issue Nov 21, 2017
show macro backtrace with -Z flag

Fixes #39413 by adding a facility to restore the "old school" macro expansion backtraces (previously removed in 6186538).

The restored functionality is accessed through the flag `-Z external-macro-backtrace`. Errors showing the truncated backtraces will suggest this flag.

### Example

Code: <details>
`a/src/lib.rs`
```rust
#[macro_export]
macro_rules! a {
    () => { a!(@) };
    (@) => { a!(@@) };
    (@@) => {
        syntax error;
    }
}
```
`b/src/main.rs`
```rust
#[macro_use] extern crate a;

macro_rules! b {
    () => { b!(@) };
    (@) => { b!(@@) };
    (@@) => {
        syntax error;
    }
}

fn main() {
    a!();
    b!();
}
```
</details>

<br/><br/>
Running without env var (note: first error is from remote macro, second from local macro):

<details>

```
$ cargo +custom run
   Compiling b v0.1.0
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
  --> src/main.rs:12:5
   |
12 |     a!();
   |     ^^^^^
   |     |
   |     expected one of 8 possible tokens here
   |     unexpected token
   |
   = note: this error originates in a macro outside of the current crate (run with RUST_MACRO_BACKTRACE=1 for more info)

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
  --> src/main.rs:7:16
   |
7  |         syntax error;
   |               -^^^^^ unexpected token
   |               |
   |               expected one of 8 possible tokens here
...
13 |     b!();
   |     ----- in this macro invocation

error: aborting due to 2 previous errors

error: Could not compile `b`.

To learn more, run the command again with --verbose.
```
</details>
The output is the same as today, except for an addition to the note which aids discoverability of the new environment variable.

<br/><br/>
Running _with_ env var:
<details>

```
$ RUST_MACRO_BACKTRACE=1 cargo +custom run
   Compiling b v0.1.0
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
 --> <a macros>:1:72
  |
1 | (  ) => { a ! ( @ ) } ; ( @ ) => { a ! ( @ @ ) } ; ( @ @ ) => { syntax error ;
  |                                                                       -^^^^^ unexpected token
  |                                                                       |
  |                                                                       expected one of 8 possible tokens here
src/main.rs:12:5: 12:10 note: in this expansion of a! (defined in <a macros>)
<a macros>:1:11: 1:20 note: in this expansion of a! (defined in <a macros>)
<a macros>:1:36: 1:47 note: in this expansion of a! (defined in <a macros>)

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
 --> src/main.rs:7:16
  |
7 |         syntax error;
  |               -^^^^^ unexpected token
  |               |
  |               expected one of 8 possible tokens here
src/main.rs:12:5: 12:10 note: in this expansion of a! (defined in <a macros>)
<a macros>:1:11: 1:20 note: in this expansion of a! (defined in <a macros>)
<a macros>:1:36: 1:47 note: in this expansion of a! (defined in <a macros>)

error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error`
 --> src/main.rs:7:16
  |
7 |         syntax error;
  |               -^^^^^ unexpected token
  |               |
  |               expected one of 8 possible tokens here
src/main.rs:13:5: 13:10 note: in this expansion of b! (defined in src/main.rs)
src/main.rs:4:13: 4:18 note: in this expansion of b! (defined in src/main.rs)
src/main.rs:5:14: 5:20 note: in this expansion of b! (defined in src/main.rs)

error: aborting due to 2 previous errors

error: Could not compile `b`.

To learn more, run the command again with --verbose.
```
</details>

The output is hard to read, but better than nothing (and it's exactly what we used to have before the infamous `fix_multispans_in_std_macros`).

<br/><br/>
Wishlist:

- Save the actual source of macros in crate metadata, not just AST, so the output can be improved
    - Hopefully this would allow line numbers in the trace as well
- Show the actual macro invocations in the traces

r? @nrc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.