Lifetime outliving annonymous lifetime

I hope this is enough code to illustrate the problem.

This does not compile

 fn athread_fn(&self, a:Arc<Mutex<usize>>) {
        println!("Hi!")
    }
    pub fn test_thread(&self, a:Arc<Mutex<usize>>) -> thread::JoinHandle<()>{
        thread::spawn( move ||  self.athread_fn(a))
    }

The error message has me confused. I expect it has something to do with the lifetime of the data guarded with the mutex but I cannot get my head around how to remedy the problem.

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> src/population.rs:228:24
    |
228 |         thread::spawn( move ||  self.athread_fn(a))
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 227:5...
   --> src/population.rs:227:5
    |
227 | /     pub fn test_thread(&self, a:Arc<Mutex<usize>>) -> thread::JoinHandle<()>{
228 | |         thread::spawn( move ||  self.athread_fn(a))
229 | |     }
    | |_____^
    = note: ...so that the types are compatible:
            expected &population::Population
               found &population::Population
    = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/population.rs:228:24: 228:51 self:&population::Population, a:std::sync::Arc<std::sync::Mutex<usize>>]` will meet its required lifetime bounds
   --> src/population.rs:228:9
    |
228 |         thread::spawn( move ||  self.athread_fn(a))
    |         ^^^^^^^^^^^^^

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> src/population.rs:231:25
    |
231 |          thread::spawn( move ||  self.thread_fn(a))
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 230:5...
   --> src/population.rs:230:5
    |
230 | /     pub fn run_in_thread(&self, a:Arc<Mutex<SimulationStatus>>) -> thread::JoinHandle<()>{
231 | |          thread::spawn( move ||  self.thread_fn(a))
232 | |     }
    | |_____^
    = note: ...so that the types are compatible:
            expected &population::Population
               found &population::Population
    = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/population.rs:231:25: 231:51 self:&population::Population, a:std::sync::Arc<std::sync::Mutex<controller::SimulationStatus>>]` will meet its required lifetime bounds
   --> src/population.rs:231:10
    |
231 |          thread::spawn( move ||  self.thread_fn(a))
    |          ^^^^^^^^^^^^^

Rust error messages from the compiler are usually very good, but I am perplexed by:

            expected &population::Population
               found &population::Population

Worik

The error isn't about the Arc<Mutex<usize>> (a); it's about the &Population (self).

The spawned thread can continue running after test_thread returns, and so it can't capture self, which is a borrowed reference that might not be valid indefinitely. For example, the parent thread might destroy the Population after calling test_thread but before the child thread has finished running.

You could fix this by changing test_thread not to access self on the spawned thread, or by making it take a Population or Arc<Population> instead of &Population, or using "scoped" threads as found in the rayon or crossbeam libraries.

3 Likes

That makes sense. I make the thread function athread_fn a function (not a method) and it compiles.

Thank you for that. Very helpful

Worik