Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
696 views
in Technique[技术] by (71.8m points)

rust - Why is adding a lifetime to a trait with the plus operator (Iterator<Item = &Foo> + 'a) needed?

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
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is one thing that is easily overlooked: if you have a trait Bar and you want to have a boxed trait object Box<dyn Bar>, the compiler automatically adds a 'static lifetime bound (as specified in RFC 599). This means that Box<dyn Bar> and Box<dyn Bar + 'static> are equivalent!

In your case, the compiler automatically adds the static bound such that this ...

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>>

... is equivalent to that:

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn 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<dyn 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<dyn 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...