4

While it makes sense intuitively that references passed to spawned threads need to have static lifetimes, I'm unclear about what exactly is making the following code not compile:

use std::sync::Arc;
use std::sync::Mutex;

struct M;

fn do_something(m : Arc<Mutex<&M>>) {
    println!("Ha, do nothing!");
}

fn main() {
    let a = M;
    {
        let c : Arc<Mutex<&M>> = Arc::new(Mutex::new(&a));
        for i in 0..2 {
            let c_clone = c.clone();
            ::std::thread::spawn(move || do_something(c_clone));
        }
    }
}

Compiling this small program gives the following error:

$ rustc -o test test.rs
test.rs:13:55: 13:56 error: `a` does not live long enough
test.rs:13         let c : Arc<Mutex<&M>> = Arc::new(Mutex::new(&a));
                                                             ^
note: reference must be valid for the static lifetime...

It seems to me that the variable a will out-live c_clone, which is what matters in this case...? Hopefully someone can help me understand what I'm missing!

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Mokosha
  • 2,737
  • 16
  • 33
  • Threads can be started from other threads. There's no way to statically know which thread is spawning a thread, so the conservative (read *safe*) solution is to require that all references must have the 'static lifetime. Items created in `main` do not have that lifetime as they are destroyed before main exits. – Shepmaster Oct 06 '15 at 23:41

1 Answers1

6

In its essence, the Arc and Mutex wrapping is superfluous: you are passing a reference to something on the local stack. When you spawn a thread with std::thread::spawn, there is nothing linking the lifetimes together; the main thread is quite at liberty to conclude and free anything in it—in this case, including a—before any other threads it spawns even start executing; thus in this case a could refer to freed memory by the time the spawned thread does anything, leaving c_clone as a dangling pointer. This is why the environment of the closure of a spawned thread must be 'static.

Chris Morgan
  • 86,207
  • 24
  • 208
  • 215
  • [Here is the reference](https://doc.rust-lang.org/std/thread/fn.spawn.html) to the documentation of `std::thread::spawn` – Mokosha Oct 10 '15 at 21:36