Towards better error messages in Scalac

I’m not sure what you have in mind as far as tooling integration, but maybe
one possibility is to have a flag that will cause scalac to output only
json or something. That might make it easier to migrate tools that parse
stdout.
Also if the LSP (e.g. in sbt 1.1.0) would use the json version rather than
the human-friendly version, perhaps GUIs could have a better way of
presenting errors than is possible on the console (without having to do
special parsing).

Well, I guess 2.12 will just have to be my last version of Scala, unless somebody contributes support for 2.13.

No other language has broken their output format so mercilessly. It is NOT an implementation detail, it is documented output. I would appreciate if updating downstream tooling was part of the funded scope, since the rest of us are being forced to donate significant time to play catchup at no benefit to us.

I tend to agree with @fommil that compatibility is important and we should not waste precious time playing catch-up. Of course, there might be very important improvements that are impossible without breaking existing clients, but I’m optimistic about that not being the case here.

What’s the bare minimum that needs to be kept in order for emacs and other tools to keep working? Would something like <filename>:line: message be compatible enough, where message is “unparsed” and includes the code snippet? This is certainly enough for Eclipse and VS Code to keep working until more advanced info is available via json or whatever it is.

$ scalac -d /tmp private.scala 
private.scala:15: error: not found: value X1
    case Some(y @ X1) =>
                  ^
one error found
1 Like

Yes something like that would be good. The regexes we’re using could be added to the tests to make sure the new format does not break downstream. https://github.com/ensime/emacs-sbt-mode/blob/master/sbt-mode.el#L210-L229

Needs to be full file name to avoid ambiguity, on the same line, because Emacs has trouble with multi-line error messages. Emacs can render the short version to the user if anybody cares enough about aestetics.

There was an interesting talk at Off the Beaten Track 2018 (co-located with POPL), named Explaining Type Errors.

The gist of the idea was that we should be moving away from “static error messages” and towardsinteractive error explanations.” Different people from different backgrounds look for different things in error messages, and displaying too much information would make the errors too verbose. Instead, we should be able to click and expand dependent error explanations (to see the potential sources of the main error), query the types of the terms involved, display the implicits in scope, access the documentation on certain features, etc.

I think this would work particularly well with implicits, which are currently pretty painful to debug, but for which you typically don’t want to display all available information (the entire resolution trace) to the users.

This is one more reason to use error ADTs as the core representation of errors, and then let interpreters do the job of presenting them to the users. It seems that it would be feasible to keep a “backward compatibility” interpreter that generates error messages the old way, so as to avoid breakage from legacy tools.

Two notable reactions to the OBT’18 talk were:

  • Martin mentioned that keeping track of precise error sources (as presented in the talk, which was about a Hindley-Milner-style system) may not scale, as the compiler is typically already under some memory pressure; re-running a more precise type-checking algorithm only if an error is encountered is an option, but it means users have to wait even longer to get feedback (also, I think it may be harder to maintain both the fast and precise checkers in parallel).

  • Someone involved in the implementation of Rust mentioned that having precise errors, and in particular precise position spans, was far from trivial – it involved a great deal of adaptation to the compiler and the addition of dedicated runtime structures.

2 Likes

It should be possible to supply a Reporter that emits legacy messages, as mentioned in the previous comment. That should be a design goal.

Another easy goal is to support filtering of messages, as also mentioned previously.

Another possible goal is support of downstream linters. I’d like my pluggable linter to work with my pluggable message suppression system and other reporting components so that clippy can offer advice about lints.

An example wart in the current API is the “re-run with different options for more information” message, which has to be customized for different tool environments. It’s easy to slip into vendor lock-in.

3 Likes

Most important information for me is filename, line and column of the error.

Another productivity boost is to place error message on the new line, not always do I have whole screen devoted to reading error messages and as soon as I have to scroll or wrap lines productivity rapidly degrade.

[error] src/main/scala/com/foldright/LineReader.scala:6:12:
[error] not found: value line
[error]     while (line != null) {
[error]            ^

Disclaimer: I do use Emacs + highly customised sbt-errors-summary

3 Likes

I am looking forward to better error messages in scala but please do consider emacs users and maintain compatibility.

1 Like

It’s not bad at all, I already do that in imclipitly using scalameta to find possible enrichments in the codebase and generate scala-clippy advice for missing enrichments. As long as we agree on a format then library authors can include a file in resources of enrichments they offer, then when a missing method is found the compiler can read the resources directory and display enrichments offered by the libraries on the classpath.

The version using scala-clippy can automatically generate advice based on the code in your project to catch messages like

val foo = Option(5).valueOr(0)

value valueOr is not a member of Option[Int]
and augment the message with:
Clippy advises: You may need to import com.helpful.OptionEnrichments._

If a nice ADT was exposed then it would be easy to augment the advice from an IDE to just add the import.

btw, hiding full pathnames in sbt in emacs is now documented in the ensime docs.

http://ensime.github.io/editors/emacs/sbt-mode/#related-customizations

1 Like

My 5 cents: Fine-granular warnings silencing

This should be easy to implement but would help a lot.