Почему Result нельзя рассматривать как будущее, даже если оно реализует IntoFuture? - PullRequest
0 голосов
/ 30 октября 2018

std::result::Result реализует IntoFuture, но следующий код не компилируется:

extern crate futures; // 0.1.25

use futures::{future::Either, prelude::*, sync::mpsc};

fn example() -> impl Future<Item = (), Error = ()> {
    let (tx, rx) = mpsc::channel(0);
    let data = Some(1);
    match data {
        Some(d) => Either::A(tx.send(d).and_then(|x| Ok(())).map_err(|e| ())),
        None => Either::B(Ok(()) as Result<(), ()>),
    }
}

Полное сообщение об ошибке:

error[E0277]: the trait bound `std::result::Result<(), ()>: futures::Future` is not satisfied
 --> src/lib.rs:5:17
  |
5 | fn example() -> impl Future<Item = (), Error = ()> {
  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `futures::Future` is not implemented for `std::result::Result<(), ()>`
  |
  = note: required because of the requirements on the impl of `futures::Future` for `futures::future::Either<futures::MapErr<futures::AndThen<futures::sink::Send<futures::sync::mpsc::Sender<{integer}>>, std::result::Result<(), futures::sync::mpsc::SendError<{integer}>>, [closure@src/lib.rs:9:50: 9:60]>, [closure@src/lib.rs:9:70: 9:76]>, std::result::Result<(), ()>>`
  = note: the return type of a function must have a statically known size

Более того, IntoFuture не требует Sized. Почему Result<(), ()> здесь нельзя трактовать как Future? 1017 *

1 Ответ

0 голосов
/ 30 октября 2018

Either реализует Future только тогда, когда оба его потомка реализуют Future и их типы выстраиваются в линию:

impl<A, B> Future for Either<A, B>
where
    A: Future,
    B: Future<Item = A::Item, Error = A::Error>, 

Result не не реализует Future, поэтому размещение Result непосредственно внутри Either также не будет реализовывать Future.

Черта IntoFuture ортогональна Future. Как указано в документации:

Эта черта очень похожа на черту IntoIterator и предназначена для очень похожего использования.

Вы не можете вызвать Iterator::map на Vec (vec![1, 2, 3].map(...)), даже если Vec реализует IntoIterator, и та же логика применима к Result / Future / IntoFuture.


Большую часть времени вы захотите использовать futures::ok:

extern crate futures; // 0.1.25

use futures::{
    future::{self, Either},
    prelude::*,
    sync::mpsc,
};

fn example() -> impl Future<Item = (), Error = ()> {
    let (tx, _) = mpsc::channel(0);
    let data = Some(1);
    match data {
        Some(d) => Either::A(tx.send(d).map(|_| ()).map_err(|_| ())),
        None => Either::B(future::ok(())),
    }
}

Вы также можете позвонить into_future напрямую:

Either::B(Ok(()).into_future())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...