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

Overhaul borrowck error messages and compiler error formatting generally #32756

Merged
merged 40 commits into from
May 3, 2016

Conversation

nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Apr 5, 2016

This is a major overhaul of how the compiler reports errors. The primary goal is to be able to give many spans within the same overall context, such as this:

./borrow-errors.rs:73:17: 73:20: error: cannot borrow `*vec` as immutable because previous closure requires unique access [E0501]
70     let append = |e| {
                    ~~~ closure construction occurs here
71         vec.push(e)
           ~~~ previous borrow occurs due to use of `vec` in closure
72     };
73     let data = &vec[3];
                   ~~~ borrow occurs here
74 }
   ~ borrow from closure ends here

However, in the process we made a number of other changes:

  • Removed the repetitive filenames from snippets and just give the line number.
  • Color the line numbers blue so they "fade away"
  • Remove the file name and line number from the error code suggestions since they don't seem to fit anymore. (This should probably happen in more places, like existing notes.)
  • Newlines in between errors to help group them better.

This PR is not quite ready to land, but we thought it made sense to stop here and get some feedback from people at large. It'd be great if people can check out the branch and play with it. We'd be especially interested in hearing about cases that don't look good with the new formatting (I suspect they exist).

Here is a checklist of some pending work items for this PR. Some of them may be best left for follow-up PRs:

  • Accommodate multiple files in a MultiSpan (this should be easy)
    • In this case, we want to print filenames though.
  • Remove duplicate E0500 code.
  • Make the header message bold, rather than current hack that makes all errors/warnings bold
  • Update warning text color (yellow is hard to read w/ a white background)

Moved numerous follow-ups to: #33240

Joint work with @jonathandturner.

Fixes #3533

@rust-highfive
Copy link
Collaborator

r? @nrc

(rust_highfive has picked a reviewer for you, use r? to override)

@nikomatsakis
Copy link
Contributor Author

Here is some before-and-after. We should do more shots, e.g. with dark background.

Before:

Before

After:

After

@nikomatsakis
Copy link
Contributor Author

cc @rust-lang/compiler @rust-lang/tools @mitaa

@nikomatsakis
Copy link
Contributor Author

Another before-and-after pair, this time on a dark background:

Before:

Before

After:

After

@alexcrichton
Copy link
Member

I'm super excited about this! Those snippets are really looking great to me.

One point is that in the past we've had mixed experience with lots of words colored differently than the default. In Cargo we recently switched from errors as all-red to just the word "error" in red. In the snippets you've pasted, this just applies to:

  • The entire filename is printed in red for the error, whereas before it was in the normal color and just "error" was in red. I personally prefer having as little in color as possible, but maybe the filename is contained enough here though?
  • The help messages for the borrows here at least are all in blue, which may not look the best on all terminals. That being said I like how it's distinct from both the error message itself as well as the code being printed.

Altogether I guess I'm just saying we probably shouldn't go too crazy in terms of colorizing words. I might revert back to today's behavior for the filename + error indicator, but the help messages I'd probably leave pretty similar to the way they are in your snippets.

@nikomatsakis
Copy link
Contributor Author

Oh, cc @brson, with whom I've talked about this a plenty.

@brson
Copy link
Contributor

brson commented Apr 6, 2016

Looks better to me. A big change but it'll probably just take time to adapt.

  • Things look kind of weird with the line numbers not lining up. Maybe I'll learn to like it. I understand it gives us more room.
  • Although I understand it's how emacs does it, putting the red on the first mention of the file/line number looks weird. When we talked about it it made a lot of sense when emacs does it, but then there was the 'wall of line numbers' where the first one was red, then the others were dark, fadded out. Here you've gone further and removed all the non-primary line information, which lessens the need to visually distinguish them. This colorization emphasizes the error range, instead of the word error. Probably better.
  • Removing the color from the help label makes it less distinct.
  • You have a blank line in your output. That works fine here when there are many lines per error, but will look very bad for a sequence of one-line errors.

@durka
Copy link
Contributor

durka commented Apr 6, 2016

I noticed the carrots ^~ are gone. Not a big deal, but it did make it clear the span was on the line above, rather than the line below (but it's usually clear anyway). I guess you could just replace all the ~ with ^.

@killercup
Copy link
Member

Very nice.

  • I really like that the filename is only given once. (Having up to 100 chars per line of code plus the file name meant I had to maximise the terminal pane showing rustc ouput on my laptop, which is annoying.)

  • Am I right in assuming the filename will be printed in yellow for warnings? That might be difficult to read on some terminals/editors with bright backgrounds.

  • I'm not sure why line numbers, the underline, and the help message are bold when they already have a different color.

  • Do we really want to print "help: run rustc --explain E0001…" every time? But I guess this is a discussion for another day.

  • Using ~ for underlines looks weird to me, because it's a character that's not at the top of the line. I think ^ looks better. To get really crazy: Why not add a unicode mode and do something like this? 😄

    const MAX_RANGE_BITS: u32 = 24;
    ⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟
    

@ticki
Copy link
Contributor

ticki commented Apr 6, 2016

This is very cool. It will essentially make dybuk outdated.

@ticki
Copy link
Contributor

ticki commented Apr 6, 2016

On a seperate note, it should be possible to configure the style of the error messages.

@nikomatsakis
Copy link
Contributor Author

@brson

You have a blank line in your output. That works fine here when there are many lines per error, but will look very bad for a sequence of one-line errors.

I was wondering about this. Do we have one-line errors? Most errors include at least a span, and usually more text.

@nikomatsakis
Copy link
Contributor Author

@brson @alexcrichton

I'm torn about the colors on the filename. I agree that coloring the filename red doesn't look as good as it does in emacs, and I also agree it is less necessary if we remove the redundant filenames.

For reference, here is an image comparing what I see in emacs (which applies its own colors) vs what the compiler does today http://imgur.com/GZKJ4Pg. Somehow the emacs one looks nice to me, but the imitation thereof in this PR looks a little plodding. It might be that the column numbers are highlighted differently. At the same time, the emacs column numbers have quite a lot of colors, maybe a bit more than is needed. In any case, @brson's observions, combined with @alexcrichton's suggestion that we minimize color, are making think that perhaps we can find a new balance.

That said, the current colors arose out of a lot of experimentation -- it's surprisingly hard to find a combination that looks good and achieves a wide variety of goals:

  • clearly separating the labels from the user's source
  • directing the eye to the error message
  • indicating the kind of error
  • not making you want to claw your eyes out

Of course, you might not agree that the current colors achieve that balance. In any case, I don't consider the current choices optimal, and I definitely think there is room to play around more here.

(Does anyone know a good "ANSI editor", btw? It'd be helpful to be able to do mock-ups. I guess I can do it in emacs, maybe. Or maybe just write some custom program using term directly. The turnaround for building the compiler is kind of brutal here if all you are doing is seeing what happens when you make a label bold.)

@nikomatsakis
Copy link
Contributor Author

Also, can we rely on unicode being available? Or auto-detect it? I don't want to have too many modes...but using unicode box-drawing characters would be cool. I remember @kmcallister (I think) had a PR on this that never quite landed.

@ticki
Copy link
Contributor

ticki commented Apr 6, 2016

For comparison

Dybuk:

This PR:

@killercup
Copy link
Member

I would be surprised if you could detect unicode support, @nikomatsakis, as it depends on the font being used (or available fallbacks, I guess.)

@ticki
Copy link
Contributor

ticki commented Apr 6, 2016

Why not just have a variable, RUST_ERROR_UNICODE, to opt-in Unicode?

@GuillaumeGomez
Copy link
Member

That's awesome! However, like others already said, why not replacing "~" by "^"?

Also, why not setting a different color for error lines? I think that having the filename with its own and unique color would improve the display and help to understand what we're reading more quickly.

@nikomatsakis
Copy link
Contributor Author

@ticki

Why not just have a variable, RUST_ERROR_UNICODE, to opt-in Unicode?

I'd much rather make it opt-out. I think the real question is what scheme we want to use for controlling rustc's "skin". We have some compile flags for using colors, which is an obvious precedent, but also doesn't seem that great; this is something that a user would want to decide, and probably uniformly. Maybe we should look for ~/.rustc.toml or something instead.

@nikomatsakis
Copy link
Contributor Author

@ticki yeah, I was thinking that maybe the thing to do is to put the error underneath the filename/line-number. In general I think it's probably a win to use more vertical space when formatting errors.

As long as emacs can still take me to the next error, I'm happy with that. =)

@frewsxcv
Copy link
Member

frewsxcv commented Apr 6, 2016

I remember @kmcallister (I think) had a PR on this that never quite landed.

For reference, here's the pull request: #21406.

EDIT: And the follow-up issue: #24387.

EDITEDIT: Another relevant issue: #28902.

@nagisa
Copy link
Member

nagisa commented Apr 6, 2016

I like the general appearance, here’s some notes:

Why not just have a variable, RUST_ERROR_UNICODE, to opt-in Unicode?

I'd much rather make it opt-out

The box drawing symbols exist since Unicode 1.1. Rust does not support systems with non-utf-8 locales anyway… the only problem is the Windows’ cmd which uses whatever weird codepages they happen to know and even weirder fonts which might not even support latin.

The cmd doesn’t use ANSI and thus must be reliably detected and worked around anyway, so…


That said, the current colors arose out of a lot of experimentation -- it's surprisingly hard to find a combination that looks good and achieves a wide variety of goals

Axe-actly! In my experience barely any default and non-trivial colouring works well with solarized, so we should probably either restrict ourselves to the most barebones escape codes and colours like colours 1-to-6 and inverse or allow configuration of them.


Solarized

looks hard to figure out which spans relate to which messages. What happens when these spans overlap?


Remove duplicate E0500 code.

Using struct_span_err_with_code method directly would help. Would become stringly typed though and otherwise opaque to the lint.

@nikomatsakis
Copy link
Contributor Author

What happens when these spans overlap?

You're looking at it. The two labels there are attached to the same span.

@steveklabnik
Copy link
Member

One more inevitable thing is that a lot of docs are going to be showing old errors. Not a showstopper for this PR, mind you, but something that needs to be considered to some degree.

@nagisa
Copy link
Member

nagisa commented Apr 6, 2016

@nikomatsakis

You're looking at it. The two labels there are attached to the same span.

To me it looks like that’s two notes attached to two adjacent spans of length 1. One span on v and another on ). That’s not overlapping. By overlapping I mean something like

code code code
^^^^^^^^^ span1
     ~~~~~~~~~ span2

@aturon
Copy link
Member

aturon commented Apr 6, 2016

@steveklabnik

One more inevitable thing is that a lot of docs are going to be showing old errors. Not a showstopper for this PR, mind you, but something that needs to be considered to some degree.

I wonder if there's any way to automate the inclusion of errors.

@nikomatsakis
Copy link
Contributor Author

@nagisa

To me it looks like that’s two notes attached to two adjacent spans of length 1. One span on v and another on ). That’s not overlapping. By overlapping I mean something like

Yeah, that's actually true in this particular case, I didn't look closely enough. In any case, what the PR currently does is to union all ~. That said, one of the changes I wanted to consider was making more than one line of ~ for overlapping spans. In this version, we erred on the side of conciseness over precision, which might not be the right trade-off.

@nikomatsakis
Copy link
Contributor Author

So what do people think about using unicode except for when running on windows, since apparently cmd doesn't support unicode?

Manishearth added a commit to Manishearth/rust that referenced this pull request May 2, 2016
Overhaul borrowck error messages and compiler error formatting generally

This is a major overhaul of how the compiler reports errors. The primary goal is to be able to give many spans within the same overall context, such as this:

```
./borrow-errors.rs:73:17: 73:20: error: cannot borrow `*vec` as immutable because previous closure requires unique access [E0501]
70     let append = |e| {
                    ~~~ closure construction occurs here
71         vec.push(e)
           ~~~ previous borrow occurs due to use of `vec` in closure
72     };
73     let data = &vec[3];
                   ~~~ borrow occurs here
74 }
   ~ borrow from closure ends here
```

However, in the process we made a number of other changes:

- Removed the repetitive filenames from snippets and just give the line number.
- Color the line numbers blue so they "fade away"
- Remove the file name and line number from the error code suggestions since they don't seem to fit anymore. (This should probably happen in more places, like existing notes.)
- Newlines in between errors to help group them better.

This PR is not quite ready to land, but we thought it made sense to stop here and get some feedback from people at large. It'd be great if people can check out the branch and play with it. We'd be especially interested in hearing about cases that don't look good with the new formatting (I suspect they exist).

Here is a checklist of some pending work items for this PR. Some of them may be best left for follow-up PRs:

- [x] Accommodate multiple files in a `MultiSpan` (this should be easy)
  - In this case, we want to print filenames though.
- [x] Remove duplicate E0500 code.
- [x] Make the header message bold, rather than current hack that makes all errors/warnings bold
- [x] Update warning text color (yellow is hard to read w/ a white background)

Moved numerous follow-ups to: rust-lang#33240

Joint work with @jonathandturner.

Fixes rust-lang#3533
@bors
Copy link
Contributor

bors commented May 2, 2016

⛄ The build was interrupted to prioritize another pull request.

bors added a commit that referenced this pull request May 2, 2016
Rollup of 14 pull requests

- Successful merges: #32756, #33129, #33225, #33260, #33309, #33320, #33323, #33324, #33325, #33330, #33332, #33334, #33335, #33346
- Failed merges:
@bors
Copy link
Contributor

bors commented May 3, 2016

⌛ Testing commit 9355a91 with merge 44b3cd8...

bors added a commit that referenced this pull request May 3, 2016
Overhaul borrowck error messages and compiler error formatting generally

This is a major overhaul of how the compiler reports errors. The primary goal is to be able to give many spans within the same overall context, such as this:

```
./borrow-errors.rs:73:17: 73:20: error: cannot borrow `*vec` as immutable because previous closure requires unique access [E0501]
70     let append = |e| {
                    ~~~ closure construction occurs here
71         vec.push(e)
           ~~~ previous borrow occurs due to use of `vec` in closure
72     };
73     let data = &vec[3];
                   ~~~ borrow occurs here
74 }
   ~ borrow from closure ends here
```

However, in the process we made a number of other changes:

- Removed the repetitive filenames from snippets and just give the line number.
- Color the line numbers blue so they "fade away"
- Remove the file name and line number from the error code suggestions since they don't seem to fit anymore. (This should probably happen in more places, like existing notes.)
- Newlines in between errors to help group them better.

This PR is not quite ready to land, but we thought it made sense to stop here and get some feedback from people at large. It'd be great if people can check out the branch and play with it. We'd be especially interested in hearing about cases that don't look good with the new formatting (I suspect they exist).

Here is a checklist of some pending work items for this PR. Some of them may be best left for follow-up PRs:

- [x] Accommodate multiple files in a `MultiSpan` (this should be easy)
  - In this case, we want to print filenames though.
- [x] Remove duplicate E0500 code.
- [x] Make the header message bold, rather than current hack that makes all errors/warnings bold
- [x] Update warning text color (yellow is hard to read w/ a white background)

Moved numerous follow-ups to: #33240

Joint work with @jonathandturner.

Fixes #3533
Manishearth added a commit to Manishearth/rust that referenced this pull request May 3, 2016
Overhaul borrowck error messages and compiler error formatting generally

This is a major overhaul of how the compiler reports errors. The primary goal is to be able to give many spans within the same overall context, such as this:

```
./borrow-errors.rs:73:17: 73:20: error: cannot borrow `*vec` as immutable because previous closure requires unique access [E0501]
70     let append = |e| {
                    ~~~ closure construction occurs here
71         vec.push(e)
           ~~~ previous borrow occurs due to use of `vec` in closure
72     };
73     let data = &vec[3];
                   ~~~ borrow occurs here
74 }
   ~ borrow from closure ends here
```

However, in the process we made a number of other changes:

- Removed the repetitive filenames from snippets and just give the line number.
- Color the line numbers blue so they "fade away"
- Remove the file name and line number from the error code suggestions since they don't seem to fit anymore. (This should probably happen in more places, like existing notes.)
- Newlines in between errors to help group them better.

This PR is not quite ready to land, but we thought it made sense to stop here and get some feedback from people at large. It'd be great if people can check out the branch and play with it. We'd be especially interested in hearing about cases that don't look good with the new formatting (I suspect they exist).

Here is a checklist of some pending work items for this PR. Some of them may be best left for follow-up PRs:

- [x] Accommodate multiple files in a `MultiSpan` (this should be easy)
  - In this case, we want to print filenames though.
- [x] Remove duplicate E0500 code.
- [x] Make the header message bold, rather than current hack that makes all errors/warnings bold
- [x] Update warning text color (yellow is hard to read w/ a white background)

Moved numerous follow-ups to: rust-lang#33240

Joint work with @jonathandturner.

Fixes rust-lang#3533
bors added a commit that referenced this pull request May 3, 2016
Rollup of 14 pull requests

- Successful merges: #32756, #33129, #33225, #33260, #33309, #33320, #33323, #33324, #33325, #33330, #33332, #33334, #33335, #33346
- Failed merges:
@bors bors merged commit 9355a91 into rust-lang:master May 3, 2016
@ticki
Copy link
Contributor

ticki commented May 3, 2016

🎉

@nikomatsakis nikomatsakis deleted the borrowck-snippet branch May 3, 2016 10:16
@joshtriplett
Copy link
Member

I really like the new approach posted by @jonathandturner in #32756 (comment) , particularly the method of highlighting the primary error.

Two remaining issues with it, one minor, one major:

  • Minor: please do consider dropping the |> marker on non-code lines, and only keeping it next to the line numbers, as in the approach shown as "alternative" in Overhaul borrowck error messages and compiler error formatting generally #32756 (comment) . I think this would help highlight and distinguish source lines from surrounding explanatory lines.
  • Major: putting a marker before the file:line:column: indicator will break many editors/IDEs, which expect that to appear starting in the first column. A quick test with vim's default settings shows that it treats the --> as part of the filename. I do think it looks great for terminal use, just not for use in an editor. Perhaps detect if stdout is a terminal, use this format if so, and if not, drop that marker?

@nikomatsakis
Copy link
Contributor Author

@joshtriplett

putting a marker before the file:line:column: indicator will break many editors/IDEs, which expect that to appear starting in the first column.

This is really a sticking point. I'm not really sure what's the best fix here. I think that the current format with the --> coming second is easier to read: I've spent a lot of time A/B testing as well as asking around and I feel pretty confident about that. There are a couple of reasons for this:

  • It puts the primary data (error, message) up front
  • It avoids the problem that the (sometimes very long) filename pushes the message way over into another "horizontal column" than the examples that come belonw
    • I think this is (partly, no doubt) what led us to putting filenames before every line before, so as to keep things kind of horizontally aligned

OTOH, I really want to enable "low-tech" editor integration. One thing we've debated about is having a "third mode". For example, perhaps we DO use an environment variable (RUST_ERROR_FORMAT) that could select default/json/header, where header is the new mode. If you have header, it looks the same as normal except that it adds:

filename:line:col: [error|warning]: message

in front of the error. This is intended for your editor to match on, basically. (The downside of this is that the message would appear twice, which is a shame.) The reason I've come to favor an env var for this purpose is that one can easily set it in the editor's setup and have it "propagate down" to compilations executed by the editor, but not affect compilations done by hand on the console.

But I guess the other question is how easy it will be to adjust editor modes to the new format as it exists today. For example, I opened this PR on the emacs mode rust-lang/rust-mode#154. If we can just get editors to either use JSON or else use the default format, that might be best.

@ticki
Copy link
Contributor

ticki commented May 4, 2016

I think that this form of integration is hacky. IDEs should prefer JSON.

@joshtriplett
Copy link
Member

@nikomatsakis I absolutely agree that this format is more usable by humans, just not by existing editors.

I don't think it's reasonable to require an environment variable for this; error message parsing and handling should work out of the box. Right now, I have no Rust support in vim (because the Vim mode for Rust isn't packaged in Debian), and I regularly use :set makeprg=cargo and :make build; I can also log the output of a build and run vim -q build.log. I would argue that those should all continue to work; this shouldn't require special editor configuration. And changing existing editors doesn't suffice; there's a long tail of editors people prefer, and any programmer's editor that parses error messages expects this convention.

Having an environment variable and command-line option for explicit handling, or for IDEs/editors that want to implement special support for Rust, seems like a good idea. However, I would suggest that the default should be "auto", which would imply "normal" if stderr is a TTY, or "header" if it isn't.

@ticki Current generation IDEs with specifically designed support for Rust might, but we can't write off decades of programmer's editors and the conventions they expect. The standard error message format is file:line: or file:line:column:.

@nagisa
Copy link
Member

nagisa commented May 4, 2016

The standard error message format is file:line: or file:line:column:.

It is only a de facto convention, not standard. There’s a bunch of things that do not honour the convention as well.

@ticki
Copy link
Contributor

ticki commented May 4, 2016

@joshtriplett

@ticki Current generation IDEs with specifically designed support for Rust might, but we can't write off decades of programmer's editors and the conventions they expect. The standard error message format is file:line: or file:line:column:.

Yeah, most compilers use that, so it wouldn't make sense to drop it. I simply think that for Rust-specific IDEs, there should be more emphasis on JSON, since it is strictly less ambigious and spec-able

@joshtriplett
Copy link
Member

@ticki Absolutely agreed; anything doing more than the most basic parsing should use the JSON format.

@nagisa Half the world runs smoothly because of de-facto conventions. The default configuration shouldn't break people's preferred editors.

Again, we're not talking about changing the default format for terminal use; we're talking about automatically detecting when output goes to a log and adding a line to simplify parsing.

@nikomatsakis One other aspect of the "header" format: it needs to not include the :line:column portion after the filename on the marker line, because otherwise the error will show up twice, once in /path/to/file:line:column and once in "--> /path/to/file:line:column. One test case for the "header" format should be to write build output to a log, runvim -q log, repeatedly hit:cn[enter]`, and make sure the list of errors traversed only includes the header lines, not any other part of the error message.

@nikomatsakis
Copy link
Contributor Author

Rather than discussing this "header format" on this closed PR, I propose we move the conversation here: http://internals.rust-lang.org/t/editor-compatibility-and-the-new-error-format/3435

I tried to summarize the salient points.

Manishearth added a commit to Manishearth/rust that referenced this pull request May 8, 2016
…=jntrnr

degrade gracefully with empty spans

In rust-lang#32756, we solved the final test failure, but digging more into it the handling of that scenario could be better. The error was caused by an empty span supplied by the parser representing EOF. This patch checks that we cope more gracefully with such spans:

r? @jonathandturner
Manishearth added a commit to Manishearth/rust that referenced this pull request May 8, 2016
…=jntrnr

degrade gracefully with empty spans

In rust-lang#32756, we solved the final test failure, but digging more into it the handling of that scenario could be better. The error was caused by an empty span supplied by the parser representing EOF. This patch checks that we cope more gracefully with such spans:

r? @jonathandturner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.