tokio::run() 和发送标记的编译错误
Compilation error with tokio::run() and Send marker
我正在尝试构建一个定义通用数据源的库,该数据源可以同步和异步地从各种来源提取数据。
在构建异步部分时,我 运行 遇到了以下我不知道如何解决的编译问题:
这是我的简化代码 (playground link)
extern crate futures; // futures = "0.1.24"
extern crate tokio; // tokio = "0.1.8"
extern crate serde_json;
use futures::Future;
use serde_json::Value;
use std::collections::HashMap;
trait DataSource {
type Data;
fn read_async(&self, Option<HashMap<String, Value>>) -> Box<futures::Future<Item=Option<Self::Data>, Error=String>>
where Self::Data: 'static + Send;
}
struct DataSourceImpl;
impl DataSource for DataSourceImpl {
type Data = Vec<String>;
fn read_async(&self, _params: Option<HashMap<String, Value>>) -> Box<futures::Future<Item=Option<Self::Data>, Error=String>>
where Self::Data: 'static + Send
{
Box::new(futures::future::ok(Some(vec!["some data".to_string()])))
}
}
fn main() {
let datasource = DataSourceImpl{};
let params = HashMap::new();
tokio::run(datasource.read_async(Some(params))
.map(|content| {
println!("Content read = {:?}", &content);
()
})
.map_err(|err| {
println!("Error {}", &err);
()
})
);
}
我得到以下编译错误:
error[E0277]: `dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>` cannot be sent between threads safely
--> src/main.rs:45:13
|
45 | runtime.spawn(future);
| ^^^^^ `dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>`
= note: required because it appears within the type `std::boxed::Box<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>`
= note: required because it appears within the type `futures::Map<std::boxed::Box<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>, [closure@src/main.rs:34:14: 37:10]>`
= note: required because it appears within the type `futures::MapErr<futures::Map<std::boxed::Box<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>, [closure@src/main.rs:34:14: 37:10]>, [closure@src/main.rs:38:18: 41:10]>`
然而,在查看标准库时,我发现了以下实现:
impl<T: ?Sized> Send for Box<T> where T: Send
impl<T> Send for Option<T> where T: Send
impl<T> Send for Vec<T> where T: Send
impl Send for String
impl Send for [failure::]Error
我错过了什么?
如果我去掉这个特征并将 Box<Future<...>>
替换为 impl Future<...>
那么它就可以工作 (playground link for the new code);但是我不明白特征和 Box
实现有什么问题...
extern crate failure;
extern crate futures; // futures = "0.1.24"
extern crate tokio; // tokio = "0.1.8"
extern crate serde_json;
use futures::Future;
use serde_json::Value;
use std::collections::HashMap;
fn read_async(_params: Option<HashMap<String, Value>>) -> impl futures::Future<Item=Option<Vec<String>>, Error=failure::Error> {
futures::future::ok(Some(vec!["some data".to_string()]))
}
fn main() {
let params = HashMap::new();
let future = read_async(Some(params))
.map(|content| {
println!("Content read = {:?}", &content);
()
})
.map_err(|err| {
println!("Error {}", &err);
()
});
tokio::run(future);
}
看来我只需要将函数签名更改为
fn read_async(
&self,
_: Option<HashMap<String, Value>>,
) -> Box<Future<Item = Option<Self::Data>, Error = String> + Send> {
// ^^^^^^^
确实,当T
是Send
时,Box<T>
应该是Send
,但我必须拼写出来,因为Future
没有导出它manually/automatically.
感谢 Tobz 指出这一点。
我正在尝试构建一个定义通用数据源的库,该数据源可以同步和异步地从各种来源提取数据。 在构建异步部分时,我 运行 遇到了以下我不知道如何解决的编译问题:
这是我的简化代码 (playground link)
extern crate futures; // futures = "0.1.24"
extern crate tokio; // tokio = "0.1.8"
extern crate serde_json;
use futures::Future;
use serde_json::Value;
use std::collections::HashMap;
trait DataSource {
type Data;
fn read_async(&self, Option<HashMap<String, Value>>) -> Box<futures::Future<Item=Option<Self::Data>, Error=String>>
where Self::Data: 'static + Send;
}
struct DataSourceImpl;
impl DataSource for DataSourceImpl {
type Data = Vec<String>;
fn read_async(&self, _params: Option<HashMap<String, Value>>) -> Box<futures::Future<Item=Option<Self::Data>, Error=String>>
where Self::Data: 'static + Send
{
Box::new(futures::future::ok(Some(vec!["some data".to_string()])))
}
}
fn main() {
let datasource = DataSourceImpl{};
let params = HashMap::new();
tokio::run(datasource.read_async(Some(params))
.map(|content| {
println!("Content read = {:?}", &content);
()
})
.map_err(|err| {
println!("Error {}", &err);
()
})
);
}
我得到以下编译错误:
error[E0277]: `dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>` cannot be sent between threads safely
--> src/main.rs:45:13
|
45 | runtime.spawn(future);
| ^^^^^ `dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>`
= note: required because it appears within the type `std::boxed::Box<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>`
= note: required because it appears within the type `futures::Map<std::boxed::Box<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>, [closure@src/main.rs:34:14: 37:10]>`
= note: required because it appears within the type `futures::MapErr<futures::Map<std::boxed::Box<dyn futures::Future<Item=std::option::Option<std::vec::Vec<std::string::String>>, Error=std::string::String>>, [closure@src/main.rs:34:14: 37:10]>, [closure@src/main.rs:38:18: 41:10]>`
然而,在查看标准库时,我发现了以下实现:
impl<T: ?Sized> Send for Box<T> where T: Send
impl<T> Send for Option<T> where T: Send
impl<T> Send for Vec<T> where T: Send
impl Send for String
impl Send for [failure::]Error
我错过了什么?
如果我去掉这个特征并将 Box<Future<...>>
替换为 impl Future<...>
那么它就可以工作 (playground link for the new code);但是我不明白特征和 Box
实现有什么问题...
extern crate failure;
extern crate futures; // futures = "0.1.24"
extern crate tokio; // tokio = "0.1.8"
extern crate serde_json;
use futures::Future;
use serde_json::Value;
use std::collections::HashMap;
fn read_async(_params: Option<HashMap<String, Value>>) -> impl futures::Future<Item=Option<Vec<String>>, Error=failure::Error> {
futures::future::ok(Some(vec!["some data".to_string()]))
}
fn main() {
let params = HashMap::new();
let future = read_async(Some(params))
.map(|content| {
println!("Content read = {:?}", &content);
()
})
.map_err(|err| {
println!("Error {}", &err);
()
});
tokio::run(future);
}
看来我只需要将函数签名更改为
fn read_async(
&self,
_: Option<HashMap<String, Value>>,
) -> Box<Future<Item = Option<Self::Data>, Error = String> + Send> {
// ^^^^^^^
确实,当T
是Send
时,Box<T>
应该是Send
,但我必须拼写出来,因为Future
没有导出它manually/automatically.
感谢 Tobz 指出这一点。