Returning a closure from a struct method

I was trying to understand closures in rust and thus was trying to return a closure from the method of a struct but it seems to be failing. I was trying to define a line and getting a predictor from the line as below

struct line {
pub constant: f64,
pub slope: f64,
}

impl line{
pub fn get_predictor(&self) -> impl Fn(f64) -> f64{
move |b| self.slope * b + self.constant
}
}

However I seem to see the following failure due to this

error[E0700]: hidden type for impl Trait captures lifetime that does not appear in bounds
--> line/src/main.rs:11:5
|
10 | pub fn get_predictor(&self) -> impl Fn(f64) -> f64{
| ----- hidden type [closure@line/src/main.rs:11:5: 11:44] captures the anonymous lifetime defined here
11 | move |b| self.slope * b + self.constant
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that the impl Trait captures '_, you can add an explicit '_ lifetime bound
|
10 | pub fn get_predictor(&self) -> impl Fn(f64) -> f64 + '_{

Any pointers to what I'm getting wrong here?

Formatting note: Use ``` not > for code:
```
Code goes here
```


Here:

    pub fn get_predictor(&self) -> impl Fn(f64) -> f64  {
        move |b| self.slope * b + self.constant
    }

You're capturing &self within the closure, and &self -- like all references -- has an associated lifetime. You did say move, but this case, that just means you're moving the borrowed &self into the closure instead of a [re-]borrow of &self. Because of this, the closure is only going to be valid for the same lifetime as &self, and you need to make that explicit in your function API. The compiler hint tells you how to do so:

help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
  |
8 |     pub fn get_predictor(&self) -> impl Fn(f64) -> f64 + '_  {
  |                                                        ++++

And if you add the suggested bound, it does compile.


However, what you probably wanted to happen is for the closure to capture the two fields slope and constant by value, instead of capturing &self. You can make that happen here by manually copying the fields out.

But with this particular struct, what I'd actually suggest is implementing Copy and Clone:

#[derive(Copy, Clone)]
pub struct Line { /* ... */ }

And then you could more easily create an owned Line to capture instead of the borrowed &self like so:

    pub fn get_predictor(&self) -> impl Fn(f64) -> f64 {
        let this = *self;
        move |b| this.slope * b + this.constant
    }

Or since Line is Copy now, callers of self methods don't have to give up ownership anymore, so you could even just make the method take self instead of &self:

    pub fn get_predictor(self) -> impl Fn(f64) -> f64 {
        move |b| self.slope * b + self.constant
    }
6 Likes