serde icon indicating copy to clipboard operation
serde copied to clipboard

Why "The 'de lifetime should not appear in the type to which the Deserialize impl applies"?

Open grelative opened this issue 2 years ago • 11 comments

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.

grelative avatar Mar 17 '22 04:03 grelative

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.

Mingun avatar Mar 17 '22 04:03 Mingun

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> {}

grelative avatar Mar 17 '22 14:03 grelative