扭曲和响应类型以及特征对象? [英] Warp and response types and trait objects?

查看:27
本文介绍了扭曲和响应类型以及特征对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 Warp 拒绝处理程序,我正在使用它,

I have a Warp rejection handler, I'm using it like this,

.recover(handle_rejection)

声明如下,

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

如果if语句两边的类型相同,

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

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

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?

我已经尝试了不同的转换到 trait 对象的显式转换,比如 as warp::reply::Reply&dyn warp::reply::Reply 但它们也不起作用.

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.

推荐答案

问题在于 impl Trait 只是一些具体的简写实现 Trait 的类型.所以这个:

The issue is that impl Trait is just a shorthand for some concrete type that implements Trait. So this:

fn foo() -> impl Bar {}

与此相同:

fn foo() -> SomeConcreteTypeImplementingBar {}

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

Where SomeConcreteTypeImplementingBar is determined automatically (Thanks @Jmb for the correction).

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

Although not correct, it might help to think of it as this:

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

相同,因为用户指定类型B,而不是函数,但它可能有助于演示目的.impl 的真正目的是说我将返回实现 Barsome 类型,但我不会告诉你那种类型是什么".

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 of impl is to say "I'm going to return some type that implements Bar, but I won't tell you what that type is".

最终,Rust 必须找出返回的具体类型.但是,请考虑以下事项:

Eventually, Rust has to figure out the concrete type that is being returned. However, consider the following:

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 是什么!在这种情况下,编译器不知道选择哪种类型,因此会抛出错误.

What concrete type should the compiler choose? Well, it could either be One or Two, depending on what some_condition is! In this case, the compiler doesn't know which type to choose, so it throws an error.

这与您遇到的错误相同.if 语句的两个分支返回不同的类型,因此编译器抛出错误,告诉您它期望 if 语句的两个分支的类型为 struct Response 或 struct WithStatus.要解决此问题,您可以:

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 struct WithStatus. To solve this issue, you can:

  • 创建一个实现Reply的新类型,封装这两种情况,然后返回该类型
  • 重新设计您的函数以仅使用一种类型.上面的选项是这种情况的一种,但您也可以使用 warp 内置类型
  • Box 你的返回值.生成的代码如下所示:
  • Create a new type that implements Reply that encapsulates both cases, then just return that type
  • Rework your function to only use one type. The above option is one case of this, but you could also use a warp built-in type
  • Box your return value. The resulting code would look like this:
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,
    )))
}

这篇关于扭曲和响应类型以及特征对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆