首页 > 解决方案 > 在 oneshot 通道中使用“DeserializedOwned”特征:对象安全错误

问题描述

以下代码:

trait ClientResponse: DeserializeOwned + Send + Sized {}

struct ClientMsg {
    ...
    resp: oneshot::Sender<Box<dyn ClientResponse>>
}

async fn client_thread(rx: mpsc::Receiver<ClientMsg>, client: reqwest::Client, base_url: Url) -> Result<(), Box<dyn Error>> {
    while let Some(msg) = rx.recv().await {
        ...
        let response = client.get(url).send().await?.json().await?;
        msg.resp.send(response);
    }
}

失败并出现错误:

error[E0038]: the trait `ClientResponse` cannot be made into an object
  --> src/main.rs:16:11
   |
16 |     resp: oneshot::Sender<Box<dyn ClientResponse>>
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ClientResponse` cannot be made into an object
   |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
  --> src/main.rs:12:23
   |
12 | trait ClientResponse: DeserializeOwned + Send + Sized {}
   |       --------------  ^^^^^^^^^^^^^^^^          ^^^^^ ...because it requires `Self: Sized`
   |       |               |
   |       |               ...because it requires `Self: Sized`
   |       this trait cannot be made into an object...

如您所见,我Sized在阅读编译器错误后尝试将该特征添加为超级特征,但它仍然给我同样的错误。我不确定如何解决这个问题,因为我想要一个可以将响应反序列化为发送者决定的类型的客户端线程。

标签: asynchronousrustserderust-tokio

解决方案


有一个专门用于使 serde 特征对象安全的 crate,称为erased-serde


推荐阅读