<div dir="ltr">Following up on this thread, I published (to the best of my ability) the result of the work with the students.<br><br><a href="https://mccue.dev/pages/8-13-23-java-compiler-error-messages">https://mccue.dev/pages/8-13-23-java-compiler-error-messages</a><br><br>(I know I haven't really responded to Maurizio's points about the inference and parsing errors, the thrust of what I wrote and the prototype we made is "we at least need a box to put the solutions into", if that makes sense.)<br><br><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Feb 7, 2023 at 8:57 PM Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com">maurizio.cimadamore@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<p>Hi,<br>
there are two classes of errors that are hard. The first, as your
example demonstrates, has to do with parser errors. When parsing
it is hard to recover from errors. Javac tries to do its best, but
if you are parsing a production, and you find a token that is
unexpected for that production, it is not clear what should happen
next. I mean, an error should be reported - but what then? Javac
tries to figure out where to start parsing again - in some cases
this can be done with some success (e.g. finding the matching
closing brace, parens, etc.). In other cases it's harder, and it
can lead to pathological situations such as the ones you describe.
Some of these issues might be made worse by actual bugs (so it is
possible that in the case of "expected class" there's an actual
issue with javac - would be nice to have a reproducer).</p>
<p>The other class of errors that are hard are errors related to
overload resolution and inference. The problem there is that the
error has to cover so much ground (too much). When you have an
overload resolution failure, you can, at least in the general
case, have many overload candidates, each of which fails for a
different reason (which might be interesting or not). If there's
inference, the reason as to why a candidate is not applicable
might be obscure (e.g. incompatible bounds on an inference
variable), and if you have nested or chained generic method calls,
things tend to explode pretty quickly, so when your typical stream
chain fails to type it's hard to understand exactly what needs to
be fixed - often because the error typicall shows up in the wrong
place. For instance, you might get an error message when you call
`toList()` on a stream and assign it to a `List<String>` -
but the real problem is that the type of the stream is not
`Stream<String>` as you expect: something sent inference
down the wrong path in an earlier call in the method chain, which
caused the stream type to become `Stream<Object>`.</p>
<p>These things can (and should!) be improved, but there's a limit
on how much you can improve things when working with the command
line interface. For instance, when diagnosing inference issues
inside an IDE, I find myself hoovering on each component of the
call chain, or try to use auto-complete after each subexpression,
to have a rough idea of what the type might be at that point. Even
doing that is not always possible: methods that are generic in
their return type can be "influenced" by their surrounding
context, so breaking up a method chain can sometimes result in
changes to how a subexpression is typed. So... it's an hard
problem - and the limited visual aids a terminal offer, combined
with the lack of interaction makes these issues particularly
pesky. Other langauges have explored the idea of a type debugger
[1] - although I don't know what's the state of these initiatives.<br>
</p>
<p>Cheers<br>
Maurizio<br>
</p>
<p>[1] - <a href="https://infoscience.epfl.ch/record/179877?ln=en" target="_blank">https://infoscience.epfl.ch/record/179877?ln=en</a><br>
</p>
<p><br>
</p>
<p><br>
</p>
<div>On 04/02/2023 03:48, Ethan McCue wrote:<br>
</div>
<blockquote type="cite">1.
The error messages that the student got were not helpful for them
seeing their error. I don't have their original code so I can't
dive in to why and say "ah, we could obviously make this case
better", but I choose to believe there was some way to not vomit "<span style="font-family:monospace">class, interface, enum, or record
expected" </span><font face="arial, sans-serif">nine times.</font></blockquote>
</div>
</blockquote></div>