Skip to content

rustc should suggest trait bounds when attempting to use associated items on generic parameters. #101351

Closed

Description

@BGR360

Given the following code (playground):

trait Foo {
    type Associated;
}

struct Generic<T> {
    field: T::Associated,
}

The current output is:

error[E0220]: associated type `Associated` not found for `T`
 --> src/lib.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ associated type `Associated` not found

Ideally the output should look like:

error[E0220]: associated type `Associated` not found for `T`
 --> src/lib.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ associated type `Associated` not found
  |
help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `Associated`, perhaps you need to restrict type parameter `T` with it:
  |
5 | struct Generic<T: Foo> {
  |                 +++++

It already does this for trait methods (playground):

pub trait Foo {
    fn do_it(&self);
}

fn use_it<T>(input: T) {
    input.do_it();
}

fn main() {
    use_it(42);
}
error[E0599]: no method named `do_it` found for type parameter `T` in the current scope
 --> src/main.rs:6:11
  |
6 |     input.do_it();
  |           ^^^^^ method not found in `T`
  |
  = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `do_it`, perhaps you need to restrict type parameter `T` with it:
  |
5 | fn use_it<T: Foo>(input: T) {
  |            +++++

And it does it (sorta, the message is more terse) if you qualify with as Trait (playground):

trait Foo {
    type Associated;
}

struct Generic<T> {
    field: <T as Foo>::Associated,
}
error[E0277]: the trait bound `T: Foo` is not satisfied
 --> src/lib.rs:6:12
  |
6 |     field: <T as Foo>::Associated,
  |            ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++

@rustbot label +D-newcomer-roadblock +D-terse +A-associated-items

Activity

  1. 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 Sep 2, 2022
  2. added
    A-associated-itemsArea: Associated items (types, constants & functions)
    D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.
    D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.
    on Sep 2, 2022
  3. fishycs commented on Sep 9, 2022

    @fishycs

    @rustbot claim

  4. BGR360 commented on Sep 9, 2022

    @BGR360
    ContributorAuthor

    @fishycs and I paired on this today. Didn't really figure out a way forward yet, but here's some breadcrumbs for the next lucky contestant.

    The error message we were originally seeing is produced during astconv in complain_about_assoc_type_not_found:

    err.span_label(span, format!("associated type `{}` not found", assoc_name));

    On nightly (and beta), it seems @compiler-errors came through and improved the message so that it now says:

    error[E0220]: associated type `Associated` not found for `T`
     --> src/lib.rs:6:15
      |
    6 |     field: T::Associated,
      |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
    
    

    This check occurs in the same function, just a few lines above. This is great, but still no suggestion is provided.

    The code that provides the suggestion we'd like to make is in suggest_traits_to_import:

    format!(
    "the following {traits_define} an item `{name}`, perhaps you need to {action} \
    {one_of_them}:",
    traits_define =
    if candidates_len == 1 { "trait defines" } else { "traits define" },
    action = action,
    one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
    name = item_name,

    The only current use of suggest_traits_to_import is when reporting a method error. A cursory look at suggest_traits_to_import makes it seem like it could be used for associated types and associated consts as well, but some of the how it is written assumes it's only used for method errors.

    It seems like this stuff is maybe asking for a larger refactor. Right now trait method errors go through a different path than associated type or associated const errors. I bet it would be cleaner if we could invoke the same "missing associated item" error path in all three cases. Perhaps @compiler-errors or @estebank has ideas or suggestions for how to approach such a refactor, or experience to say why that would be difficult to do.

  5. compiler-errors commented on Sep 10, 2022

    @compiler-errors
    Contributor

    So I think we currently have issues with doing more involved suggestion during this place in astconv because of cycles -- when we're suggesting a "add <T: Trait>" for a method, it's easier to do because that can only happen inside the body of a function, whereas associated types can show up in the signature of an item, which causes issues. I think there are comments that explain this somewhere in astconv, but I can't remember where.

  6. BGR360 commented on Sep 11, 2022

    @BGR360
    ContributorAuthor

    Interesting, okay. What would be an example of one of those "cycles"?

  7. added 4 commits that reference this issue on Sep 29, 2023
    9996c32
    fe67e70
    f7b3ba5
    0608151
  8. added a commit that references this issue on Oct 13, 2023
    781e864
  9. added a commit that references this issue on Oct 16, 2023
    14663e0
  10. added a commit that references this issue on Oct 16, 2023
    dc500e2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-associated-itemsArea: Associated items (types, constants & functions)A-diagnosticsArea: Messages for errors, warnings, and lintsD-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.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