Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set lifetime for boxed closure capturing `self`?

I want to return an iterator (in particular, a Filter). I used a previous answer that suggests returning a boxed iterator. The problem is that my filter captures self and I get:

error: closure may outlive the current function, but it borrows self, which is owned by the current function

But I think I'm being explicit that self has lifetime 'a and so does the Box I'm returning:

fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> {
    Box::new( (0..32).filter( |&pos| match self.at(pos) { Occupied::Empty => false, _ => true } ) )
}

This is an attempt to simplify my first effort, where I created a new FooIterator which owns a reference to self in basically the same way.

If I use most of the same syntax to simply capture self as a member reference it works fine:

struct Foo { junk: i32 }
struct FooIterator<'a> { foo: &'a Foo }
impl Foo {
    fn foo<'a>(&'a self) -> Box<FooIterator<'a>> {
        Box::new( FooIterator { foo: self } )
    }       
}
like image 589
Ben Jackson Avatar asked Jan 05 '16 06:01

Ben Jackson


1 Answers

You get an error because your closure receives a reference to self, which itself is a reference. However, since the reference points to a local variable, that reference becomes invalid as soon as the function returns.

To fix this, add the move keyword before the closure. This instructs the compiler to move the closed-over variables in the closure, rather than pass a reference to those variables to the closure.

fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> {
    Box::new( (0..32).filter(move |&pos| match self.at(pos) { Occupied::Empty => false, _ => true } ) )
}
like image 83
Francis Gagné Avatar answered Nov 15 '22 08:11

Francis Gagné