Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing anyhow::Result with std::io::Result

Tags:

rust

Can anyone help me understand why this code compiles fine:

use actix_web::{App, HttpServer};
use anyhow::Result;

mod error;

#[actix_rt::main]
async fn main() -> Result<()> {
    HttpServer::new(|| App::new())
        .bind("127.0.0.1:8080")?
        .run()
        .await?;

    Ok(())
}

while this does't compile:

use actix_web::{App, HttpServer};
use anyhow::Result;

mod error;

#[actix_rt::main]
async fn main() -> Result<()> {
    HttpServer::new(|| App::new())
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

with the error:

error[E0308]: mismatched types
 --> src/main.rs:6:1
  |
6 | #[actix_rt::main]
  | ^^^^^^^^^^^^^^^^^ expected struct `anyhow::Error`, found struct `std::io::Error`
7 | async fn main() -> Result<()> {
  |                    ---------- expected `std::result::Result<(), anyhow::Error>` because of return type
  |
  = note: expected enum `std::result::Result<_, anyhow::Error>`
             found enum `std::result::Result<_, std::io::Error>`
  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

What is fundamentally different between the two examples?

like image 201
Zizheng Tai Avatar asked Jun 07 '20 05:06

Zizheng Tai


2 Answers

The problem is that the second example is returning Result<(), std::io::Error> which is returned by starting the server, whereas the second one is returning Result<(), anyhow::Error> in the form of Ok(()).

The reason the first example works is that the ? operator (or the try! macro) performs a conversion from whatever error is returned to the error of the return type of the function.

From the docs:

In case of the Err variant, it retrieves the inner error. try! then performs conversion using From. This provides automatic conversion between specialized errors and more general ones.

like image 89
Bennett Hardwick Avatar answered Nov 16 '22 04:11

Bennett Hardwick


anyhow::Error implements From<std::error::Error>, but they are not the same thing.

In the first one the ? is taking the std::error::Error from run().await and calling anyhow::Error::from. The second one is not.

Changing the return type of your method to

Result<(), std::error::Error>

fixes the issue.

like image 23
pigeonhands Avatar answered Nov 16 '22 02:11

pigeonhands