问题是impl Trait
只是一些具体的简写
实现的类型Trait
。所以这:
fn foo() -> impl Bar {}
与此相同:
fn foo() -> SomeConcreteTypeImplementingBar {}
Where SomeConcreteTypeImplementingBar
自动确定(感谢@Jmb 的更正)。
虽然不正确,但将其视为以下内容可能会有所帮助:
fn foo<B: Bar>() -> B
This is not一样的,因为用户指定了类型B
,不是函数,但它可能有助于演示目的。真正的目的是impl
就是说“我要回来了some实现的类型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
}
}
编译器应该选择什么具体类型?嗯,也可以是One
or Two
,取决于什么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,
)))
}