我有一个函数可以返回具有User
特征的将来。我有两个具体的实现:AnonymousUser
和BaseUser
。要获得BaseUser
,在身份验证之后,我必须转到数据库并获取该数据库(可能成功也可能不会成功),然后以正确的类型返回新的Future。我已经尝试了以下(playground):
extern crate futures; // 0.1.23
extern crate rand; // 0.5.4
use futures::future::{ok, Future};
use std::io::Error;
trait User {}
#[derive(Debug)]
struct AnonymousUser;
impl User for AnonymousUser {}
#[derive(Debug)]
struct BaseUser;
impl User for BaseUser {}
fn fetch_base_user() -> impl Future<Item = BaseUser, Error = Error> {
ok(BaseUser)
}
fn run_future() -> impl Future<Item = impl User, Error = Error> {
match rand::random::<bool>() {
true => fetch_base_user().from_err().then(move |res| match res {
Ok(user) => ok(user),
Err(_) => ok(AnonymousUser),
}),
false => ok(AnonymousUser),
}
}
fn main() {
run_future().and_then(move |user| println!("User {:?}", user));
}
此操作失败,因为返回then
函数需要一个BaseUser
:
error[E0308]: match arms have incompatible types
--> src/main.rs:23:62
|
23 | true => fetch_base_user().from_err().then(move |res| match res {
| ______________________________________________________________^
24 | | Ok(user) => ok(user),
25 | | Err(_) => ok(AnonymousUser),
| | ----------------- match arm with an incompatible type
26 | | }),
| |_________^ expected struct `BaseUser`, found struct `AnonymousUser`
|
= note: expected type `futures::FutureResult<BaseUser, _>`
found type `futures::FutureResult<AnonymousUser, _>`
我尝试强制返回类型:
use futures::future::FutureResult;
fn run_future() -> impl Future<Item=impl User, Error=Error> {
match rand::random::<bool>() {
true => fetch_base_user().from_err().then(move |res| ->
FutureResult<impl User, Error> { // Forcing the result type here
match res {
Ok(user) => ok(user),
Err(_) => ok(AnonymousUser),
}
}),
false => ok(AnonymousUser),
}
}
失败,并显示以下信息:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:27:22
|
27 | FutureResult<impl User, Error> { // Forcing the result type here
| ^^^^^^^^^
我尝试使用Box
es返工,几乎可以工作(playground)
fn run_future() -> impl Future<Item = Box<impl User>, Error = Error> {
match rand::random::<bool>() {
true => fetch_base_user()
.from_err()
.then(move |res| -> FutureResult<Box<User>, Error> {
match res {
Ok(user) => ok(Box::new(user) as Box<User>),
Err(_) => ok(Box::new(AnonymousUser) as Box<User>),
}
}),
false => ok(Box::new(AnonymousUser) as Box<User>),
}
}
失败
error[E0308]: match arms have incompatible types
--> src/main.rs:22:5
|
22 | / match rand::random::<bool>() {
23 | | true => fetch_base_user().from_err().then(move |res| match res {
24 | | Ok(user) => ok(Box::new(user) as Box<User>),
25 | | Err(_) => ok(Box::new(AnonymousUser) as Box<User>),
26 | | }),
27 | | false => ok(Box::new(AnonymousUser) as Box<User>),
| | ---------------------------------------- match arm with an incompatible type
28 | | }
| |_____^ expected struct `futures::Then`, found struct `futures::FutureResult`
|
= note: expected type `futures::Then<futures::future::FromErr<impl futures::Future, _>, futures::FutureResult<std::boxed::Box<User>, _>, [closure@src/main.rs:23:51: 26:10]>`
found type `futures::FutureResult<std::boxed::Box<User>, _>`
所以我想这只是强制将两者设为相同的结果类型
答案 0 :(得分:0)
最后,来自shepmaster的评论引导我通过另一个问题进行了回复:How do I conditionally return different types of futures?
基本上使用Either :: A和Either :: B解决了此问题。如果没有将参数装箱,我仍然无法使其正常工作,但这可能是一个不同的问题。