A case for a new output format for the compiler?

The rust compiler currently supports three output formats:

  • json (self explanatory)
  • human
warning: unused variable: `a`
 --> src/main.rs:2:9
  |
2 |     let a = 1;
  |         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: `foo` (bin "foo") generated 1 warning (run `cargo fix --bin "foo"` to apply 1 suggestion)
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
  • short
   Compiling foo v0.1.0 (/tmp/foo)
src/main.rs:2:9: warning: unused variable: `a`
warning: `foo` (bin "foo") generated 1 warning (run `cargo fix --bin "foo"` to apply 1 suggestion)
    Finished dev [unoptimized + debuginfo] target(s) in 0.17s

Now, compare with the output of what is also commonly used when building rust code:

  • gcc
foo.c: In function ‘foo’:
foo.c:2:1: warning: control reaches end of non-void function [-Wreturn-type]
    2 | }
      | ^
  • clang
foo.c:2:1: warning: non-void function does not return a value [-Wreturn-type]
    2 | }
      | ^
1 warning generated.

Do you notice the difference? The warning message is on the same line as the file name. This is extremely convenient to extract warnings/errors from large build logs.

To some extent, that's what the short output does, but it's also too short, because it skips everything else, and you have to do another build to get the full message.

I, for one, would like a format that shows the message like the short format, but with the full context like the human format. So here's my question: should this be a new format, or would a change to the human format be considered?

2 Likes

Come to think of it, it would also be nice if the short version had the unused_variables in it too (and likewise for the hypothetical new format)

2 Likes

Am I correct in thinking such extraction is an automated process? Isn't the JSON output format best for that?

3 Likes

Am I correct in thinking such extraction is an automated process? Isn't the JSON output format best for that?

The extraction is an automated process, but the same logs are also for human consumption. I guess a wrapper that takes the json output and munges it would work, but then the nice coloring is lost (the json doesn't contain it) for the cases where you do want the colors. Rebuilding the original output from the json with color is certainly possible, but it's also a lot of work.

1 Like

Cargo exclusively uses rustc's json output for all of its processing, including the colored message you see. Granted, I don't remember under what conditions cargo will report back up the colored messages, if at all.

I'd rather not have to reimplement what cargo does to display colors. (and now that you mention that, I'm rather confused as to why cargo doesn't cache the json messages rather than the formatted output, ultimately leading to Message caching does not allow switching --message-format between short and human · Issue #9003 · rust-lang/cargo · GitHub)

Cargo uses --error-format=json --json=diagnostic-rendered-ansi to get colors with the json error message format.

3 Likes

But cargo build --message-format=json doesn't show it, and --json=anything is not a supported option.

1 Like

I think adding an equivalent option to cargo would be the best course of action then.

1 Like

GCC was started in the 80s, when there was no standard tooling-friendly output format besides "print one item per line in a sorta-stable format, parse it with grep and hope for the best". Clang copied it due to compatibility reasons. I don't see a good reason to represent this bug-prone approach in modern tooling. Json output is already intended to be easily and unambiguously parseable. If it's missing some information, that's a good reason to extend its structured output, rather than invent yet another unstructured one.

By the way, not every terminal renders colours, so it would be nice to have an environment-portable encoding of colours anyway.

11 Likes