Rust: Error Message Overhaul

Created on 27 Apr 2016  路  53Comments  路  Source: rust-lang/rust

PR https://github.com/rust-lang/rust/pull/32756 began a gradual overhaul of our error message formatting. We would very much like feedback on error messages you think could use improvement, as well of course as any bugs or other problems with the new error formatting code. Please leave comments!

What follows is a list of known issues we plan to address. Likely many of these will be moved into distinct GitHub issues at some point.

Improvements to the overall error reporting mechanism:

  • [x] New unit testing mechanism that can test colors and precise appearance: #33000
  • [ ] Improve the treatment of tabs.
  • [ ] Subdiagnostics like note should not be colored green but rather just appear bold
  • [ ] Subdiagnostics like note should not use the --> indicator but rather >>>, and the underline should be -- and not ^^

    • basically, they do not have a primary span

  • [ ] Mandatory labels on primary spans?
  • [ ] Change from >>>> for secondary file names to something like ::: maybe?
  • [ ] When snippet labels are too long, potentially move them to a footnote of some kind

Specific error messages that need improvement:

  • [ ] Identify when you have the same span for multiple borrows in a loop and give a better message.
  • [ ] We special case closure captures due to unique loans, but we could give similar treatment to any loan coming through a capture.
  • [ ] Decide whether to thread the closure header span through the builder API convenience methods.
A-diagnostics

Most helpful comment

I think that for syntax highlighting, I'd prefer to just find keywords and highlight them in bold (something very minimal). We have to be very wary of drawing attention away.

All 53 comments

For anyone who want to play around with ideas related to the error formatting, you can use this.

cc @jonathandturner

Could you add the following?

  • [ ] Customization of error formatting.
  • [ ] Unicode switch.
  • [ ] Syntax highlighting.

@ticki

Customization of error formatting.

We'd talked some about maybe a "customization of error colors". What do you mean by error formatting?

Unicode switch.

Because we want errors to look and feel similar across platforms, the idea here is to pick a way to display the error that's friendly to even non-unicode environments (like default Windows). We can definitely revisit this one if modern Windows improvements, like Bash on Windows for example, open up the door to using more Unicode.

Syntax highlighting.

Oh right. Yeah, that could look good, depending on how we do it. Would be fun to experiment.

Syntax highlighting.

I worked on it a while ago for rustc --explain. I came to the conclusion that the "best" way to do it would be through rustdoc. It just needs to add an "ascii" (don't know if it's the correct translation) output format. But for that, we need to rework rustdoc source code in order to easily add new output formats.

Improve the treatment of tabs.

I'm not sure to understand the issue here. Aren't they translated as whitespaces?

@GuillaumeGomez the tabs issue is around treating the amount of space we print the tab the same as the amount of space we need to move under the source code to start underlining. The old code had some logic in there to line them up and we just need to port it over.

Ok, so it's a port issue. Thanks for the explanation @jonathandturner!

One thing that nags me a lot is the amount of space between distinct error messages in the printed console output. Often, because of whitespace in individual error messages, there is more visual whitespace _within_ messages than _between_ distinct ones. This makes it difficult, when scanning printed console output, to visually distinguish different messages, which makes fast visual parsing of the compiler output tricky.

When coupled with the fact that rustc often generates several error messages at once, some of which are follow-ons from one original message appearing at the top of the output, I often find myself scrolling upwards through a column of hard-to-scan text looking for a hard-to-spot relevant message.

A more clearly formatted beginning of the compiler output and clearer delineation between individual error messages would help a lot.

Thanks!

@mhintz Do you have an example of the spacing issue you're talking about? Also, is this an issue with the previous error message style or the new message style?

We'd talked some about maybe a "customization of error colors". What do you mean by error formatting?

Well, making it possible to define the escapes introducing the various labels.

Oh right. Yeah, that could look good, depending on how we do it. Would be fun to experiment.

I thought about using a loosly coloured scheme, to avoid confusion with the labels otherwhere.

Enum variants are associated items, which has some potentially surprising consequences if you attempt to access them through a type alias (including Self in trait implementations). Whether that's actually desired behaviour or not is #26264, but in #31168 I observed that the error is strikingly unhelpful.

A better error, I think, would be something like error: enum variants cannot be accessed through an alias, perhaps with a note suggesting the appropriate code change since we know the compiler can look up the name of the enum in question.

@Ketsuban Wrong thread?

No?

We would very much like feedback on error messages you think could use improvement

My issue was about an error message which isn't very clear, so I posted it here to garner attention since this is an issue for bringing attention to unhelpful error messages.

@jonathandturner Just scrolled through the history over at #32756 and it looks like that PR takes care of my objection about spacing, by reformatting and separating nightly's current output. I also hadn't known about the Dybuk formatter, which looks pretty good (maybe even better than the PR).

I assumed it wasn't on the radar, since it hasn't been merged into nightly yet, and I saw the rustlang Twitter account post about it. Glad it's being worked on!

  • [ ] Customization of error formatting.
  • [ ] Unicode switch.

I am sort of undecided about whether we want these. Customization is
a lot of area to stabilize -- we have to select a means of
customization etc, spec it out, support it, etc -- that I would prefer
to avoid, and it seems like a kind of niche request.

  • [ ] Syntax highlighting.

But this would be nice.

I think that for syntax highlighting, I'd prefer to just find keywords and highlight them in bold (something very minimal). We have to be very wary of drawing attention away.

@nikomatsakis: More or less than this?

Is #31173 covered here?

Wish this thread was open a few weeks ago. I once had an error message give me a rusctc --explain number which in no way pointed to my actual error. It turned out I'd left a semicolon on the end of one of my matchers without an explicit return. I don't remember the exact scenario but I'd assume a mutable variable with a default value was set and the matcher would change it if certain conditions were met and the mutable variable would always be the return value. I apologize that I'm guessing here and this may not have been the issue but it was specifically a semi-colon without an explicit return issue. The error messages in my ~/.bash_history file are E0308, E0507, E0277, E0433, E0080 so one of these only added to my confusion.

Earlier I wrote:

Customization is a lot of area to stabilize -- we have to select a means of customization etc, spec it out, support it, etc -- that I would prefer to avoid, and it seems like a kind of niche request.

Ever since I wrote this, the wording I used has been bugging me. Even though I still more-or-less feel the same, I feel like saying this is a "niche" request sounds dismissive, which I did not intend. Let me just clarify that what I meant is that I suspect that it's a feature that few would take advantage of, and I'd be happiest if we can just find one output that everyone is relatively satisfied with.

It seems to me that macro backtrace is always printed in old format.

When will the next nightly build be released?

@ticki - @alexcrichton is currently working on it. There was a hiccup in the nightly build that he's looking into.

It seems like almost everything that is colored is also bold. In my eye that's little much.
Don't know where to look first
screenshot_20160508_235538

UPDATE: infact, I find it hard to tell where the output started, usually I scroll up to the point where something like this sticks out:

user@machine ~/code/projectx $ cargo run

Now this no longer sticks out

@hoodie - yup, that's a great point. We're working on a revision at the moment that will de-emphasize the "help: for further information..." line so that it's not so bold.

@hoodie interesting. I find the bold helpful for making colored text look good, but I agree that in your display it is more distracting. I guess it's highly sensitive to the particular colors and configuration somehow.

@nikomatsakis it's just that everything is bold, it could suffice to at least make the help: line regular

span_suggestion is not handled in new format.

The colors are gross on Windows. They used to look nice with the old format with nice bright yellows and reds. But dark blue and dark yellow on black? Awful.

@retep998 - that's interesting. So it looks like it doesn't use any bold text. I agree, without the full ANSI support that doesn't look all that good.

When we designed it, we were figuring that the command-line usage in Windows would largely be black and white. I didn't experiment with other shells that might support some (but potentially not all) of the ANSI sequences we're using.

We'd talked about maybe letting you configure the colors in the settings file. That way if you could set it up to look good, regardless of your terminal setup.

@jonathandturner Well it isn't using ANSI escape sequences to begin with on Windows, but rather console API calls. Although yes, the Windows console doesn't currently have a way to make text bold. All you have is 16 colors to choose from, one for foreground and one for background.

That said, the default color in the Windows console is not white, but rather light gray, so if you want bold, you can actually just make the text white and that should stand out.

Also, the warning color was changed from bright yellow to just normal yellow, and that affects both error formats. I'm not at all a fan of that change.

While it would be good to have a way to let the user choose the colors, we should still have a sensible default for the standard Windows console colors.

Actually, there is a second set of default colors, for when you open a powershell window directly, it replaces the dark magenta and yellow colors with its own dark blue background and nearly white foreground, which looks even sillier.

So we definitely need to provide a way to the user to choose which colors they want rustc to use.

Still, the default needs to be sensible for the standard Windows console. People who use that horrendous powershell white on blue scheme can go configure rustc to use something else.

it seems we need target specific stylesheets here :grin:

First, looking forwards to tabs working.

Second, is it expected that using nightly (rustc 1.10.0-nightly (e0fd34bba 2016-05-09)) on this snippet https://is.gd/jP3UYZ has less helpful error messages than stable when not using RUST_NEW_ERROR_FORMAT? E.g.

x.rs:4:15: 4:16 error: cannot borrow `a` as mutable more than once at a time [E0499]
x.rs:4  let c = &mut a;
                     ^
x.rs:4  let b = &mut a;
                     ^
x.rs:4 }
       ^

Third, tabs seem to be broken on the old error messages? I'm pretty sure they used to work E.g.

src/main.rs:79:35: 79:53 error: failed to resolve. Use of undeclared type or module `mem` [E0433]
src/main.rs:79          Moveable { v: Box::new(unsafe { mem::uninitialized() }) }
                                                 ^~~~~~~~~~~~~~~~~~

@aidanhs

the second one looks like a bug - I filed #33543 for it

@aidanhs #33513 fixes tabs for both old and new error format.

Someone posted this into #rust and we solved the problem, but still pondered over the error:

Nightly on playpen, but same result (different formatting) on 1.8 or beta.

use std::io;
use std::sync::{Arc, RwLock};
use std::thread::{Builder as ThreadBuilder, JoinHandle};

fn main() {
    let data = vec!["I am data!".to_string()];
    let data_lock = Arc::new(RwLock::new(data));

    thread(data_lock.clone())
        .map(|t| t.join().expect("Thread failed"))
        .expect("Thread creation failed");
}

fn thread(lock: Arc<RwLock<Vec<String>>>) -> io::Result<JoinHandle<()>>  {
    let thread_lock = lock.clone();
    ThreadBuilder::new()
        .spawn(move || {
            match thread_lock.read() { // line 20
                Ok(data) => {
                    data.iter()
                        .map(|s| println!("{}", s))
                        .collect::<Vec<_>>();
                },
                _ => (),
            } // line 26
        })
}
error: `thread_lock` does not live long enough
  --> <anon>:20:19
20 |>             match thread_lock.read() {
   |>                   ^^^^^^^^^^^
note: reference must be valid for the destruction scope surrounding block at 18:23...
  --> <anon>:18:24
18 |>         .spawn(move || {
   |>                        ^
note: ...but borrowed value is only valid for the block at 18:23
  --> <anon>:18:24
18 |>         .spawn(move || {
   |>                        ^

This is solved by adding a semicolon to the end of the match block on line 26.

I'm not entirely sure what's going on here, I am guessing that the semicolon ensures that the result of the match doesn't try to be returned from the scope of the closure(?) even though the result of the match doesn't contain anything from thread_lock, it is ().

@rrichardson that problem sounds lik it is due to the temporary lifetimes; in this case the match is the trailing unit in the block. See e.g. (closed) https://github.com/rust-lang/rust/issues/22252 -- I feel like there remains an issue open on trying to address this in some nicer way but I've not found it just now. In any case, clearly the error message it can be better: it'd be nice to see if we can revise the rules in some way to make this not an error in the first place, but I'm not sure if that is possible.

Oh good, now even _more_ stuff is using the difficult to read blue text. (Also the help text isn't formatted in bright cyan the way help messages are supposed to be)

Come on, good defaults are really important!

Also, the Windows Console doesn't support bold, so I'd really appreciate it if instead you simply used white. Note that regular text is light gray by default, not white, so white would be the perfect choice here, making the text brighter and stand out, just like bold would.

Even with good defaults, I'd still really appreciate it if rustc had a way for me to choose which colors it uses for which thing. That way I can choose a nice palette of colors in my console and then tell rustc to use those colors.

Using some env vars to define colors sounds like a good idea. :D

@retep998 - agreed good defaults are important, which is why we took so long to stabilize and work on what the format should look like. tbh there wasn't a ton of feedback on what it looks like on Windows.

The colors are easy enough to change. We could potentially detect Windows and switch to something like:

cyan_secondary

Btw, here's what bright white looks like. I'd be afraid it would blend in too much with the code:

white_secondary

@jonathandturner I'm saying to use bright white instead of bold, not instead of blue. If you look at images from other platforms you'll notice how certain text is bold. In conhost that text is not bold because there is no support for bold. Instead of making that text bold, make it bright white on Windows which achieves a similar effect.

@GuillaumeGomez Sure, anything is better than the status quo.

@retep998 - I think you might have something in mind, though I'm not entirely following what you're saying. All blue text is bold text.

I'm certainly amenable to helping here. For example, like I said, we can detect Windows and make changes to the defaults.

@GuillaumeGomez Sure, anything is better than the status quo.

I think the best way to help "the status quo" is to help us create a solution that works for Windows.

@jonathandturner Look at this screenshot someone posted earlier from a non-windows platform:

Notice how some of the white text is bold? That bold text is being generated by https://github.com/rust-lang/rust/blob/d00c2454157713e77729989c715b96ee31c6b278/src/librustc_errors/emitter.rs#L898. Notice how it merely specifies bold and does not specify a color. As a result, because conhost doesn't support bold, that text does not stand out at all in any way. Making that text bright white would be an improvement.

As for a replacement for the "bright" blue currently being used for line numbers and stuff, cyan is the closest alternative there is. Unfortunately bright cyan is being used for help messages, but there's not many choices in the default console color palette that aren't too dark.

Also, the color for warnings really needs to be bright yellow on Windows. Dark yellow is just bleh. Specifically this bit of code https://github.com/rust-lang/rust/blob/master/src/librustc_errors/lib.rs#L735

Re: syntax highlighting, using rustdoc's syntax highlighter after a small refactor (internals discussion):

screen shot 2017-01-23 at 10 54 42

@estebank - I like it 馃憤 Have you tried it with a white background?

@jonathandturner without any customization (just changed the profile in my term):

@estebank - yeah, that yellow isn't quite strong enough for white. In the compiler, albeit a bit hacky, we do this:

                if cfg!(windows) {
                    term::color::BRIGHT_YELLOW
                } else {
                    term::color::YELLOW
                }

However you end up doing it, having something that works well on black and white backgrounds might be a good way of picking defaults.

Agree.

What would you think of using (and avoiding abusing) a set background for specific tokens?

@estebank - let's move this discussion to a separate thread because lots of people are following this one.

Do you have a PR we can move it to?

I'm wondering if it's possible to only use the base colours, instead of the bright versions, especially when there is heavy use of bold at the same time. Most terminals allow an option for setting whether bold text appears in bright colours.

Also, some colour schemes (like Solarized) make heavy use of the bright colours for subtle background shades and this may cause the error output to look odd. Of course, full colour customisation is preferable for these types of cases.

I feel like this bug has outlived its usefulness. I'm going to close it.

Was this page helpful?
0 / 5 - 0 ratings