Skip to content

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

Description

@Heliozoa

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsAsyncAwait-PolishAsync-await issues that are part of the "polish" areaAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions