Link lifetime in associated type

I need a way to link a lifetime from an associated type to Box<dyn Trait> so that dyn Trait is not automatically bound to 'static:

// Simplified `IntoIterator`
trait Iterable {
    type Item;
    type Iter;
}

pub struct TypeErasedIterable<T>(T);

impl<'a, T> Iterable for TypeErasedIterable<T>
where
    T: Iterable,
    T::Iter: 'a,
{
    type Iter = Box<dyn Iterator<Item = T::Item> + 'a>;
    type Item = T::Item;
}

This code produces a compiler error:

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates

Have a good day!

You could

  • Add a lifetime parameter to the trait
  • Add a lifetime parameter to the type
  • Add a lifetime parameter to the associated type
  • Use a generic which includes the lifetime (... for TypeErasedIterable<&'a T>)

But there is no notation for "the maximum lifetime which a type could meet in a bound", which is what it looks like you wish for here.

impl<T: Iterable> Iterable for TypeErasedIterable<T> {
    // Imaginary language feature                  vvvvvvvvvvvv
    type Iter = Box<dyn Iterator<Item = T::Item> + 'limit(Self)>;
    type Item = T::Item;
}

Yes, because if I just write Box<dyn Iterator<Item = T::Item>> without the 'a bound. Lifetime elision rule will give it the 'static bound, which also requires other type parameters to outlive 'static. So if I have an Iterable, say impl<'a, T> Iterable for &'a Vec<T> then Self::Iter will be 'a, then I wouldn't be able to use Iterable impl for TypeErasedIterable because of failed unsizing coercion

dyn Iterator<Item = _> + 'i represents a type erased iterator that's valid for 'i. You could do something similar for TypeErasedIterable<..>.

pub struct TypeErasedIterable<'i, I>(I, PhantomData<&'i I>);

impl<'i, I> Iterable for TypeErasedIterable<'i, I>
where
    I: Iterable,
{
    type Iter = Box<dyn Iterator<Item = I::Item> + 'i>;
    type Item = I::Item;
}