serde
serde copied to clipboard
Why "The 'de lifetime should not appear in the type to which the Deserialize impl applies"?
Serde's documentation about lifetime mentioned this:
The 'de lifetime should not appear in the type to which the Deserialize impl applies.
// Do not do this. Sooner or later you will be sad.
impl<'de> Deserialize<'de> for Q<'de> {
// Do this instead.
impl<'de: 'a, 'a> Deserialize<'de> for Q<'a> {
But didn't give a explanation, I'm curious about what's the drawback of using 'de
as the lifetime of type which Deserialize impl applies.
Probably https://users.rust-lang.org/t/how-to-end-borrow-in-this-code/72719/3?u=mingun can give you an answer:
...
// `&'static [u8]` in particular implements // `for<'any> BufferedInput<'any, ()>` impl<'long: 'short, 'short> BufferedInput<'short, ()> for &'long [u8] { fn read(&mut self, _buf: ()) -> &'short [u8] { self } }
... You may wonder why we had to spell this out, and the answer is that lifetimes in trait parameters are invariant -- they can't automatically shrink, like you're used to with
&[u8]
, say. The above change makes the implementation covariant by breaking up the lifetime of the implemented trait ('short
) and the lifetime of the implementer ('long
) -- every concrete&'long [u8]
gets an implementation for every'short
that is shorter. ...
But I totally agree that such an explanation should be placed in the documentation.
impl<'long: 'short, 'short> BufferedInput<'short, ()> for &'long [u8] { fn read(&mut self, _buf: ()) -> &'short [u8] { self } }
Yeah, this imp of BufferedInput
has the benefit of satisfying the HRTB for<'any> &'static [u8]: BufferedInput<'any, ()>
.
But it does not apply to Deserialize
, there is nothing can represent a lifetime smaller than anyone, so we can not form a HRTB for<'any> Q<'???>: Deserialize<'any>
that the following impl will satisfy.
impl<'de: 'a, 'a> Deserialize<'de> for Q<'a> {}