Reputation: 377
I'm trying to implement a struct that holds a field which implements two traits:
use meilisearch_sdk::document::Document;
use serde::{Serialize,Deserialize};
trait DeserializableDocument<'a>: Deserialize<'a> + Document{}
#[derive(Serialize, Deserialize, Debug)]
pub struct KafkaMessage<'a, DeserializableDocument>{
Data: &'a DeserializableDocument,
}
Where the following struct would satisfy Data
:
#[derive(Serialize, Deserialize, Debug)]
pub struct User {
ID: String,
Firstname: String,
Lastname: String,
}
impl Document for User {
type UIDType = String;
fn get_uid(&self) -> &Self::UIDType { &self.ID }
}
However upon trying to define the empty trait object DeserializableDocument
I get the following error:
type annotations needed
cannot infer type for type parameter `Self`
note: cannot satisfy `Self: <my-project>::documents::_::_serde::Deserialize<'a>`
[dependencies]
serde = { version="1.0", features = ["derive"] }
meilisearch-sdk = "0.15"
What is the correct way to approach this?
When restructured according to @ChayimFriedman answer and @SebastianRedl comment:
#[derive(Serialize, Deserialize, Debug)]
pub struct KafkaMessage<D> where D: Document {
Data: D,
}
I get the following compiler error:
type annotations needed for `std::option::Option<D>`
consider giving `__field1` the explicit type `std::option::Option<D>`, where the type parameter `D` is specified
Ofcourse, specifying D: Option<D>
doesn't resolve it either.
Upvotes: 3
Views: 1717
Reputation: 71440
Document
already includes the Self: DeserializeOwned
bound, and DeserializeOwned
is basically for<'a> Deserialize<'a>
(and also has this bound). So you basically requested the compiler to satisfy:
trait DeserializableDocument<'a>: Deserialize<'a> + for<'b> Deserialize<'b> {}
Or, generalized:
trait Trait<'a> {}
trait Foo<'a>: Trait<'a> + for<'b> Trait<'b> {}
error[E0283]: type annotations needed
--> src/lib.rs:2:16
|
2 | trait Foo<'a>: Trait<'a> + for<'b> Trait<'b> {}
| ^^^^^^^^^ cannot infer type for type parameter `Self`
|
= note: cannot satisfy `Self: Trait<'a>`
I don't know why this error happens (it sound trivial to prove that if Edit: this is a compiler bug: #844351, but since Trait<'a>
is implemented for any lifetime 'a
then Trait<'a>
is implemented for some lifetime 'a
)DeserializeOwned
implies any lifetime for Deserialize<'a>
, you can just omit that bound:
trait DeserializableDocument: Document {}
Edit: As for your new error, it is exactly the same reason. The #[derive(Deserialize)]
is expanding to something like:
impl<'de, D> Deserialize<'de> for KafkaMessage<D>
where
D: Document,
D: Deserialize<'de>,
{
// ...
}
Which like we already learn, is essentially the same as:
impl<'de, D> Deserialize<'de> for KafkaMessage<D>
where
D: for<'a> Deserialize<'a>,
D: Deserialize<'de>,
{
// ...
}
And again we see the conflict.
The best advice I can give is to just not put the where
bounds on the struct, but rather on the impl
s. Putting bounds on the struct is a bad idea anyway.
1. Thanks @steffahn for helping to find it out at users.rust-lang.org!
Upvotes: 3