Skip to content

"the following other types implement trait" needs improvement. #103822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mejrs opened this issue Nov 1, 2022 · 5 comments
Open

"the following other types implement trait" needs improvement. #103822

mejrs opened this issue Nov 1, 2022 · 5 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@mejrs
Copy link
Contributor

mejrs commented Nov 1, 2022

tl;dr: this help message is pretty bad, and needs work. See some prior discussion at #102752

Let me begin with some examples:

Examples

Showing completely unrelated impls

pub fn foo() -> Result<u8, u8> {
    let i = 42_i32;
    Ok(i).into()
}
error[E0277]: the trait bound `Result<u8, u8>: From<Result<i32, _>>` is not satisfied
 --> src/main.rs:4:5
  |
4 |     Ok(i).into()
  |     ^^^^^ ---- required by a bound introduced by this call
  |     |
  |     the trait `From<Result<i32, _>>` is not implemented for `Result<u8, u8>`
  |
  = help: the following other types implement trait `From<T>`:
            <Result<miniz_oxide::MZStatus, miniz_oxide::MZError> as From<&miniz_oxide::StreamResult>>
            <Result<miniz_oxide::MZStatus, miniz_oxide::MZError> as From<miniz_oxide::StreamResult>>
  = note: required for `Result<i32, _>` to implement `Into<Result<u8, u8>>`

For more information about this error, try `rustc --explain E0277`.

Showing hundreds of impls

42_u8 >> "blah"
error[E0277]: no implementation for `u8 >> &str`
 --> src/main.rs:2:7
  |
2 | 42_u8 >> "blah"
  |       ^^ no implementation for `u8 >> &str`
  |
  = help: the trait `Shr<&str>` is not implemented for `u8`
  = help: the following other types implement trait `Shr<Rhs>`:
            <&'a i128 as Shr<i128>>
            <&'a i128 as Shr<i16>>
            <&'a i128 as Shr<i32>>
            <&'a i128 as Shr<i64>>
            <&'a i128 as Shr<i8>>
            <&'a i128 as Shr<isize>>
            <&'a i128 as Shr<u128>>
            <&'a i128 as Shr<u16>>
          and 568 others

For more information about this error, try `rustc --explain E0277`.

Cryptic bounds and types

fn a() -> Result<i32, ()> {
    Err(5)?
}
error[E0277]: `?` couldn't convert the error to `()`
 --> src/lib.rs:2:11
  |
1 | fn a() -> Result<i32, ()> {
  |           --------------- expected `()` because of this
2 |     Err(5)?
  |           ^ the trait `From<{integer}>` is not implemented for `()`
  |
  = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
  = help: the following other types implement trait `FromResidual<R>`:
            <Result<T, F> as FromResidual<Result<Infallible, E>>>
            <Result<T, F> as FromResidual<Yeet<E>>>
  = note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>`

For more information about this error, try `rustc --explain E0277`.

Discussion

Now, lets look at what these "help" messages tend to have in common:

  • they take up a lot of space (especially the second example) and look pretty noisy.
  • they require significant effort to parse. To get to "does this look like what I need?" you have to read the message, understand what the mentioned types are and how it might fit in your code. All these things are much harder if you're not familiar with Rust.
  • they're more often than not completely useless
  • if they're useless, you have to mentally discard all this information you've just loaded.
  • because they're usually useless, they introduce fatigue. I don't even look at these anymore, unless I can see at a glance that they're simple like in the case of
   = help: the following other types implement trait `Pattern<'a>`:
             &'b String
             &'b [char; N]
             &'b [char]
             &'b str
             &'c &'b str
             [char; N]
             char

but these cases are fairly rare.

Discussion

Do you agree this is a problem, and what can we do about it?

@mejrs mejrs added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 1, 2022
@kpreid
Copy link
Contributor

kpreid commented Nov 2, 2022

Idea: if the list of possible impls is very long, as in the Shr example, don't show it at all (unless some other heuristic can trim it down by some kind of relevance). The logic here is that if there are many impls, then it is very unlikely a relevant one will be at the top of the truncated list, and the user would be better served by consulting the trait's documentation (which shows all implementations and may have guidance).

The cost of this is that the user would not get the hint "typical impls of this trait look like this", which is occasionally useful, but I think it's a worthwhile tradeoff.

@tgross35
Copy link
Contributor

Would it be possible to somehow show what types do implement it, maybe with a flag or something?

When there are 500 types like the example, this info clearly isn't all that useful. But when there are only a handful of possibilities

    = help: the following other types implement trait `RxpoTxpo`:
              (NoneT, Pad0, NoneT, NoneT)
              (NoneT, Pad0, Pad2, NoneT)
              (NoneT, Pad0, Pad2, Pad3)
              (Pad0, NoneT, NoneT, NoneT)
              (Pad0, NoneT, Pad2, NoneT)
              (Pad0, NoneT, Pad2, Pad3)
              (Pad1, NoneT, NoneT, NoneT)
              (Pad1, NoneT, Pad2, NoneT)
            and 10 others

Come on compiler, show me the options and I'll pick the one I meant!

@tgross35
Copy link
Contributor

tgross35 commented Jan 23, 2023

I know this will never happen, but it would be really awesome to be able to optionally look up the full info that the compiler has about some error messages, especially any that don't fit in the screen now

$ cargo c
...
error[E0277]: the trait bound `(Pad0, Pad1, NoneT, NoneT): RxpoTxpo` is not satisfied [id: 36afd9]

$ cargo show-id 36afd9
[full message, context, help, hints, list of available traits - whatever the compiler knows]

@chorman0773
Copy link
Contributor

chorman0773 commented Feb 2, 2023

I wrote a macro for indexing a tuple using a constant (instead of a literal) that gives an amazing error like this when going out of bounds:
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=99058d44da46eb62b9d08f49b8c44cf6

New WR, btw: 812 other impls. PB attempts to follow. Update: I was able to get it up to just shy of 9k.

@dragomang87
Copy link

Idea: if the list of possible impls is very long, as in the Shr example, don't show it at all (unless some other heuristic can trim it down by some kind of relevance). The logic here is that if there are many impls, then it is very unlikely a relevant one will be at the top of the truncated list, and the user would be better served by consulting the trait's documentation (which shows all implementations and may have guidance).

The cost of this is that the user would not get the hint "typical impls of this trait look like this", which is occasionally useful, but I think it's a worthwhile tradeoff.

I disagree, what if a user still gets the missing implementation error even though according to the documentation it looks like it should exist? Enabling to see the whole list with some optioin/flag/switch can help understand the problem (e.g. wrong version or some technicality about a generic in question). After having checked the documentation, it would still be nice to be able to confirm that the implementation does not exist or that the implementation that is supposed to be used indeed exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants