shorez
shorez

Reputation: 167

Why doesn't this closure outlive var?

Consider the following Rust code:

use std::thread;

fn main() {
    bar();
    loop {}
}

fn bar() {
    let var = b"foo";
    thread::spawn(|| {
        write(var);
    });
}

fn write(d: &[u8]) {
    println!("{:?}", d)
}

To my understanding, var is on the stack of function bar, which no longer exists after it returns.

Still, the new thread accesses it afterwards and successfully writes the data.

  1. Why does this work?
  2. Why doesn't the Rust compiler complain?

Upvotes: 9

Views: 146

Answers (2)

jfMR
jfMR

Reputation: 24788

To my understanding, var is on the stack of function bar, which no longer exists after it returns.

var is just a reference with type &'static [u8; 3]. This reference value is what is on the stack, not the string literal.

The owner of the byte string literal b"foo" is the program binary, which results in the string literal having a 'static lifetime because it exists for the entire lifetime of the running program.

Upvotes: 8

at54321
at54321

Reputation: 11846

The b"foo" value doesn't live on the stack actually. It is stored in the read-only memory of the compiled binary and has a 'static lifetime.

Consider this alternative example:

fn bar() {
    let var = format!("foo");
    thread::spawn(|| {
        write(&var);
    });
}

fn write(d: &str) {
    println!("{:?}", d)
}

That won't work (unless you add move before the closure), because var (of type String) is allocated on the stack.

Upvotes: 4

Related Questions