FromResidual? not even in the crate I'm using

I am trying to test some sample code I found, but I am getting this error on compile:
error[E0277]: the trait bound (): FromResidual<Result<Infallible, std::io::Error>> is not satisfied

It refers to the line: smol::block_on(async{
I searched and smol doesn't even have FromResidual in its crate anywhere. Help?

This is the sample code:

smol::block_on(async{
        let listener = TcpListener::bind("127.0.0.1:8080").await?;
        let mut incoming = listener.incoming();

        while let Some(stream) = incoming.next().await {
            let mut stream = stream?;
            stream.write_all(b"hello").await?;
        }
        
    });
1 Like

I was able to work around it by not using the ? and just handling those in place. But I would like to be able to propagate and would like to know why this is a problem and a different way to deal with it.

FromResidual is from std: FromResidual in std::ops - Rust.

Here's a simplified example that triggers the same* error:

fn main() {
    async {
        something()?;
    };
}

fn something() -> Result<(), ()> {
    todo!()
}

   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 | |         something()?;
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 a case of a bad error message. Without the future we get a much better one:

fn main() {
    something()?;
}

fn something() -> Result<(), ()> {
    todo!()
}
   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:16
  |
1 | / fn main() {
2 | |     something()?;
  | |                ^ 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

So the issue here is that the future created by the async block returns the unit type (). As you may know, you can only use ? in functions that return a Result or Option (or, as the error message says, another type that implements FromResidual). If we instead make it so the async block returns such a type:

fn main() {
    async {
        something()?;
        Ok(())
    };
}

fn something() -> Result<(), ()> {
    todo!()
}

We get a different error:

   Compiling playground v0.0.1 (/playground)
error[E0282]: type annotations needed
 --> src/main.rs:4:9
  |
4 |         Ok(())
  |         ^^ cannot infer type for type parameter `E` declared on the enum `Result`

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

Now it's complaining that it doesn't know what the error type is. If we annotate the full type of the result:

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

fn something() -> Result<(), ()> {
    todo!()
}

We no longer get any errors.

*You didn't post the full error but I'm assuming this is the same

edit: I thought the error message was confusing enough to warrant an issue and I couldn't find an existing one so I created Improve error message when trying to use `?` in an async block that does not return a FromResidual type · Issue #94944 · rust-lang/rust · GitHub

9 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.