扭曲和反应类型以及特征对象



我有一个Warp拒绝处理程序,我这样使用它,

.recover(handle_rejection)

它是这样宣布的,

pub async fn handle_rejection(err: Rejection) -> Result<impl warp::reply::Reply, Infallible> {

如果if语句的两边都是同一类型,则

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,
))
}

一切都很好,但如果改变其中一方,

Ok(e.into_response())

这已经不好了,我在编译时遇到了这个错误,

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`
|

我不明白,因为那一边没有改变,这应该仍然满足impl warp::reply::Reply,这里有什么问题?

我尝试过不同的置换,将trait对象显式地转换为as warp::reply::Reply&dyn warp::reply::Reply,但它们都不起作用。

问题是impl Trait只是一些具体的缩写实现Trait的类型。所以这个:

fn foo() -> impl Bar {}

与此相同:

fn foo() -> SomeConcreteTypeImplementingBar {}

其中SomeConcreteTypeImplementingBar是自动确定的(感谢@Jmb的更正(。

虽然不正确,但这样想可能会有所帮助:

fn foo<B: Bar>() -> B

这与不同,因为用户指定的类型是B,而不是函数,但它可能有助于演示。CCD_ 9的真正目的是说";我将返回一些实现Bar类型,但我不会告诉您该类型是什么;。

最终,Rust必须找出要返回的具体类型。但是,请考虑以下内容:

trait Bar {}
struct One;
impl Bar for One {}
struct Two;
impl Bar for Two {}
fn foo() -> impl Bar {
if some_condition {
One
} else {
Two
}
}

编译器应该选择什么具体类型?好吧,它可能是OneTwo,这取决于some_condition是什么!在这种情况下,编译器不知道该选择哪种类型,因此会抛出一个错误。

这和你遇到的错误是一样的。if语句的两臂返回不同的类型,因此编译器抛出一个错误,告诉您它希望if语句两臂的类型为结构Response或结构WithStatus。要解决此问题,您可以:

  • 创建一个实现Reply的新类型,该类型封装了这两种情况,然后只返回该类型
  • 对函数进行返工,使其仅使用一种类型。上面的选项就是一种情况,但您也可以使用warp内置类型
  • Box您的退货价值。生成的代码如下所示:
pub async fn handle_rejection(err: Rejection) -> Result<Box<dyn warp::reply::Reply>, Infallible> {
if let Some(e) = err.find::<crate::api::error::UserError>() {
Ok(Box::new(e.into_response()))
} else {
Ok(Box::new(warp::reply::with_status(
warp::reply::reply(),
warp::http::StatusCode::NOT_FOUND,
)))
}

最新更新