Why GAT Lifetime Parameter Need Bound

Why does generic associated type with lifetime parameter needs Self:'a when returned from method with &'a self, but if it was from a type other than Self, there is no lifetime bound required?

trait Foo {
    type Bar<'a>: Sized;

    // Why do I need to add `Self: 'a` to the `Bar` type to make this
    // line compiles? Why can't the `Bar` accepts any life
    fn foo1<'a>(&'a self) -> Self::Bar<'a>;

    // But, I can return Self::Bar<'b> here without specifying anything
    fn foo2<'a, 'b>(&'a self, x: &'b ()) -> Self::Bar<'b>;
    
    // This also doesn't compile. What makes `Self` type different?
    // The error was: "this bound is currently required to ensure that impls have maximum flexibility",
    // What does "maximum flexibility" mean here?
    fn foo3<'a,'b>(&'a self, y: &'b Self) -> Self::Bar<'b>;
}

It's trying to help you avoid situations like this.[1] Without the bound, you have to define the GAT for all lifetimes, which rules out type Bar<'a> = &'a Self when Self is not 'static, because having a reference to a no-longer valid type is not, itself, valid.

You can read more here.

It's not Self specific, either.


  1. It's effectively a lint that you can't disable explicitly, which is a design mistake IMO; you can disable it with a dummy method, as shown in the example. You can see the exact rules/heuristic here. ↩ī¸Ž

1 Like