Lifetime in an associated type

#1

I have the exact same question as a 3 year old reddit thread. It has a legitimate answer, but I wanted to ask if anything has changed since then:

I started trying to add a lifetime to my trait as suggested in the post. It ended up proliferating the lifetime to places I’d rather not have to maintain them, so I thought I’d see if anything has changed.

I’m guessing any changes here would depend on generic associated types. My designs have brought me up against a lack of GATs a few times now (especially with iteration). This suggests that I have brought some design baggage (my history is largely Python) that is causing to architect solutions or patterns that aren’t suitable to Rust. Perhaps it’s just too many layers of abstraction?

0 Likes

#2

No change, still working as intended. If the trait is limited to a lifetime so must any structure implementing it.

Some demo code might be a good way to get feedback if there is some alternative.

1 Like

#3

I would like to point out another solution to the problem

trait Gal<'a> {
    type Assoc: 'a;

    // anything that needs to know the internals of Assoc
    fn new_assoc() -> Self::Assoc
    fn get_from_assoc(_assoc: &Self::Assoc) -> &u32;
}

trait Trait {
    fn use_gal<'a>(&'a self, &Self::Assoc) where Self: Gal<'a>;
}

When applied to the question the the reddit thread

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=851fa0a851567386d2e0b497c3d65283


Now, this way makes it more complex to design and implement Doc, but it also allows you to almost completely ignore the lifetimes when using Doc. So there is a trade off.

2 Likes

#4

This pattern could be extended to types to allow a more expressive form of GATs in today’s Rust, but with a huge ergonomic penalty.

// any number of types and lifetimes
trait Gat<'a, T> {
    type Assoc: 'a;

    // anything that needs to know the internals of Assoc
    fn new_assoc() -> Self::Assoc
    fn get_from_assoc(_assoc: &Self::Assoc) -> &u32;
}

trait Trait {
    fn use_gal<'a, T>(&'a self, &Self::Assoc) where Self: Gal<'a, T>;
}

This is more expressive because you can do things with this that you can’t do with GATs.

for example, specializing on a type

type Special;

impl<T: Copy> Gat<'a, T> { ... }
impl Gat<'a, Special> { ... }
1 Like