'Mixing anyhow::Result with std::io::Result
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?
Solution 1:[1]
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.
Solution 2:[2]
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.
Solution 3:[3]
You can use the same conversion that anyhow
uses:
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.map_err(anyhow::Error::from)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Bennett Hardwick |
Solution 2 | pigeonhands |
Solution 3 | Caleb Hattingh |