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 doesn'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?
The problem is that the second example is returning Result<(), std::io::Error>
which is returned by starting the server, whereas the first 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.