I'm applying a closure on the iterator and I want to use stable, so I want to return a boxed Iterator
. The obvious way to do so is the following:
struct Foo;
fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>> {
Box::new(myvec.iter())
}
This fails because the borrow checker cannot infer the appropriate lifetimes.
After some research, I've found What is the correct way to return an Iterator (or any other trait)?, which brought me to adding + 'a
:
fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &'a Foo> + 'a> {
Box::new(myvec.iter())
}
But I don't understand
- What this does
- And why it is needed here
There is one thing that is easily overlooked: if you have a trait
Bar
and you want to have a boxed trait objectBox<dyn Bar>
, the compiler automatically adds a'static
lifetime bound (as specified in RFC 599). This means thatBox<dyn Bar>
andBox<dyn Bar + 'static>
are equivalent!In your case, the compiler automatically adds the static bound such that this ...
... is equivalent to that:
Now lifetime elision rules kick in and "connect" the two lifetime-slots, such that the above code is equivalent to:
But the type
Iter<'a, Foo>
(the specific iterator type forVec<Foo>
) obviously does not satisfy the bound'static
(because it is borrowing theVec<Foo>
)! So we have to tell the compiler that we don't want the default'static
bound by specifying our own lifetime bound:Now the compiler knows that the trait object is only valid for the lifetime
'a
. Note that we don't explicitly need to annotate the lifetime of the associatedItem
type! Lifetime elision rules take care of that.