Lifetime problem with serde and GAT

I'm trying to use Generic Associated Types in structure that derive serde::Deserialize.

trait Trait {
    type Gat<'a>;
}

struct Foo;

impl Trait for Foo {
    type Gat<'a> = &'a str;
}

struct Goo;

impl Trait for Goo {
    type Gat<'a> = String;
}

#[derive(serde::Deserialize)]
struct A<'a> {
    x: <Foo as Trait>::Gat<'a>, // lifetime may not live long enough consider adding the following bound: `'de: 'a`
    y: <Goo as Trait>::Gat<'a>, // this one is OK
}

#[derive(serde::Deserialize)]
struct B<'a> {
    x: &'a str, // no problem when inlined
}

(playground)

The field A::x got an error :

lifetime may not live long enough consider adding the following bound: `'de: 'a`

but A::y which type doesn't use the lifetime and B::x which is "inlined" have no error.

Is the problem from GAT or serde ?

I tried using cargo expand and it seem the problem is from serde :

impl<'de, 'a> _serde::Deserialize<'de> for A<'a> {
// ...
impl<'de: 'a, 'a> _serde::Deserialize<'de> for B<'a> {

I open an issue here.

The latter. If you expand macros, you'll see

        impl<'de, 'a> _serde::Deserialize<'de> for A<'a> {
// ...
        impl<'de: 'a, 'a> _serde::Deserialize<'de> for B<'a> {
// Similarly for `Visitor`

If you add the bound manually, it compiles.

#[derive(serde::Deserialize)]
#[serde(bound = "'de: 'a")]
struct A<'a> {
    x: <Foo as Trait>::Gat<'a>,
    y: <Goo as Trait>::Gat<'a>,
}
1 Like

Interesting, I didn't know it was possible to manually set the bounds. ty !

Arguably the behavior intentional as the bound isn't needed if the associated types don't use the lifetime.

I found in the serde docs an explanation and solution to the problem here.

#[serde(borrow)] must be used on field to explicitly borrow.