Returning an iterator from a method fights me over lifetimes every single time Idiomatic?
I have a struct holding a Vec<Record> and I want a method that returns an iterator over the records matching a predicate, without collecting into a new Vec. Every attempt ends in either a lifetime error about the closure, or the compiler telling me the returned type doesn't live long enough. I've made it work once with Box<dyn Iterator> and it felt like giving up. What's the current idiomatic signature for this?
@borrowck_ben · 6mo ago · 3 replies
fn matching(&self, kind: Kind) -> impl Iterator<Item = &Record> + '_is what you want. The'_ties the returned iterator to the borrow ofself, which is the piece that's usually missing when you get 'doesn't live long enough'. Inside,self.records.iter().filter(move |r| r.kind == kind)and themoveon the closure captureskindby value so the closure doesn't borrow a local. Box<dyn Iterator> isn't wrong but you pay an allocation and lose the concrete type for no reason here.Reply
Report
@borrowck_ben · 6mo ago
It can see it, it just won't assume it, because for
impl Traitin return position the captured lifetimes have to be spelled out or elided explicitly. Newer editions loosened this, which is why half the examples you find online don't have it.Reply
Report
@sdcard_sid · 6mo ago
The
+ '_was the missing piece. I'd been writingimpl Iterator<Item = &Record>and wondering why it wanted a lifetime it could clearly see.Reply
Report