Ошибка компиляции с tokio :: run () и маркером отправки - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь создать библиотеку, определяющую общий источник данных, который может извлекать данные из различных источников, синхронно и асинхронно.При создании асинхронной части я столкнулся со следующей проблемой компиляции, которую я не понимаю, как ее решить:

Вот мой упрощенный код ( ссылка на игровую площадку )

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<...>, то это сработает ( ссылка на игровую площадку для нового кода );пока я не понимаю, что не так с чертой и реализацией 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);
}

1 Ответ

0 голосов
/ 27 сентября 2018

Похоже, мне просто нужно было изменить сигнатуру функции на

fn read_async(
    &self,
    _: Option<HashMap<String, Value>>,
) -> Box<Future<Item = Option<Self::Data>, Error = String> + Send> {
//                                                        ^^^^^^^

Действительно, Box<T> должно быть Send, когда T равно Send, но я должен объяснить это, потому чтоFuture не получает его вручную / автоматически.

Спасибо Тобз за указание на это.

...