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 Traitis just a shorthand for some concrete type that implementsTrait. So this:is the same as this:
Where
SomeConcreteTypeImplementingBaris 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 ofimplis 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
OneorTwo, depending on whatsome_conditionis! 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
Responseor structWithStatus. To solve this issue, you can:Replythat encapsulates both cases, then just return that typewarpbuilt-in typeBoxyour return value. The resulting code would look like this: