【问题标题】:*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely with serde::de::DeserializeOwned struct*mut (dyn std::ops::Fn() + 'static)` 不能使用 serde::de::DeserializeOwned 结构在线程之间安全共享
【发布时间】:2020-06-20 08:14:40
【问题描述】:

我正在尝试将Iced (UI framework based on The Elm Architecture)Reqwest (wrapper over hyper) 一起使用,后者可以使用Serde for JSON deserialisation

它们独立地工作正常,但我是 Rust 新手,我的实现有些问题。

我从(正在进行的)网络功能开始。

#[derive(Deserialize, Debug, Clone)]
pub(crate) enum Error {
    APIError,
    ParseError,
}

impl From<reqwest::Error> for Error {
    fn from(error: reqwest::Error) -> Self {
        Error::APIError
    }
}

pub(crate) async fn post<T>(request: Request) -> Result<T, Error>
where
    T: DeserializeOwned + Debug + Clone,
{
    let headers = standard_headers(request.params);
    let response = Client::new()
        .post(&format!("{}{}", request.base, request.path))
        .json(&request.body)
        .headers(headers)
        .send()
        .await?
        .json::<T>()
        .await?;

    Ok(response)
}

我尝试将它用作 Iced 的一部分:

fn new() -> (Runner, Command<Message>) {
    (
        Runner::Loading,
        Command::perform(post(Login::request()), Message::Next),
    )
}

我收到以下编译错误:

error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
  --> src/feature/runner/runner.rs:42:13
   |
42 |             Command::perform(post(Login::request()), Message::Next),
   |             ^^^^^^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
   | 
  ::: <snip>/futures/src/command/native.rs:29:22
   |
29 |         future: impl Future<Output = T> + 'static + Send,
   |                      ------------------ required by this bound in `iced_futures::command::native::Command::<T>::perform`
   |
   = help: within `core::fmt::Void`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`

我认为问题与在 post 中使用 T: DeserializeOwned and life times 相关,因此所有权是这样的,async fn post 中的 T 类型可能与 Command 中的异步调用位于不同的线程上(因此提到Send

答案甚至可能在终身链接中,但我还没有足够的知识来看到它或知道我的想法是否在正确的地方。我调试回只使用具体类型而不是 T ,它可以工作。

我很想了解为什么会出现这个问题以及我可以做些什么来解决它。

提前致谢!

【问题讨论】:

标签: rust async-await serde reqwest


【解决方案1】:

这个提示:

help: within `core::fmt::Void`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`

让我觉得整个问题与您在fn post 中使用format! 有关(请参阅https://github.com/rust-lang/rust/issues/64960)。尝试升级您的 rust 编译器或在长 .await 链之前移出 url:

let url = format!("{}{}", request.base, request.path);
let response = Client::new()
    .post(&url)
    // ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多