New error format

Recently, Niko and I landed our first batch of changes in rethinking how we display compiler error messages. Error messages in Rust, especially ones like borrow checker errors, have a lot of moving parts to them. As a new user, the first time you see errors like this can be daunting. The information is there, but you have to wrap your head around it to know what to do next.

We've got a new design that we think helps to bring out the most important information. You can try it out using a nightly build and setting the RUST_NEW_ERROR_FORMAT environment variable (eg, "export RUST_NEW_ERROR_FORMAT=true" in bash). Here is how it looks.

Before

After

The new format has a few advantages over the previous format:

  • We've removed the redundant line information, which cuts down on noise
  • Put your source front and center
  • We use callouts, bolding, and coloring to focus your eyes on the key part of the error while also noting important other bits of information

As you can see, it's not that we're really showing different information than we were previously, we're just displaying it in a way that's a bit easier to read and understand.

We're not done, yet, and we'd love your help. We have a set of improvements we'd like to make which are tracked with this meta-issue: https://github.com/rust-lang/rust/issues/33240. Feel free to file formatting issues, readability issues, missing info bugs, etc and mention the meta-issue. So far, we've been converting borrow check errors to the new format. We'd also like to convert region check errors as well. We have some ideas, and if you like to help out let's chat.

We'd like to keep design discussions on the format here on the internals list as it's nicer to have to have full discussions here.

Also, if you are a maintainer for one of the Rust editor plugins, we're currently discussing how the new errors and editors interact in this thread: Editor compatibility and the new error format

For those that are still reading and are curious about the ins and outs of the design, here's a quick overview of the different parts.

Header: The header is now split across two lines. The first line starts with an indicator of what the message type is (Error, Warning, etc), followed by the main message text and then by the error code. The second line is indented underneath and gives the location. This should let your eye quick "lock on" to what the message is about, and then where it is.

Line number column: The line number column replaces the are where we previously put the full filepath. Same idea here, we want to give you a way to see what lines the errors were on. We separate these lines with the |> to help separate the line numbers from the source. This serves double duty by also creating a box around your source. The combination of this and the indentation above makes it easy, at a glance, to see each error separately and find each of the parts.

Source code area: Your source code. We pull out the relevant lines that have error/warning/note spans (just as before) but grouped in the same order you might see them in your source. We also have labels on each span. Ideally, for readability, all spans should have labels, but we haven't quite gotten there yet.

Optional notes: We still have the optional notes, just like we did with the old error format. Things like expected/found will show up here, for example.

24 Likes

Finally, there is a nightly that has these changes! I wanted to try them for weeks now :smiley:

While @jntrnr’s screenshot only shows one error with black-on-white text, I wanted to see how this looks with warnings and white-on-black. So, I ran my clippy-diesel branch with RUST_NEW_ERROR_FORMAT=true, which looks like this (PDF).

Quite nice and much better than before, but still noisy. It’d be interesting to see if we could combine some messages about the same line/span. (Also, some spans look wrong, i.e., they only underline one character, but that may be a problem with clippy.)

Will you consider splitting the file name from the line:col information? Double-clicking to select the file name using either the old or the new error format gives you a selection of something like src/impl_views.rs:154:19. If the line number were separated with whitespace, then it’s easier to grab the file name from the error output.

1 Like

This is the result of a deliberate change we made, which was to convert multi-line spans into a single ^ at the start. This was made to lighten the display of multi-line spans:

  • today we just display the lines with no carrot at all; that seemed bad
  • before we were displaying ^^^^^ all the way until the end of the line, then some ..., and then ^^^ at the end; this was a bit much.

We could tweak this behavior. However, I think that the assumption that @jntrnr and I made was that by and large multi-line spans are a "bug" in the sense that we ought to try and supply tighter spans. For example, to highlight a method, we should just give the span of the method name, not the entire method definition.

We initially did this but decided against it. The reason boils down to the longstanding file:line:col convention supported by editors. For example, @nrc urged us to keep the current format because he likes to copy-and-paste the foo.rs:22:22 text onto the command line and run subl foo.rs:22:22, which brings his editor to the right spot. One option might be to tweak the colors used for the line and column to help them "fade" a bit.

1 Like

Yes, please keep this format! iTerm, SublimeText, and VSCode all support cmd+clicking these strings to open the file at the right position.

1 Like

which brings up the question, how is this integrated into editors? is there a standard format or does every editor have to provide parsers for these errors? Do you take “parsability” into account?

We have been discussing this here: Editor compatibility and the new error format

1 Like

Ok, that clarifies a lot. But my editor does not support this format.

@bluss - out of curiosity, which editor do you use?

This will make it harder to get quality reporting out of clippy – we often use spans of Exprs without looking how big those are in the code. At least somehow showing that those spans are multiline would probably be a good idea.

do you have some examples that look a lot worse? I think the function declarations seem…not bad, but I’d be curious if there are some where knowing the end extent is quite useful.

I think most of the match-related lints could fall into that category (for example the single_match tries to replicate the original code before suggesting a replacement). Also lints like option_map_unwrap_or or no_effect, just add water and some multiline expressions…

The reason I asked for specific examples is that, in most cases where I’ve seen the errors in practice, I find it to be an improvement.

Another rather interesting question might be whether we can make it easier for lints to take advantage of the ability to combine multiple spans with labels :slight_smile:

It would be nice if the order of the messages were reversed, so you can easily find the first error.

1 Like

vim! I think there should be a solution but the file_line plugin I found is buggy and does not interact with syntax highlighting or filetype plugins properly, so it seems like the wrong way to go. Maybe even a shell function is the best solution.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.