Lifetime problems while implementing FromInterator

Can someone help me to understand why I can't compile the following example?

struct Foo(Box<dyn Iterator<Item = u8>>);

impl FromIterator<u8> for Foo {
    fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
        Foo(Box::new(iter.into_iter()))
    }
}

The compiler shows the following error:

error[E0310]: the associated type `<T as IntoIterator>::IntoIter` may not live long enough
 --> src/lib.rs:5:13
  |
5 |         Foo(Box::new(iter.into_iter()))
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: consider adding an explicit lifetime bound `<T as IntoIterator>::IntoIter: 'static`...
  = note: ...so that the type `<T as IntoIterator>::IntoIter` will meet its required lifetime bounds

For more information about this error, try `rustc --explain E0310`.

For what I understand, when I call IntoIterator::into_iter() I will have ownership of the iterator, so why do I still need to specify the 'static lifetime? (of course in this case - as far as I know - I can't even do that, since the bounds are defined on the FromIterator trait).

Sure, but how do you know the T: IntoIterator<...> type doesn't reference borrowed data? Your Foo type doesn't have any lifetime annotations, which means the result of calling T::into_iter() can't have contain any non-'static references (i.e. <T as IntoIterator>::IntoIter : 'static).

Unfortunately, you can't add that bound to your from_iter() method because it's fixed in the FromIterator trait.

Depending on your circumstances, you could use a From impl because that lets you add arbitrary constraints to the input type.

struct Foo(Box<dyn Iterator<Item = u8>>);

impl<I> From<I> for Foo
where
    I: IntoIterator<Item = u8>,
    <I as IntoIterator>::IntoIter: 'static,
{
    fn from(iter: I) -> Self {
        Foo(Box::new(iter.into_iter()))
    }
}

(playground)

Thanks Michael for the explanation, as always, now it is pretty obvious! hahahaha

1 Like