Skip to content

Confusing error from an incorrect return; in async block #95055

@spaarmann

Description

@spaarmann

This code compiles without errors:

async fn foo() -> Result<(), Box<dyn std::error::Error>> {
    async {
        Err(anyhow!("oh no"))?;
        Ok(())
    }.await
}

Adding a return; in the middle of the async block makes this code wrong

async fn foo() -> Result<(), Box<dyn std::error::Error>> {
    async {
        Err(anyhow!("oh no"))?;
        return;
        Ok(())
    }.await
}

and rustc correctly produces an error. Playground link
However, the error is very confusing:

error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
  --> src/lib.rs:27:30
   |
26 |       async {
   |  ___________-
27 | |         Err(anyhow!("oh no"))?;
   | |                              ^ cannot use the `?` operator in an async block that returns `()`
28 | |         return;
29 | |         Ok(())
30 | |     }.await
   | |_____- this function should return `Result` or `Option` to accept `?`
   |
   = help: the trait `FromResidual<Result<Infallible, anyhow::Error>>` is not implemented for `()`

error[E0308]: mismatched types
  --> src/lib.rs:29:9
   |
29 |         Ok(())
   |         ^^^^^^ expected `()`, found enum `Result`
   |
   = note: expected type `()`
              found enum `Result<(), _>`
note: return type inferred to be `()` here
  --> src/lib.rs:27:9
   |
27 |         Err(anyhow!("oh no"))?;
   |         ^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/lib.rs:26:5
   |
26 | /     async {
27 | |         Err(anyhow!("oh no"))?;
28 | |         return;
29 | |         Ok(())
30 | |     }.await
   | |___________^ expected enum `Result`, found `()`
   |
   = note:   expected enum `Result<(), Box<(dyn std::error::Error + 'static)>>`
           found unit type `()`
help: try adding an expression at the end of the block
   |
30 ~     }.await;
31 +     Ok(())
   |

It simultaneously complains in the first error that the ? is invalid because the async block returns () and then in the next error it says that it inferred the return type to be () because of that ?.

Ideally the compiler could figure out based on the return type of the function that the return; is the problem here, but at the very least it would be good to not point at the Err(...)? line as the reason for the return type being inferred as ().

Tested on stable 1.59 and nightly 1.61 (2022-03-16).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions