I have a Warp rejection handler, I'm using it like this,
.recover(handle_rejection)
It's declared like this,
pub async fn handle_rejection(err: Rejection) -> Result<impl warp::reply::Reply, Infallible> {
If both sides of the if
statement are the same type,
if let Some(e) = err.find::<crate::api::error::UserError>() {
Ok(warp::reply::with_status(
warp::reply::reply(),
warp::http::StatusCode::NOT_FOUND,
))
}
else {
Ok(warp::reply::with_status(
warp::reply::reply(),
warp::http::StatusCode::NOT_FOUND,
))
}
Everything works fine, but if change one of those sides to be,
Ok(e.into_response())
It's no longer ok, I get this error on compilation,
error[E0308]: mismatched types
--> src/api.rs:22:8
|
22 | Ok(warp::reply::with_status(
| ____________________^
23 | | warp::reply::reply(),
24 | | warp::http::StatusCode::NOT_FOUND,
25 | | ))
| |_________________^ expected struct `Response`, found struct `WithStatus`
|
I don't understand that though, because that side didn't change, this should still satisfy impl warp::reply::Reply
, what's the problem here?
I've tried different permutation of casting to the trait object explicitly like as warp::reply::Reply
and as &dyn warp::reply::Reply
but they don't work either.
The issue is that
impl Trait
is just a shorthand for some concrete type that implementsTrait
. So this:is the same as this:
Where
SomeConcreteTypeImplementingBar
is determined automatically (Thanks @Jmb for the correction).Although not correct, it might help to think of it as this:
This is not the same, because the user specifies the type
B
, not the function, but it might be helpful for demonstration purposes. The real purpose ofimpl
is to say "I'm going to return some type that implementsBar
, but I won't tell you what that type is".Eventually, Rust has to figure out the concrete type that is being returned. However, consider the following:
What concrete type should the compiler choose? Well, it could either be
One
orTwo
, depending on whatsome_condition
is! In this case, the compiler doesn't know which type to choose, so it throws an error.This is the same error that you're getting. The two arms of your if statement are returning different types, so the compiler is throwing an error, telling you that it expects the type of both arms of the if statement to be either struct
Response
or structWithStatus
. To solve this issue, you can:Reply
that encapsulates both cases, then just return that typewarp
built-in typeBox
your return value. The resulting code would look like this: