0

The following code:

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);
    }
}

Fails with error:

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...

As you can see, I tried adding the Sized trait as a super trait after reading the compiler error, but it still gives me the same error. I'm not sure how else to approach this problem, since I want a client thread that can deserialize responses into types decided by the senders.

jeanluc
  • 1,608
  • 1
  • 14
  • 28
  • Please paste the error as text rather than image. That way it will be googlable and much easier to edit. – user4815162342 Feb 20 '21 at 18:43
  • The error has nothing to do with tokio, you just can't make `serde::de::DeserializeOwned` into an object: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2380d6d4e2e752144df1ed9b5d01b8b1. For more information, see the link provided in the compiler's message. – mcarton Feb 20 '21 at 22:12
  • In this case because `DeserializeOwned` nor `Deserialize` have function signatures taking `self` by value or by reference (`static`) you can only use the `trait` as a constraint. – WBuck Feb 21 '21 at 03:54

1 Answers1

0

There is a crate exactly for making serde traits object safe called erased-serde

Hadus
  • 1,551
  • 11
  • 22