Where do I declare lifetime used in trait's associated type?

trait Foo {
    type Bar;
}

struct Baz;

impl<'a> Foo for Baz {
    type Bar = std::slice::Iter<'a, u8>;
}

I don't know where to declare 'a. Rust doesn't like it being on impl, but without it complains that 'a in Iter is undeclared.

1 Like

Wow, you're on a roll. Technically, you could write:

trait Foo {
    type Bar;
    fn do_it(self) -> Self::Bar;
}

struct Baz;

impl<'a> Foo for &'a Baz {
    type Bar = std::slice::Iter<'a, u8>;
    fn do_it(self) -> std::slice::Iter<'a, u8> { /* ... */ }
}

but, in practice, this tends to get ugly very fast. Ideally, you could write:

trait Foo {
    type Bar<'a>;
    fn do_it(&self) -> Self::Bar;
}

struct Baz;

impl Foo for Baz {
    type Bar<'a> = std::slice::Iter<'a, u8>;
    fn do_it<'a>(&'a self) -> std::slice::Iter<'a, u8> { /* ... */ }
}

but you'd need a limited form of HKT first:

https://github.com/rust-lang/rfcs/pull/1598

2 Likes

Yeah, I'm just tying to write one set of functions for two types :slight_smile:

Thanks for the help

FYI, an alternative solution is to avoid associated types and use boxed trait objects. In this case, you'd write:

trait Foo {
    fn do_it(&'a self) -> Box<Iterator<Item=X> + 'a>;
}

struct Baz;

impl Foo for Baz {
    fn do_it(&self) -> Box<Iterator<Item=X> {
        /* ... */
        Box::new(/* ... */) as Box<Iterator<Item=X>>
    }
}

Another alternative is to put the lifetime on the trait itself:

trait Foo<'a> {
    type Bar;
    fn do_it(&'a self) -> Self::Bar;
}

struct Baz;

impl<'a> Foo<'a> for Baz {
    type Bar = std::slice::Iter<'a, u8>;
    fn do_it(&'a self) -> std::slice::Iter<'a, u8> { /* ... */ }
}