1

我有一个函数可以返回具有User特征的未来。我有它的两个具体实现:AnonymousUserBaseUser. 要获得BaseUser,在身份验证之后,我必须去数据库并获取它,这可能成功也可能不成功,并以正确的类型返回新的未来。我尝试了以下(操场):

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

我尝试使用Boxes 返工返工,这几乎奏效了(操场

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

所以我想这只是迫使两者成为相同的结果类型的问题

4

1 回答 1

2

最后,shepmaster 的评论让我通过另一个问题得到了回应:我如何有条件地返回不同类型的期货?

基本上使用 Either::A 和 Either::B 解决了这个问题。如果不对参数进行装箱,我仍然无法使其工作,但这可能是一个不同的问题。

于 2018-09-02T20:19:36.457 回答