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

Improve error message when trying to use ? in an async block that does not return a FromResidual type #94944

Closed
Heliozoa opened this issue Mar 15, 2022 · 5 comments
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints AsyncAwait-Polish Async-await issues that are part of the "polish" area AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Heliozoa
Copy link
Contributor

Currently, trying to use ? in a function that does not return a compatible type results in a great error message:

fn main() {
    Result::<(), ()>::Ok(())?;
}
Compiling playground v0.0.1 (/playground)
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
 --> src/main.rs:2:29
  |
1 | / fn main() {
2 | |     Result::<(), ()>::Ok(())?;
  | |                             ^ cannot use the `?` operator in a function that returns `()`
3 | | }
  | |_- this function should return `Result` or `Option` to accept `?`
  |
  = help: the trait `FromResidual<Result<Infallible, ()>>` is not implemented for `()`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

However, when the same issue occurs in an async block, the output is not as helpful: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d8fadebcedd4dda50a5377047a6227d7

fn main() {
    async {
        Result::<(), ()>::Ok(())?;
    };
}

The current output is:

Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `(): FromResidual<Result<Infallible, ()>>` is not satisfied
 --> src/main.rs:2:11
  |
2 |       async {
  |  ___________-
3 | |         Result::<(), ()>::Ok(())?;
4 | |     };
  | |     ^
  | |     |
  | |_____the trait `FromResidual<Result<Infallible, ()>>` is not implemented for `()`
  |       required by a bound introduced by this call

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

This is especially unhelpful in the current state of things with FromResidual being an unstable trait with incomplete docs. Ideally the output would look something like:

Compiling playground v0.0.1 (/playground)
error[E0277]: the `?` operator can only be used in a future that returns `Result` or `Option` (or another type that implements `FromResidual`)
 --> src/main.rs:2:11
  |
2 | /     async {
3 | |         Result::<(), ()>::Ok(())?;
  | |                                 ^ cannot use the `?` operator in a future that returns `()`

4 | |     };
  | |_- this future should return `Result` or `Option` to accept `?`
  |
  = help: the trait `FromResidual<Result<Infallible, ()>>` is not implemented for `()`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error

I'm not sure what the proper terminology here is. It might be that the error message should instead of futures talk about async blocks, and/or instead of returning () talk about resolving to (), the output or Output being (), or something else.

This issue was inspired by the URLO post at https://users.rust-lang.org/t/fromresidual-not-even-in-the-crate-im-using/72980

@Heliozoa Heliozoa 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 Mar 15, 2022
@tmandry
Copy link
Member

tmandry commented Apr 8, 2022

@rustbot label A-async-await

@rustbot rustbot added the A-async-await Area: Async & Await label Apr 8, 2022
@nikomatsakis
Copy link
Contributor

The error seems ok for async functions; the bad case is specifically async blocks from what I can tell:

playground

@eholk
Copy link
Contributor

eholk commented Apr 11, 2022

Yeah, this error message could definitely be improved. It seems like a good polish bug for someone to take on. I added it to the async project board.

@rustbot label AsyncAwait-Triaged

@rustbot rustbot added the AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. label Apr 11, 2022
@eholk
Copy link
Contributor

eholk commented Apr 11, 2022

@rustbot label AsyncAwait-Polish

@rustbot rustbot added the AsyncAwait-Polish Async-await issues that are part of the "polish" area label Apr 11, 2022
@kpreid
Copy link
Contributor

kpreid commented Jul 16, 2022

This seems to have been fixed, as 1.64.0-nightly (2022-07-13 87588a2) does produce the custom message with the original repro source:

error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
 --> src/main.rs:3:33
  |
2 |       async {
  |  ___________-
3 | |         Result::<(), ()>::Ok(())?;
  | |                                 ^ cannot use the `?` operator in an async block that returns `()`
4 | |     };
  | |_____- this function should return `Result` or `Option` to accept `?`
  |
  = help: the trait `FromResidual<Result<Infallible, ()>>` is not implemented for `()`

@tmandry tmandry moved this to Done in wg-async work Dec 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-diagnostics Area: Messages for errors, warnings, and lints AsyncAwait-Polish Async-await issues that are part of the "polish" area AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
Status: Done
Development

No branches or pull requests

7 participants