Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust: Lifetime outliving anonymous function

Tags:

rust

I'm trying to simulate an async execution with the function spawn but I fail to compile the code snippet below.

use std::thread::{spawn, JoinHandle};

fn main() {
    let data  = vec![String::from("some data"), String::from("some more data")];

    let doer = Doer{f: |x| {return x + " hello"} };

    let results: Vec<JoinHandle<String>> = data.iter()
        .map(|x| doer.apply_async(x.to_owned()))
        .collect();

    results.iter().for_each(|x| println!("{}", x.join().unwrap()));
}

struct Doer {
    f: fn(xs: String) -> String
}

impl Doer {
    fn apply(&self, datum: String) -> String {
        let f = &self.f;
        return f(datum);
    }

    fn apply_async(&self, datum: String) -> JoinHandle<String> {
        return spawn(move|| self.apply(datum));
    }
}

I have an error like this first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 25:5...

I'm not sure to understand what lifetime is outliving the anonymous lifetime. Any idea?

like image 997
jeremie Avatar asked Sep 06 '26 03:09

jeremie


1 Answers

apply_async is a method that takes &self. This means that self is a reference that is only guaranteed to live for the duration of the call to apply_async. The closure move || self.apply(datum) captures self, lifetime and all, which means it is not 'static. This is why you can't call spawn on it.

If Doer implements Clone, one way to solve this problem is to make a clone of *self and move it into the closure.

    fn apply_async(&self, datum: String) -> JoinHandle<String> {
        let s = self.clone();
        return spawn(move || s.apply(datum));
    }

If you don't want to clone the whole Doer, you could only copy the necessary parts, and reimplement apply inside apply_async, for instance:

    fn apply_async(&self, datum: String) -> JoinHandle<String> {
        let f = self.f;
        return spawn(move|| f(datum));
    }
like image 163
trent Avatar answered Sep 10 '26 05:09

trent