Compiler diagnostics improvement wishlist


Syntax errors (previously noted in this thread) are annoying because they cause a cascade of unrelated failures. is a fun one where the borrow error message points to the wrong borrow. had me scratching my head for a while. I suppose my issue was that I didn’t understand (and still only vaguely have an idea) of what was causing the borrow of buffer to last for so long (note that changing from a trait object to a struct fixes it). I haven’t thought about it too much, but something like a ‘breakdown’ mode where the compiler explains the decisions it’s made about a lifetime might be useful?


This issue just caused me a lot of confusion:

error[E0405]: cannot find trait `Hash` in this scope
   --> src/
132 | impl Hash for Person {
    |      ^^^^ not found in this scope
help: possible candidate is found in another module, you can import it into scope
1   | use util::read2::imp::winapi::_core::hash::Hash;

Specifically that last line where it did not suggest std.


My recent trouble:

help: the following trait is implemented but not in scope, perhaps add a `use` for it:
1  | use std::os::ext::ffi::OsStringExt;

So I happily put use std::os::ext::ffi::OsStringExt; where needed only to get this error message:

error[E0433]: failed to resolve. Could not find `ext` in `os`
  --> src/
37 |         use std::os::ext::ffi::OsStringExt;
   |                      ^^^ Could not find `ext` in `os`

warning: unused import: `std::os::ext::ffi::OsStringExt`
   --> src/
37 |         use std::os::ext::ffi::OsStringExt;
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: #[warn(unused_imports)] on by default

error[E0599]: no function or associated item named `from_vec` found for type `std::ffi::OsString` in the current scope


    help: the following trait is implemented but not in scope, perhaps add a `use` for it:
1  | use std::os::ext::ffi::OsStringExt;

Which is quite ridiculous.

This was confusing too:

error[E0308]: mismatched types
  --> src/
26 |                         Err(_) => true,
   |                         ^^^^^^ expected struct `std::vec::Vec`, found enum `std::result::Result`
   = note: expected type `std::vec::Vec<u8>`
              found type `std::result::Result<_, _>`

I don’t remember how I solved this (I found it in terminal output), so I have no idea what the problem was.

Also, sometimes compiler prints out helpful “did you mean?” message and sometimes it doesn’t even if it probably could if it tried harder (looking into more modules). Ideally I could write use Whatever and get the list of all valid imports.


The errors that result from having multiple versions of a crate can be quite inscrutable.

A nice one I got today:

29 |         ReadBincode::new(new_inner(channel))
   |         ^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::boxed::Box<bincode::ErrorKind>>` is not implemented for `my_module::Error`
   = help: the following implementations were found:
             <my_module::Error as std::convert::From<std::io::Error>>
             <my_module::Error as std::convert::From<std::boxed::Box<bincode::ErrorKind>>>
   = note: required by `<tokio_serde_bincode::ReadBincode<T, U>>::new`

Edit: in fact, that’s part of a more general complaint about namespacing: namespacing in errors is done on a rather blanket basis, which can be a bit unhelpful.

On the one hand if you have only one Result (or OsStringExt) in scope it can make errors unreadable to refer to it as std::result::Result (resp. std::os::ext::ffi::OsStringExt) once the types get big — often to understand an error message I have to paste it into a new emacs buffer and manually remove a lot of the namespacing and format the types across multiple lines so I can see what’s actually going on.

On the other hand, in cases like the above where there are multiple things with the same name being referred to, it would be nice to have the types and traits prefixed by their crate and version — if the error read, for example,

29 |         ReadBincode::new(new_inner(channel))
   |         ^^^^^^^^^^^^^^^^ the trait `From<Box<bincode[0.8]::ErrorKind>>` is not implemented for `Error`
   = help: the following implementations were found:
             <Error as From<io::Error>>
             <Error as From<Box<bincode[0.9]::ErrorKind>>>
   = note: required by `ReadBincode<T, U>::new`

(using the shorthand module names that are in scope where possible) the cause of the error becomes immediately clear.


Thank you for all the replies. I’m glad to see that most of the responses are for things already in the backlog, which means that we’re already making progress towards fixing them. This feedback is invaluable to allow us to focus our efforts.

For future reference, some tickets to follow:





@abreis: I know there’s a ticket but can’t find it. Diagnostics try to show you the code as it appears in the file as much as possible. I find the idea of reformatting the code for some diagnostics (like this one) interesting. It’ll probably be lower in priority as I feel there’re lower hanging fruit that need to be addressed, but it’s definitely worth exploring.



@Twey:, needs some coordination with cargo.

Feel free to keep them coming!


One thing that I brought up in my answer (which was a bit rambling, sorry) was the possibility of a flag to only give the first error. Does that exist? I don’t see it mentioned here.


There’s no way at the moment to show only one error. I feel though that a better approach would be to reduce the amount of incorrect errors that are emitted (like ignoring type checking blocks that have had parse errors, and recover more gracefully in the parser).

We’ve had discussions with @nikomatsakis about using a pager for all output, but we haven’t yet reached a decision as not everybody is happy with the idea, so it would have to have a way to configure it (a flag at minimum, adding a config file would be best).

I’ve looked at what would be required to do so and it required changing the way diagnostics are emitted (right now they’re going straight to stdout, they would have to go to a buffer). This wouldn’t be a tremendous amount of work, but it just requires somebody to put in the time to do it :blush: .


Today I saw a beginner get confused with the module system because he declared a module as pub mod foo { } and had a file with the real content. Linting on .rs files that are not actually modules would be helpful.


Thanks! That ticket (, however, describes a slightly different situation (to_owned on double reference returns a single reference instead of an owned value) than the one I was concerned with (to_owned on single reference to an unclonable value returns a single reference instead of an owned value). From user standpoint the way to fix these two is different (don’t double reference / dereference first to get single ref vs. implement Clone for the value), so it makes sense for the diagnostics and help messages to consider them separate too. Should I file another ticket?


Yes! Go ahead. Please include a repro case and as much context on the type of output you would prefer to see.


Show the source of the type for type deduction:

If this program is just a little bit longer, it’s pretty much impossible to tell that the failure comes because of the return Err(&str) instead of return Err(String)