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

Error message’s hint pointing entirely at the wrong place. #77677

Closed
steffahn opened this issue Oct 7, 2020 · 2 comments
Closed

Error message’s hint pointing entirely at the wrong place. #77677

steffahn opened this issue Oct 7, 2020 · 2 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@steffahn
Copy link
Member

steffahn commented Oct 7, 2020

Reduced example:

trait TraitF {
    fn f();
}
trait TraitG {
    fn g();
}

struct Foo<T>(T);

impl<T> Foo<T> {
    fn foo() {}
    fn bar() {
        struct Bar<F, T>(F, T);
        impl<F, T> TraitF for Bar<F, T>
        where
            F: FnOnce(T),
        {
            fn f() {}
        }
        impl<F> TraitG for Bar<F>
        where
            F: FnOnce(T),
        {
            fn g() {}
        }
    }
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0401]: can't use generic parameters from outer function
  --> src/lib.rs:22:23
   |
10 | impl<T> Foo<T> {
   |      - type parameter from outer function
...
18 |             fn f() {}
   |                - try adding a local generic parameter in this method instead
...
22 |             F: FnOnce(T),
   |                       ^ use of generic parameter from outer function

error[E0107]: wrong number of type arguments: expected 2, found 1
  --> src/lib.rs:20:28
   |
20 |         impl<F> TraitG for Bar<F>
   |                            ^^^^^^ expected 2 type arguments

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0107, E0401.
For more information about an error, try `rustc --explain E0107`.
error: could not compile `playground`.

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

This came up during refactoring, while I was adding the parameter T to Bar (intentionally named the same as the outer T because they are going to be instantiated to the same type anyways). This kind of error message (the first one, E0401) had me puzzled for some time before figuring out that it was nonsensical. I’m referring to the try adding a local generic parameter in this method instead part. The real code of course was quite a bit longer, making the situation actually confusing, in particular:

  • The try adding ... hint points to the wrong place entirely. It should suggest adding a parameter to the impl TraitG (even though such a suggestion might not always make sense, idk).
  • The type parameter from outer function pointer is also somewhat confusing, since when foo’s body is a few lines and bar is super long and nested, it is quite nontrivial to even figure out that “outer function” refers to bar(). (As in: it is easy to forget that you’re even inside of a function body at all if you’ve been focusing on this Bar struct and it’s impls for a while.) Also... what is the distinction between the words function and method here? (My original code has bar(self) but still called it “outer function”.)

@rustbot modify labels: A-diagnostics, T-compiler, D-confusing, C-bug.

@rustbot rustbot added A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 7, 2020
@Enselic
Copy link
Member

Enselic commented Jul 25, 2023

For reference, the errors now given look like the following:

Compiling playground v0.0.1 (/playground)
error[[E0401]](https://doc.rust-lang.org/stable/error_codes/E0401.html): can't use generic parameters from outer function
  --> src/lib.rs:22:23
   |
10 | impl<T> Foo<T> {
   |      - type parameter from outer function
...
20 |         impl<F> TraitG for Bar<F>
   |              - help: try using a local generic parameter instead: `T,`
21 |         where
22 |             F: FnOnce(T),
   |                       ^ use of generic parameter from outer function

error[[E0107]](https://doc.rust-lang.org/stable/error_codes/E0107.html): struct takes 2 generic arguments but 1 generic argument was supplied
  --> src/lib.rs:20:28
   |
20 |         impl<F> TraitG for Bar<F>
   |                            ^^^ - supplied 1 generic argument
   |                            |
   |                            expected 2 generic arguments
   |
note: struct defined here, with 2 generic parameters: `F`, `T`
  --> src/lib.rs:13:16
   |
13 |         struct Bar<F, T>(F, T);
   |                ^^^ -  -
help: add missing generic argument
   |
20 |         impl<F> TraitG for Bar<F, T>
   |                                 +++

Some errors have detailed explanations: E0107, E0401.
For more information about an error, try `rustc --explain E0107`.
error: could not compile `playground` (lib) due to 2 previous errors

The try adding ... hint points to the wrong place entirely. It should suggest adding a parameter to the impl TraitG (even though such a suggestion might not always make sense, idk).

This seems fixed in latest output?

Also... what is the distinction between the words function and method here? (My original code has bar(self) but still called it “outer function”.)

This seems fixed in latest output?

The type parameter from outer function pointer is also somewhat confusing

This point still stands. Unsure what the best solution is.

@steffahn
Copy link
Member Author

steffahn commented Jul 31, 2023

Thanks for noticing this @Enselic.

It appears like the bug was “accidentally” fixed by changes / simplifications(?) to the suggestion logic, in #99249

I wonder if the code that originally did something wrong for figuring out the source location still exists for any other purposes, or if it’s gone entirely. I would ask for feedback from @cjgillot (:wave:), but I don’t know how much one can remember one year after the PR, and as long as there are no known issues (and this is a diagnostics problem to begin with, only), it’s likely not worth spending any time investigating.

I think I will not keep this issue open for merely the suggestion to add a mention of the actual outer function bar; I can imagine it’d be nicer if the error message would point out bar for example by mentioning its name

error[[E0401]](https://doc.rust-lang.org/stable/error_codes/E0401.html): can't use generic parameters from outer function
  --> src/lib.rs:22:23
   |
10 | impl<T> Foo<T> {
   |      - type parameter from outer function `bar`
...
20 |         impl<F> TraitG for Bar<F>
   |              - help: try using a local generic parameter instead: `T,`
21 |         where
22 |             F: FnOnce(T),
   |                       ^ use of generic parameter from outer function

or perhaps even pointing to it? (Of course only in cases like this where the parameter is from the impl block, which might be somewhat distant from where the function bar itself begins. I’ll consider at a later time whether to open a new enhancement/papercut issue on that point.

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 C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. 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

3 participants