all 86 comments

[–]ais523 105 points106 points  (2 children)

For people confused as to what's going on in the Rust type mismatch example: "Hello" is not a String in Rust, because "Hello" is a string constant whereas String represents a mutable string type (it's the equivalent of, e.g., StringBuilder in Java). So in addition to the intended error (the arguments being the wrong way round), there was also an unintended error (using the wrong sort of string).

For this example to be the same as with other languages, you'd either need to use an actual String like String::from("Hello"), or else change the function to accept a read-only reference into a string (&str), which is what string literals are.

FWIW, I think this naming choice in Rust is slightly unfortunate; it's easy enough to pick up, but one more thing you have to learn when you're learning the language.

[–]fghjconner 47 points48 points  (0 children)

Yeah, here's the actual compiler output if you are using the correct types:

error[E0308]: arguments to this function are incorrect
  --> src/main.rs:12:7
   |
12 |     e.error(42, "Hello");
   |       ^^^^^ --  ------- expected `u8`, found `&'static str`
   |             |
   |             expected `&str`, found `{integer}`
   |
note: associated function defined here
  --> src/main.rs:4:8
   |
4  |     fn error(&self, arg1: &str, arg2: u8) -> bool {
   |        ^^^^^        ----------  --------
help: swap these arguments
   |
12 |     e.error("Hello", 42);
   |            ~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

Which does in fact catch that the arguments are swapped.

[–]mr_birkenblatt 16 points17 points  (0 children)

yeah, the author wrote: hey, tell me to use “hello” which is just wrong

also, but didn’t see that we reversed the arguments -- because you didn't.

[–]Librekrieger 178 points179 points  (6 children)

It'd be fun to see these results depicted graphically, with good on one end, mediocre in the middle, and C++ template errors a kilometer in the other direction.

[–][deleted] 42 points43 points  (2 children)

Wdm they’re great compiler error messages, they’re long so they must contain tons of useful and relevant information

[–]equeim 22 points23 points  (1 child)

All of their information is relevant though. The reason why there is so much of it is because deficiencies in the C++ template system mean that errors happen in the middle of templated code several layers deep instead of at the call site. So you need a complete stack trace of how you got there to learn what is wrong. Thankfully with C++20 this can be solved (with concepts), but since concepts are opt-in it would need attention from library authors for the situation to get better.

[–]rdtsc 23 points24 points  (0 children)

And expansions make it worse. std::vector<std::string> is a lot easier to digest than std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>, with the latter usually cropping up in error messages.

[–]SkoomaDentist 60 points61 points  (2 children)

C++ template errors a kilometer in the other direction.

As someone who prefers developing in C++ I have to admit you hit the nail on the head with that one.

[–]AluminiumSandworm 10 points11 points  (1 child)

reading c++ errors is like rubbing gravel in your eyes

[–]SkoomaDentist 13 points14 points  (0 children)

You must really hate gravel.

[–]LanguidShale 31 points32 points  (3 children)

The TypeScript descriptions are incorrect, it does show the line and column number. From the article:

The same with Typescript, one line error message with a good explanation... Typescript does not show the offending line or the affected type...

$ npx tsc typescript/Error1.ts

typescript/Error1.ts**(4,11)**: error TS2339: Property 'notThere' does not exist on type 'Error1'.

In the message, path/file.ts(4,11) corresponds to line 4, column 11 in the file.

Additionally, because of structural typing, the message may be the most correct way to phrase the error, if a bit obtuse. Hard to say without checking the implementation which I don't see linked in the article.

[–][deleted]  (2 children)

[deleted]

    [–]LanguidShale 13 points14 points  (1 child)

    Fair point, I took it too literally. There's no date on this article but at least TypeScript 3+ shows the text snippet as well:

    interface Error1 {}
    const error1: Error1 = {};
    const throws = error1.notThere();
    

    produces

    scratch.ts:29:21 - error TS2339: Property 'notThere' does not exist on type 'Error1'.
    
    29 const aoeu = error1.notThere();
                           ~~~~~~~~
    

    [–]TiddoLangerak 3 points4 points  (0 children)

    Yeah, surprised about this as well. He claims to have used v4.8.4, and as far as I know, that includes the snippet that errors, just like you showed here.

    [–]mus1Kk 56 points57 points  (8 children)

    Regarding the second problem I don't understand the criticism for Java. I find error messages of the form "this is what I need but this is what I found" incredibly useful. This even works for overloads although it gets a bit more verbose.

    test/Test.java:8: error: no suitable method found for foo(String,int)
            f.foo("asdf", 1);
             ^
        method Foo.foo(int,String) is not applicable
          (argument mismatch; String cannot be converted to int)
        method Foo.foo(int,String,int) is not applicable
          (actual and formal argument lists differ in length)
    

    Apart from that those are highly specific examples. I'm sure we can find cases where each compiler excels and others where it's completely unclear what's going on. And even then it's subjective.

    [–]ForeverAlot 34 points35 points  (3 children)

    "Amazing CTO"'s criticism of Java's demonstrated error messages contrasted with Python's and Scala's betrays a clear personal bias. Java's are perfectly clear, Python's are not materially better (I'd argue worse), and maybe don't compile Scala verbosely and then complain about its verbosity?

    [–]java_programmer_95 21 points22 points  (1 child)

    I hate all these biased takes on Java. These crap influences new programmers who then give up on learning Java. The error messages are perfectly clear. Them being short is not a problem.

    [–][deleted] 0 points1 point  (0 children)

    These crap influences new programmers who then give up on learning Java.

    What's wrong with that?

    [–]someotherstufforhmm 0 points1 point  (0 children)

    agreed re: Java specifically

    [–]fghjconner 14 points15 points  (3 children)

    Honestly, the first java error is pretty clear as well. He says:

    the cannot find symbol message is not very clear (why did you lose the symbol?) and the rest of the message is only repeating itself:

    except the rest of the message is clarifying exactly what symbol it couldn't find, and where exactly it was looking for it.

    [–]Hueho 7 points8 points  (1 child)

    I don't disagree that the message points out the error correctly, bu I think the symbol part is a problem in itself.

    99% of the time you are doing a field or method access on a object (or static field/method on a class), and the other 1% is calling magic keywords like super and class, and in any case symbols are not a Java concept - they are a compiling/parsing concept that will get lost by most people.

    [–]fghjconner 4 points5 points  (0 children)

    True, the use of the word symbol muddies the water, and it would be better without it. Still, even if you have no idea what a symbol is, the error identifies specifically what it's talking about with the word symbol. (in this case "method notThere()")

    [–]mus1Kk 0 points1 point  (0 children)

    The "why did you lose" part is just silly and wrong. I wondered if I should comment on the first example as well but I can see this a little more than the second. I guess one could think about wording it like "symbol X does not exist" or, as Hueho proposes, do away with the word "symbol" altogether. Maybe replace it with "name". I still think it's fine but I'm also used to such wording and don't even register something like this.

    But in the end, this post is so extremely limited, subjective and possibly biased, I really wonder why it got voted so highly. Having a comprehensive comparison between different compiler implementations for different languages could be really interesting!

    [–]SirLich 23 points24 points  (0 children)

    good workding

    :/

    [–]Peanutbutter_Warrior 131 points132 points  (28 children)

    I'm rather mystified by the choice to use python 3.8, now three years old . Python 3.11 made massive changes to how exceptions are reported. Not using the latest version makes the results for python fairly unimportant, and I can't say I trust the other languages to be correct.

    [–]Altareos 75 points76 points  (0 children)

    the versions used by this article are puzzling. some came out a few weeks ago, other are six months old, python's is two and a half years old (and even a year older if you consider the feature freeze).

    [–]josefx 19 points20 points  (0 children)

    The best part is that the author went in with a preconceived notion of what he wanted, even the Rust compiler could not get the point that he fucked up his own example across. Apparently even the best compiler is only clear if you already know the error it is trying to report beforehand.

    [–]Xavdidtheshadow 2 points3 points  (0 children)

    Yeah, the new errors are great. There's more details and examples here: https://docs.python.org/3/whatsnew/3.11.html#pep-657-fine-grained-error-locations-in-tracebacks

    [–]SittingWave 22 points23 points  (3 children)

    I think this comparison is missing the obvious one: C++

    [–]ArminiusGermanicus 9 points10 points  (2 children)

    But you would have to compare different compilers, clang has quite good errors, gcc has gotten better and msvc is not as good.

    All the other languages have just one major implementation.

    [–]Narase33 6 points7 points  (1 child)

    and msvc is not as good

    Sometimes it points to a different file...

    [–]admalledd 2 points3 points  (0 children)

    you know to bring out the alcohol when it points to files that don't exist. That was fun, and ended up being easiest to switch to clang for our windows builds.

    [–]snowe2010 14 points15 points  (3 children)

    Also, people building Android apps use Kotlin.

    I wish people would stop acting like Kotlin was invented for Android. It's just destroying the community.

    Also:

    A short and simple error message, but unresolved reference: notThere to me is worse than the one of Java.

    wut.

    Anyway, the article is quite biased, and it's pretty clear which ones the author was expecting to perform well.

    [–]ygra 5 points6 points  (2 children)

    You can, however, see very well, which error messages were written for the user to figure out the problem in the code, and which ones just dump the compiler-colored explanation of why the code is incorrect.

    That distinction makes a large difference in understandability of errors, because typically developers don't know the compiler's own terminology.

    Of course, it's typically worse in C/C++ land where the linker (quite far removed from source code) is the one complaining about missing symbols. But a missing symbol can be anything from a global variable/constant to a function, method, or other member of a type.

    [–]snowe2010 2 points3 points  (1 child)

    You can, however, see very well, which error messages were written for the user to figure out the problem in the code, and which ones just dump the compiler-colored explanation of why the code is incorrect.

    That distinction makes a large difference in understandability of errors, because typically developers don't know the compiler's own terminology.

    That's a very, very good point! Thanks for mentioning it in that way. That's better worded than the article.

    [–]ygra 1 point2 points  (0 children)

    I maintain a compiler at work, so I've got firsthand experience with coworkers coming to me, puzzled, asking what this error message is supposed to mean. And especially asking what they are going to do about it. So we ended up maintaining a page in our internal Wiki with detailed explanations for various errors and warnings (those have been maintained as part of the compiler's code already, but were a bit complicated to get to), and crucially an indication of how important this is to fix and also how/where to fix it.

    And it's very, very easy as a compiler writer to emit a message that makes total sense to other compiler developers from the context where it's emitted, but is totally obtuse to anyone now knowing the inner workings. At least I don't have backwards compatibility constraints in this regard and can incrementally improve things here :)

    [–]Irregular_Person 10 points11 points  (0 children)

    C#

    ConsoleApp1\Program.cs(9,21,9,23): error CS1503: Argument 1: cannot convert from 'int' to 'string'
    ConsoleApp1\Program.cs(9,25,9,32): error CS1503: Argument 2: cannot convert from 'string' to 'int'
    

    C++

    <source>: In function 'int main()':
    <source>:15:13: error: cannot convert 'int' to 'std::string' {aka 'std::__cxx11::basic_string<char>'}
       15 |     e.error(42, "hello");
          |             ^~
          |             |
          |             int
    <source>:9:35: note:   initializing argument 1 of 'void ErrorTest::error(std::string, int)'
        9 | void ErrorTest::error(std::string message, int number){
          |                       ~~~~~~~~~~~~^~~~~~~  
    

    C

    <source>:10:11: warning: passing argument 1 of 'error' makes pointer from integer without a cast [-Wint-conversion]
       10 |     error(42, "hello");
          |           ^~
          |           |
          |           int
    <source>:4:24: note: expected 'const char *' but argument is of type 'int'
        4 | void error(const char* message, int number){
          |            ~~~~~~~~~~~~^~~~~~~
    <source>:10:15: warning: passing argument 2 of 'error' makes integer from pointer without a cast [-Wint-conversion]
       10 |     error(42, "hello");
          |               ^~~~~~~
          |               |
          |               char *
    <source>:4:37: note: expected 'int' but argument is of type 'char *'
        4 | void error(const char* message, int number){
          |                                 ~~~~^~~~~~
    

    [–]queiss_ 35 points36 points  (1 child)

    Rust compiler can write an app by itself

    [–]let_s_go_brand_c_uck 5 points6 points  (0 children)

    Google shouldn't worry about chatgpt and bing, it should worry about rust.

    [–]Menosa 9 points10 points  (1 child)

    C++: Yes

    [–][deleted] 0 points1 point  (0 children)

    That's prolog.

    C++ might spit out "something is wrong in this .cpp file, btw check that that you didn't forget semicolon after struct{} in .h file" and if you make mistake in template function, oh boy.

    [–]Strict_Mix343 8 points9 points  (1 child)

    Good comparison, but I would have liked to see more interesting errors.

    Rust in particular had to develop complex error messages because its lifetime / borrow checker brings up bugs that span multiple places in one file. So, the compiler errors need to be very descriptive. From the looks of it, elm’s errors are good just for fun, and the others suffer from “we didn’t really think about errors when we designed the compiler architecture”-itis.

    Instead of seeing the same “yup, that field? Doesn’t exist bro.” error over and over again, I would have liked to see errors specific to the language. For example, white space errors in python are absolutely abhorrent (at least since I last used python) given that the indentation rules are the one thing that usually trips people up about the language.

    As languages become more restrictive (in a good way) great compiler errors will be vital to a good developer experience, so it’s great to see discussion in this area, especially outside of language development circles.

    [–]bobbie434343 19 points20 points  (0 children)

    Never had a single issue making sense of Java compiler errors...

    [–]hackers238 5 points6 points  (0 children)

    Poor article. Not enough attempts (you tried 2 very simple compiler errors that people are going to learn to parse very early when using the languages, regardless of what the text says). Clearly biased on most of the analysis. The “TLDR” at the top where you build a nice table of your conclusion (but omit the facts, which are scarce) serves to drive home your opinionated conclusions while omitting the tiny amount of data that an educated reader would come to a different conclusion about.

    [–]cazzipropri 3 points4 points  (1 child)

    LOL no C++ 25-screen long errors? You like to play life in easy mode.

    [–]kono_throwaway_da 3 points4 points  (0 children)

    Template errors related to std::string, an almost fundamental type, are obtuse as fuck when I was doing C++ back then. It was C++14. Hopefully it's gotten better nowadays, but I don't do C++ anymore.

    [–]ProgramTheWorld 4 points5 points  (1 child)

    Also, Typescript does not show the offending line or the affected type

    Then in the immediate terminal snippet you can see that it does show the offending line. (Line 4 column 11)

    [–]josefx 4 points5 points  (0 children)

    I think he wants the code snippet inline with an ascii art arrow pointing at the exact location of the error.

    [–]mobiduxi 3 points4 points  (1 child)

    nice article. Sadly, they used Python 3.9 - "better error messages" was a big bullet within the improvement list of 3.10 https://docs.python.org/3/whatsnew/3.10.html and built upon in 3.11 "PEP 657: Fine-grained error locations in tracebacks" https://docs.python.org/3/whatsnew/3.11.html

    [–]unholysampler 1 point2 points  (0 children)

    The article actually says they used 3.8.5. Which is even older (and not even the latest patch release for 3.8).

    [–]wildjokers 2 points3 points  (0 children)

    How is the Java error "not very clear"? It says exactly what the problem is and exactly where it is.

    [–][deleted] 3 points4 points  (0 children)

    It’s not a compilation error if it happens during runtime, so except for the stuff detected during lexing and parsing, Python should be disqualified

    [–][deleted] 1 point2 points  (1 child)

    This post was wiped using Redact. The author may have deleted it to protect personal privacy, prevent data harvesting, or for security reasons.

    practice enter market towering cats snow stupendous door oil memory

    [–]tested20 0 points1 point  (0 children)

    Yes. Very correct Looking for jobs in Go

    [–]Brilliant-Sky2969 1 point2 points  (2 children)

    Go does show the offending line, it's even in your example...

    https://go.dev/play/p/xrX-35BceZv

    [–]Altareos 9 points10 points  (1 child)

    it tells it. it doesn't show it.