1
votes

How can I reduce the lifetime of a closure?

I was trying to make a method, which returns an iterator related to self. I didn't want to make new struct or something, so I just made it return filters and maps, and confronted some borrow checker errors.

The following code was my first try.

fn f<'b>(&'b self) -> impl Iterator<Item = u8> {
    (0..self.some_number())
        .filter(|&i| self.some_bool_function(i))
        .map(|i| i as u8)
}

The following code replicates my question.

struct A(bool);

impl A {
    fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
        (0..1).filter(|&i| self.0)
    }
}

or even shorter,

fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
    || *t
}

This would not compile, because the closure may outlive self. I don't know how to make this work, without moving self.

1

1 Answers

0
votes

If you return a closure, you must ensure that the closure has everything it needs - even after returning (i.e. after the (temporary) function parameters are popped from the stack).

Thus, I think you want to move the stuff you return into the closure:

impl A {
    fn f<'a>(&'a self) -> impl Iterator<Item = u8> + 'a {
        (0..1).filter(move |&i| self.0)
    }
}

Resp.

fn g<'a>(t:&'a ()) -> impl 'a + FnMut() {
    move || *t
}

Resp (extending your first example):

struct A(bool);

impl A {
    fn some_number(&self) -> usize {
        6
    }
    fn some_bool_function(&self, i: usize) -> bool {
        i%2==0
    }

    fn f<'b>(&'b self) -> impl Iterator<Item = u8> + 'b {
        (0..self.some_number())
            .filter(move |&i| self.some_bool_function(i))
            .map(|i| i as u8)
    }
}