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

First complains on wrong types and wrong arguments count and then complains that the function doesn't exist #106929

Closed
safinaskar opened this issue Jan 16, 2023 · 5 comments · Fixed by #112100
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

@safinaskar
Copy link
Contributor

safinaskar commented Jan 16, 2023

Code

// Here is (somewhat) minimal reproducer extracted from actual code
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1dd13c8cc5daee9cb6a14c5ee5cdefac

/*async fn post(client: &reqwest::Client, key: &ring::hmac::Key, body: &[(String, String)]) -> Result<String, Box<dyn std::error::Error>> {
    todo!();
}*/

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();
    let key = ring::hmac::Key::new(todo!(), todo!());
    post(&client, &key, &[
        ("".to_owned(), "".to_owned()),
    ]).await?;
    return Ok(());
}

Current output

Compiling playground v0.0.1 (/playground)
warning: unreachable expression
 --> src/main.rs:8:45
  |
8 |     let key = ring::hmac::Key::new(todo!(), todo!());
  |                                    -------  ^^^^^^^ unreachable expression
  |                                    |
  |                                    any code following this expression is unreachable
  |
  = note: `#[warn(unreachable_code)]` on by default
  = note: this warning originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `&Key: IntoUrl` is not satisfied
    --> src/main.rs:9:5
     |
9    | /     post(&client, &key, &[
10   | |         ("".to_owned(), "".to_owned()),
11   | |     ]).await?;
     | |______^ the trait `IntoUrl` is not implemented for `&Key`
     |
     = help: the following other types implement trait `IntoUrl`:
               &'a String
               &'a str
               String
               Url
note: required by a bound in `reqwest::Client::post`
    --> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.11.13/src/async_impl/client.rs:1431:20
     |
1431 |     pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
     |                    ^^^^^^^ required by this bound in `reqwest::Client::post`

error[E0061]: this function takes 1 argument but 2 arguments were supplied
    --> src/main.rs:9:5
     |
9    |       post(&client, &key, &[
     |  _____^^^^________________-
10   | |         ("".to_owned(), "".to_owned()),
11   | |     ]).await?;
     | |_____- argument of type `&[(String, String); 1]` unexpected
     |
note: associated function defined here
    --> /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/reqwest-0.11.13/src/async_impl/client.rs:1431:12
     |
1431 |     pub fn post<U: IntoUrl>(&self, url: U) -> RequestBuilder {
     |            ^^^^
help: remove the extra argument
     |
9    |     post(&key)(&client, &key, &[
     |         ++++++

error[E0425]: cannot find function `post` in this scope
 --> src/main.rs:9:5
  |
9 |     post(&client, &key, &[
  |     ^^^^ not found in this scope
  |
help: use the `.` operator to call the method `post` on `&reqwest::Client`
  |
9 ~     (&client).post(&key, &[
10+         ("".to_owned(), "".to_owned()),
11~     ]).await?;
  |

error[E0277]: `reqwest::RequestBuilder` is not a future
  --> src/main.rs:11:7
   |
9  | /     post(&client, &key, &[
10 | |         ("".to_owned(), "".to_owned()),
11 | |     ]).await?;
   | |      -^^^^^^
   | |      ||
   | |      |`reqwest::RequestBuilder` is not a future
   | |______|help: remove the `.await`
   |        this call returns `reqwest::RequestBuilder`
   |
   = help: the trait `Future` is not implemented for `reqwest::RequestBuilder`
   = note: reqwest::RequestBuilder must be a future or must implement `IntoFuture` to be awaited
   = note: required for `reqwest::RequestBuilder` to implement `IntoFuture`

Some errors have detailed explanations: E0061, E0277, E0425.
For more information about an error, try `rustc --explain E0061`.
warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` due to 4 previous errors; 1 warning emitted

Desired output

I think errors should be in other order

Rationale and extra context

Provided code is minimal reproducer extracted from actual code from my project.

In some point I had function post in my code called from main. But then I commented post and forgot about that. Then I run compiler and saw these very strange error messages. I usually read compiler errors from begin to end. The first error said that I have no &Key: IntoUrl satisfied. This is very strange. Why I should have &Key: IntoUrl satisfied? I stared at this very strange error for some time. And then I decided to see other error messages. And then I suddenly saw error message (at 3rd place) that post is not defined at all! At this moment I understood that post is commented (remember: my actual code is big, so it is easy to miss this).

So, the problem is so: rustc is simply too smart. Rustc should simply complain that post is not defined. But rustc goes further and "fixes" it and then complains that post is called with wrong number of arguments and that bounds are not satisfied. And moreover rustc gives error messages in wrong order: first complains that traits are not satisfied and argument number is wrong and then complains that there is no post at all!

Remember: I usually read first error message only and ignore the rest.

Rustc version is 1.66.1 stable

Other cases

No response

Anything else?

No response

@safinaskar safinaskar 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 Jan 16, 2023
@estebank
Copy link
Contributor

I think this might be due to the desugaring of the tokio::main function having another post in scope, somehow.

@safinaskar
Copy link
Contributor Author

@estebank , I removed async, await and tokio::main and still get the same:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3396e6c9c3c23ab0bb0ace82d0c50bd3

@safinaskar
Copy link
Contributor Author

Here is even more reduced example:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=280eb0724ca62630ccae7666153e97fc

struct Client;

impl Client {
    fn post<T: std::ops::Add>(&self, _: T, _: T) {}
}

fn f() {
    let c = Client;
    post(c, ());
}

@estebank
Copy link
Contributor

Ok, now I see. What's happening is that the E0425 is recovering a resolution error for post not existing and assuming that you meant c.post. When this guess is correct, the spurious errors are talking about fixes that the fixed code will need, but in your case the guess was incorrect, making the errors nonsensical. It should be easy to silence further errors by avoiding the recovery always and let subsequent compilations produce accurate errors.

Noratrieb added a commit to Noratrieb/rust that referenced this issue May 30, 2023
Don't typecheck recovered method call from suggestion

Only make the use-dot-operator-to-call-method suggestion, but do not double down and use the recovered type to perform method call typechecking as it will produce confusing diagnostics relevant for the *fixed* code.

### Code Sample

```rust
struct Client;

impl Client {
    fn post<T: std::ops::Add>(&self, _: T, _: T) {}
}

fn f() {
    let c = Client;
    post(c, ());
}
```

### Before This PR

```
error[[E0277]](https://doc.rust-lang.org/stable/error_codes/E0277.html): cannot add `()` to `()`
 --> src/lib.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^^^^^^^^ no implementation for `() + ()`
  |
  = help: the trait `Add` is not implemented for `()`
note: required by a bound in `Client::post`
 --> src/lib.rs:4:16
  |
4 |     fn post<T: std::ops::Add>(&self, _: T, _: T) {}
  |                ^^^^^^^^^^^^^ required by this bound in `Client::post`

error[[E0061]](https://doc.rust-lang.org/stable/error_codes/E0061.html): this function takes 2 arguments but 1 argument was supplied
 --> src/lib.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^ an argument of type `()` is missing
  |
note: method defined here
 --> src/lib.rs:4:8
  |
4 |     fn post<T: std::ops::Add>(&self, _: T, _: T) {}
  |        ^^^^                   -----  ----  ----
help: provide the argument
  |
9 |     post((), ())(c, ());
  |         ++++++++

error[[E0425]](https://doc.rust-lang.org/stable/error_codes/E0425.html): cannot find function `post` in this scope
 --> src/lib.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^ not found in this scope
  |
help: use the `.` operator to call the method `post` on `&Client`
  |
9 -     post(c, ());
9 +     c.post(());
  |

Some errors have detailed explanations: E0061, E0277, E0425.
For more information about an error, try `rustc --explain E0061`.
```

### After This PR

```
error[E0425]: cannot find function `post` in this scope
 --> tests/ui/typeck/issue-106929.rs:9:5
  |
9 |     post(c, ());
  |     ^^^^ not found in this scope
  |
help: use the `.` operator to call the method `post` on `&Client`
  |
9 -     post(c, ());
9 +     c.post(());
  |

error: aborting due to previous error

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

Fixes rust-lang#106929.
@bors bors closed this as completed in cc12182 May 30, 2023
@safinaskar
Copy link
Contributor Author

Yes, the bug is fixed

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

Successfully merging a pull request may close this issue.

2 participants