Skip to content
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

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

Closed
BGR360 opened this issue Sep 2, 2022 · 4 comments · Fixed by #116257
Assignees
Labels
A-associated-items Area: Associated items (types, constants & functions) A-diagnostics Area: Messages for errors, warnings, and lints D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@BGR360
Copy link
Contributor

BGR360 commented Sep 2, 2022

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

@BGR360 BGR360 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 Sep 2, 2022
@rustbot rustbot added A-associated-items Area: Associated items (types, constants & functions) D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. labels Sep 2, 2022
@fishycs
Copy link

fishycs commented Sep 9, 2022

@rustbot claim

@BGR360
Copy link
Contributor Author

BGR360 commented Sep 9, 2022

@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.

@compiler-errors
Copy link
Member

compiler-errors commented Sep 10, 2022

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.

@BGR360
Copy link
Contributor Author

BGR360 commented Sep 11, 2022

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

estebank added a commit to estebank/rust that referenced this issue Sep 29, 2023
Fix rust-lang#101351.

When an associated type on a type parameter is used, and the type
parameter isn't constrained by the correct trait, suggest the
appropriate trait bound:

```
error[E0220]: associated type `Associated` not found for `T`
 --> file.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++
  ```

When an associated type on a type parameter has a typo, suggest fixing
it:

```
error[E0220]: associated type `Baa` not found for `T`
  --> $DIR/issue-55673.rs:9:8
   |
LL |     T::Baa: std::fmt::Debug,
   |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
   |
help: change the associated type name to use `Bar` from `Foo`
   |
LL |     T::Bar: std::fmt::Debug,
   |        ~~~
```
estebank added a commit to estebank/rust that referenced this issue Sep 29, 2023
Fix rust-lang#101351.

When an associated type on a type parameter is used, and the type
parameter isn't constrained by the correct trait, suggest the
appropriate trait bound:

```
error[E0220]: associated type `Associated` not found for `T`
 --> file.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++
  ```

When an associated type on a type parameter has a typo, suggest fixing
it:

```
error[E0220]: associated type `Baa` not found for `T`
  --> $DIR/issue-55673.rs:9:8
   |
LL |     T::Baa: std::fmt::Debug,
   |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
   |
help: change the associated type name to use `Bar` from `Foo`
   |
LL |     T::Bar: std::fmt::Debug,
   |        ~~~
```
estebank added a commit to estebank/rust that referenced this issue Sep 29, 2023
Fix rust-lang#101351.

When an associated type on a type parameter is used, and the type
parameter isn't constrained by the correct trait, suggest the
appropriate trait bound:

```
error[E0220]: associated type `Associated` not found for `T`
 --> file.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++
  ```

When an associated type on a type parameter has a typo, suggest fixing
it:

```
error[E0220]: associated type `Baa` not found for `T`
  --> $DIR/issue-55673.rs:9:8
   |
LL |     T::Baa: std::fmt::Debug,
   |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
   |
help: change the associated type name to use `Bar` from `Foo`
   |
LL |     T::Bar: std::fmt::Debug,
   |        ~~~
```
estebank added a commit to estebank/rust that referenced this issue Sep 29, 2023
Fix rust-lang#101351.

When an associated type on a type parameter is used, and the type
parameter isn't constrained by the correct trait, suggest the
appropriate trait bound:

```
error[E0220]: associated type `Associated` not found for `T`
 --> file.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++
  ```

When an associated type on a type parameter has a typo, suggest fixing
it:

```
error[E0220]: associated type `Baa` not found for `T`
  --> $DIR/issue-55673.rs:9:8
   |
LL |     T::Baa: std::fmt::Debug,
   |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
   |
help: change the associated type name to use `Bar` from `Foo`
   |
LL |     T::Bar: std::fmt::Debug,
   |        ~~~
```
@estebank estebank assigned estebank and unassigned fishycs Sep 29, 2023
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Oct 16, 2023
Suggest trait bounds for used associated type on type param

Fix rust-lang#101351.

When an associated type on a type parameter is used, and the type parameter isn't constrained by the correct trait, suggest the appropriate trait bound:

```
error[E0220]: associated type `Associated` not found for `T`
 --> file.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++
  ```

When an associated type on a type parameter has a typo, suggest fixing
it:

```
error[E0220]: associated type `Baa` not found for `T`
  --> $DIR/issue-55673.rs:9:8
   |
LL |     T::Baa: std::fmt::Debug,
   |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
   |
help: change the associated type name to use `Bar` from `Foo`
   |
LL |     T::Bar: std::fmt::Debug,
   |        ~~~
```
@bors bors closed this as completed in 781e864 Oct 16, 2023
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Oct 16, 2023
Rollup merge of rust-lang#116257 - estebank:issue-101351, r=b-naber

Suggest trait bounds for used associated type on type param

Fix rust-lang#101351.

When an associated type on a type parameter is used, and the type parameter isn't constrained by the correct trait, suggest the appropriate trait bound:

```
error[E0220]: associated type `Associated` not found for `T`
 --> file.rs:6:15
  |
6 |     field: T::Associated,
  |               ^^^^^^^^^^ there is a similarly named associated type `Associated` in the trait `Foo`
  |
help: consider restricting type parameter `T`
  |
5 | struct Generic<T: Foo> {
  |                 +++++
  ```

When an associated type on a type parameter has a typo, suggest fixing
it:

```
error[E0220]: associated type `Baa` not found for `T`
  --> $DIR/issue-55673.rs:9:8
   |
LL |     T::Baa: std::fmt::Debug,
   |        ^^^ there is a similarly named associated type `Bar` in the trait `Foo`
   |
help: change the associated type name to use `Bar` from `Foo`
   |
LL |     T::Bar: std::fmt::Debug,
   |        ~~~
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) A-diagnostics Area: Messages for errors, warnings, and lints D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. D-terse Diagnostics: An error or lint that doesn't give enough information about the problem at hand. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants