首页 > 解决方案 > *mut (dyn std::ops::Fn() + 'static)` 不能使用 serde::de::DeserializeOwned 结构在线程之间安全共享

问题描述

我正在尝试将Iced(基于 The Elm 架构的 UI 框架)Reqwest(超级包装器)一起使用,它可以使用Serde 进行 JSON 反序列化

它们独立地工作正常,但我是 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)`

我相信这个问题与使用T : DeserializeOwned和.postTasync fn postSend

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

我很想了解为什么会存在这个问题以及我能做些什么来解决它。

提前致谢!

标签: rustasync-awaitserdereqwest

解决方案


这个提示:

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

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

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

推荐阅读