Skip to content

Improve E0599 for missing trait bounds (where clauses) #61661

Closed

Description

@djc

For the following example:

struct Foo<T> {
    t: T,
}

struct Inner {
    i: u8,
}

trait Bar {
    fn bar(&self);
}

impl<T> Bar for Foo<T> where T: Clone {
    fn bar(&self) {
        println!("x");
    }
}

fn main() {
    let foo = Foo { t: Inner { i: b'i' } };
    foo.bar();
}

The error message is:

error[E0599]: no method named `bar` found for type `Foo<Inner>` in the current scope
  --> src/main.rs:21:9
   |
1  | struct Foo<T> {
   | ------------- method `bar` not found for this
...
21 |     foo.bar();
   |         ^^^
   |
   = note: the method `bar` exists but the following trait bounds were not satisfied:
           `Foo<Inner> : Bar`
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `bar`, perhaps you need to implement it:
           candidate #1: `Bar`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

Foo<T> does actually implement Bar, and this makes the suggestions from the compiler misleading in this case: there is already an implementation for Foo<T> : Bar, and Bar is already in scope. It would be much more helpful if the compiler could suggest the trait bounds necessary to satisfy the requirement.

This seems very similar to what @estebank suggested in #9082 (comment).

Activity

  1. changed the title [-]E0599[/-] [+]Improve E0599 for missing trait bounds (where clauses)[/+] on Jun 8, 2019
  2. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jun 8, 2019
  3. added
    A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    on Nov 15, 2019
  4. estebank commented on Feb 18, 2020

    @estebank
    Contributor

    Would the following be enough of an improvement?

    error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
       --> file5.rs:21:9
        |
    1   |   struct Foo<T> {
        |   ------------- method `bar` not found for this
    ...
    21  |       foo.bar();
        |           ^^^ method not found in `Foo<Inner>`
        |
        = note: the method `bar` exists but the following trait bounds were not satisfied:
                `Inner: std::clone::Clone` which is required by `Foo<Inner>: Bar`
        = help: items from traits can only be used if the trait is implemented and in scope
        = note: the following trait defines an item `bar`, perhaps you need to implement it:
                candidate #1: `Bar`
    
  5. djc commented on Feb 18, 2020

    @djc
    ContributorAuthor

    This is a great improvement! In this context, the latter three lines are somewhat confusing:

        = help: items from traits can only be used if the trait is implemented and in scope
        = note: the following trait defines an item `bar`, perhaps you need to implement it:
                candidate #1: `Bar`
    

    Since they actually don't apply for this case.

    Also, it might help to elaborate the lines before that, maybe an explicit mention of <Foo<Inner> as Bar>::bar() can be thrown in?

  6. estebank commented on Feb 18, 2020

    @estebank
    Contributor

    What do you think of the following output?

    error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
      --> file5.rs:21:9
       |
    1  | struct Foo<T> {
       | ------------- method `bar` not found for this
    ...
    5  | struct Inner {
       | ------------ this type doesn't satisfy the bound `std::clone::Clone`
    ...
    21 |     foo.bar();
       |         ^^^ method not found in `Foo<Inner>`
       |
       = note: the method `bar` exists but the following trait bounds were not satisfied:
               `Inner: std::clone::Clone`
       = help: items from traits can only be used if the trait is implemented and in scope
       = note: the following trait defines an item `bar`, perhaps you need to implement it:
               candidate #1: `Bar`
    

    Screen Shot 2020-02-18 at 12 05 00 AM

    I'll look into removing the last few lines as I agree that they are somewhat misleading here and obscure the solution, but we have to make sure we don't actually hide information useful for other cases with different underlying problems.

  7. djc commented on Feb 18, 2020

    @djc
    ContributorAuthor

    Yeah, this would be even better. I still think it would be nice to specifically call out Bar somewhere/somehow as the provider of bar() and the implementer specifying the trait bound (though it doesn't need the full location treatment).

  8. estebank commented on Feb 18, 2020

    @estebank
    Contributor

    What about this?

    error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
      --> file5.rs:24:9
       |
    1  | struct Foo<T> {
       | ------------- method `bar` not found for this
    ...
    5  | struct Inner {
       | ------------ the method `bar` but this type doesn't satisfy the bound `Inner: std::clone::Clone`
    ...
    9  | trait Bar {
       | --------- this trait defines an item `bar`
    ...
    24 |     foo.bar();
       |         ^^^ method not found in `Foo<Inner>`
       |
       = help: items from traits can only be used if the trait is implemented and in scope
    
  9. djc commented on Feb 18, 2020

    @djc
    ContributorAuthor

    I find the four separate span blocks a bit distracting. I would opt for something like this:

    error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
      --> file5.rs:24:9
       |
    1  | struct Foo<T> {
       | ------------- method `bar` not found for this
    ...
    5  | struct Inner {
       | ------------ this type doesn't satisfy the bound `Inner: std::clone::Clone`
       |
       = note: the method `bar` exists but the following trait bounds were not satisfied:
               `Inner: std::clone::Clone` which is required by `Foo<Inner>: Bar`
       = help: items from traits can only be used if the trait is implemented and in scope
    

    On the other hand, a span block pointing to the impl Bar for Foo<Inner> might be useful.

  10. estebank commented on Feb 19, 2020

    @estebank
    Contributor

    The current output in the PR looks like this

    error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
      --> file5.rs:21:9
       |
    1  | struct Foo<T> {
       | -------------
       | |
       | method `bar` not found for this
       | doesn't satisfy `Foo<Inner>: Bar`
    ...
    5  | struct Inner {
       | ------------ doesn't satisfy `Inner: std::clone::Clone`
    ...
    9  | trait Bar {
       | --------- `Bar` defines an item `bar`, perhaps you need to implement it
    ...
    21 |     foo.bar();
       |         ^^^ method not found in `Foo<Inner>`
       |
       = note: the method `bar` exists but the following trait bounds were not satisfied:
               `Inner: std::clone::Clone` which is required by `Foo<Inner>: Bar`
       = help: items from traits can only be used if the trait is implemented and in scope
    

    I'm a bit hesitant about removing spans at this point. It might be true that changing it to the following could be a good idea, but I'm not sure:

    error[E0599]: no method named `bar` found for struct `Foo<Inner>` in the current scope
      --> file5.rs:21:9
       |
    1  | struct Foo<T> {
       | ------------- method `bar` not found for this
    ...
    5  | struct Inner {
       | ------------ doesn't satisfy `Inner: std::clone::Clone`
    ...
    21 |     foo.bar();
       |         ^^^ method not found in `Foo<Inner>`
       |
       = note: the method `bar` exists but the following trait bounds were not satisfied:
               `Inner: std::clone::Clone` which is required by `Foo<Inner>: Bar`
       = help: items from traits can only be used if the trait is implemented and in scope
       = note: the following trait defines an item `bar`, perhaps you need to implement it:
               candidate #1: `Bar`
    
  11. djc commented on Feb 20, 2020

    @djc
    ContributorAuthor

    Let's see if we can get some wisdom from the crowd.

  12. added 2 commits that reference this issue on Feb 27, 2020
    4524657
    88f66f1
  13. added a commit that references this issue on Feb 29, 2020
    55aee8d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`D-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions