Hacker News new | ask | show | jobs
by lhnz 3738 days ago
I would like it to say something like "Either the trait `core::fmt::Debug` is not implemented for the type `T`, or it is implemented but the compiler does not know about it in this context."

Not sure if that is the language I would use, but that is what I want it to say. Suggesting that I might be able to solve the problem by providing more information to the compiler would help me realise how I could solve the problem.

I've had similar problems when developing Rust code, and I wonder whether they would be happy to accept changes to their error messages?

My biggest difficulties trying to understand Rust error messages were either with lifetimes or errors emanating from within macros (it is very hard to see what is failing when you have never seen the code itself.)

2 comments

Interesting. I'd read that code as "For all T, if we have a Buffer<T>, print out the Vec<T>'s elements" and it makes sense that this doesn't work. It isn't that the compiler doesn't know about it, but that T is not constrained within the form to something printable and consequently you can't print it. It would seem more confusing if it had indeed worked, since that would mean (in a semantic sense) that T is auto-constrained to the types that are actually used as T, so you can't reason about the code having the T on its own but only within the context of the larger form.

Not arguing or anything about what error messages are valid. I just found your perspective about the "compiler not knowing" interesting and felt like sharing this.

Ah, you are right. It's not so much that the compiler doesn't know something, but that the compiler does know something: T could have been an non-printable type. You are being protected against panics that might have resulted from passing vectors of non-printable types in.

I still think the error message could be a lot better, as the word 'implementation' is confusing. What's happened here is that Buffer was being used in a for-loop as if it always contained printable types, when actually there was no assurance that this was the case.

Edit: Highly recommend reading the comments of the two people that responded to me, as they're both more correct and more helpful while I was trying to work things out as I wrote my comments.

In fact noting pretty much what you wrote in the first paragraph would improve it a lot: below the initial error message (above the expansion stuff) it could note

    requires that "i" implements Debug, but

    src/x/mod.rs:15 impl<T> Info for Buffer<T> {
    does not specify that T must be Debug

    hint: you can bound T to Debug:

        impl <T> Info for Buffer<T> where T: Debug {

    this means the code will only work with types which implements Debug, 
    but lets you use Debug operations in your methods
Worse, the rest of the error message gives completely the wrong direction for this error case, it gives an advice for a concrete type T, not for a generic one.
> You are being protected against panics that might have resulted from passing vectors of non-printable types in.

Not quite. Rust's generics are instantiated statically - the compiler generates code specific to the type parameters passed in. The compiler must handle cases where it could not find a conforming function implemented for that the type, otherwise no code can be generated. Without the use of traits to constrain types you could get around this by printing a stack trace of the instantiation, but that causes even worse error messages - ie. the ones you see coming from C++ compilers.

  >  I wonder whether they would be happy to accept changes to their error messages?
We have a special tag just for this in the issue tracker, and care a lot about diagnostics. Please report confusing errors if you see them, and patches are even better.

People seem to be _really_ split about Rust's current errors: I've heard, in the same day, "Rust has the worst error messages" and "Rust has the best error messages". Trying to figure out how to get the former camp into the latter.

> I've heard, in the same day, "Rust has the worst error messages" and "Rust has the best error messages".

Which probably means there's a steep learning curve to them, but they are really useful and informative after that initial learning period is over. If so, tread carefully lest you ruin the latter by catering to much to the former problem.

Is it possible to have error messages that work for everyone? Is there a fundamental difference between what the former group want out of an error message and what the latter group want?
That's what I am trying to figure out. I have a hunch that it may be correlated with language background.

That's usually why I'm always asking for specifics when people make general complaints, I'm trying to dig into the _why_. "Error messages are bad" isn't actionable; "error messages are bad because" often is. This thread was already getting into specifics before I woke up, though :)