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<Iterator<Item = &Foo>> {
Box::new(myvec.iter())
}
This fails because the borrow checker cannot infer the appropriate lifetimes.
After some research, I've found Correct way to return an Iterator?, which brought me to adding + 'a
:
fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<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 Foo
and you want to have a boxed trait object Box<Foo>
, the compiler automatically adds a 'static
lifetime bound (as specified in RFC 599). This means that Box<Foo>
and Box<Foo + 'static>
are equivalent!
In your case, the compiler automatically adds the static bound such that this ...
fn into_iterator(myvec: &Vec<Foo>) -> Box<Iterator<Item = &Foo>>
... is equivalent to that:
fn into_iterator(myvec: &Vec<Foo>) -> Box<Iterator<Item = &Foo> + 'static>
Now lifetime elision rules kick in and "connect" the two lifetime-slots, such that the above code is equivalent to:
fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<Iterator<Item = &'a Foo> + 'static>
But the type Iter<'a, Foo>
(the specific iterator type for Vec<Foo>
) obviously does not satisfy the bound 'static
(because it is borrowing the Vec<Foo>
)! So we have to tell the compiler that we don't want the default 'static
bound by specifying our own lifetime bound:
fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<Iterator<Item = &Foo> + 'a>
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 associated Item
type! Lifetime elision rules take care of that.
来源:https://stackoverflow.com/questions/42028470/why-is-adding-a-lifetime-to-a-trait-with-the-plus-operator-iteratoritem-foo