rust - 特征边界 `futures::Future<Item=Arc<T>, Error=Box<Error + Send>>: Send` 不满足

标签 rust rust-tokio

我有以下(简化的)代码片段,我正在尝试在 CpuPool 上运行 future :

use futures::{self, Future, IntoFuture};
use std::error;
use futures_cpupool::CpuPool;

pub struct Store<T: 'static + Send + Sync> {
    inner: Arc<StoreInner<T, C, SerDe, P>>,
}

struct StoreInner<T: 'static + Send + Sync> {
    read_thread_pool: CpuPool,
}

impl<T: 'static + Send + Sync> Store<T> {
    pub fn get(self, obj_id: String) -> Box<Future<Item = Arc<T>, Error = Box<error::Error + Send>>>
    where
        T: for<'de> BinaryDeserialize<'de>,
    {
        let latest_version_id =
            futures::future::ok(()).and_then(move |_| self.get_latest_version_id(&obj_id));
        let latest_version = latest_version_id.and_then(
            move |version_id| -> Box<Future<Item = Arc<T>, Error = Box<error::Error + Send>>> {
                self.get_version(&obj_id, version_id)
            },
        );
        Box::new(self.inner.read_thread_pool.spawn(latest_version))
    }
}

但是,当我尝试编译时出现以下错误。

error[E0277]: the trait bound `futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>: std::marker::Send` is not satisfied
   --> src/store/mod.rs:181:46
    |
181 |         Box::new(self.inner.read_thread_pool.spawn(Box::new(latest_version)))
    |                                              ^^^^^ `futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>`
    = note: required because it appears within the type `std::boxed::Box<futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>`
    = note: required because it appears within the type `futures::future::chain::Chain<futures::AndThen<futures::FutureResult<(), std::boxed::Box<std::error::Error + std::marker::Send>>, std::boxed::Box<futures::Future<Item=serde::export::Option<std::string::String>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:177:67: 177:115 self:_, obj_id:_]>, std::boxed::Box<futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:178:56: 180:10 self:_, obj_id:_]>`
    = note: required because it appears within the type `futures::AndThen<futures::AndThen<futures::FutureResult<(), std::boxed::Box<std::error::Error + std::marker::Send>>, std::boxed::Box<futures::Future<Item=serde::export::Option<std::string::String>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:177:67: 177:115 self:_, obj_id:_]>, std::boxed::Box<futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:178:56: 180:10 self:_, obj_id:_]>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<futures::AndThen<futures::AndThen<futures::FutureResult<(), std::boxed::Box<std::error::Error + std::marker::Send>>, std::boxed::Box<futures::Future<Item=serde::export::Option<std::string::String>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:177:67: 177:115 self:_, obj_id:_]>, std::boxed::Box<futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:178:56: 180:10 self:_, obj_id:_]>>`
    = note: required because it appears within the type `std::boxed::Box<futures::AndThen<futures::AndThen<futures::FutureResult<(), std::boxed::Box<std::error::Error + std::marker::Send>>, std::boxed::Box<futures::Future<Item=serde::export::Option<std::string::String>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:177:67: 177:115 self:_, obj_id:_]>, std::boxed::Box<futures::Future<Item=std::sync::Arc<T>, Error=std::boxed::Box<std::error::Error + std::marker::Send>>>, [closure@src/store/mod.rs:178:56: 180:10 self:_, obj_id:_]>>`

代码看起来很无辜,以后的ItemError都是Send。我不知道为什么会出现此错误。

最佳答案

认为这里的问题是 Future 特性不是 Send 只是因为它的 ItemError 都是 Send - 你必须明确指定它。

如果 Future 是一个结构,我认为编译器可以自动派生 Send,但它不是,所以它不能。

我修复了编译错误,并将 + Send 添加到您定义的 Future 类型,现在它可以编译(除了没有 主要功能):

extern crate futures;
extern crate futures_cpupool;

use futures::Future;
use std::error;
use std::sync::Arc;
use futures_cpupool::CpuPool;

pub struct Store {
    inner: Arc<StoreInner>,
}

struct StoreInner {
    read_thread_pool: CpuPool,
}

impl Store {
    pub fn get<T: 'static + Send + Sync>(
        self,
        obj_id: String,
    ) -> Box<Future<Item = Arc<T>, Error = Box<error::Error + Send>> + Send> {
        let latest_version_id =
            futures::future::ok(()).and_then(move |_| self.get_latest_version_id(&obj_id));
        let latest_version =
            latest_version_id
                .and_then(
                    move |version_id| -> Box<
                        Future<Item = Arc<T>, Error = Box<error::Error + Send>> + Send,
                    > { self.get_version(&obj_id, version_id) },
                );
        Box::new(self.inner.read_thread_pool.spawn(latest_version))
    }

    pub fn get_latest_version_id(
        &self,
        obj_id: &String,
    ) -> Box<Future<Item = String, Error = Box<error::Error + Send>> + Send> {
        unimplemented!();
    }

    pub fn get_version<T: 'static + Send + Sync>(
        &self,
        obj_id: &String,
        version_id: String,
    ) -> Box<Future<Item = Arc<T>, Error = Box<error::Error + Send>> + Send> {
        unimplemented!();
    }
}

playground

关于rust - 特征边界 `futures::Future<Item=Arc<T>, Error=Box<Error + Send>>: Send` 不满足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47161109/

相关文章:

generics - 具有泛型的特征的语法

rust - 为什么迭代器的实现在异步上下文中不够通用?

async-await - 为什么 `Box<dyn Sink>` 在使用 Tokio 和实验性异步/等待支持时不实现 `Sink` 特征?

Rust 与 Futures 和 Tokio 并发执行

rust - 借来的值(value)在 Tokio 的 future 中存在的时间不够长

rust - tokio 在 Rust 中加入多个任务

rust - 变量绑定(bind) : moving a &mut or borrowing the referent?

arrays - 将数组从 Julia 发送到 Rust(使用 "ccall")

c++ - 等效于 Rust 的 include_str 的 C++ 宏

for-loop - 将嵌套的 for 循环转换为迭代器