Rust: Write to #[thread_local] is not respected

Created on 8 Oct 2018  路  3Comments  路  Source: rust-lang/rust

#![feature(thread_local)]

#[thread_local]
static S: &str = "before";

fn set_s() {
    S = "after";
}

fn main() {
    println!("{}", S);
    set_s();
    println!("{}", S);
}

On rustc 1.31.0-nightly (b2d6ea98b 2018-10-07) and x86_64-unknown-linux-gnu, we see the following surprising behavior:

$ cargo run  # as expected
before
after

$ cargo run --release
before
before

In release mode it seems the write has not happened in the place that it should.

Mentioning thread_local tracking issue: rust-lang/rust#29594.

E-needs-test NLL-fixed-by-NLL

Most helpful comment

Ah, apparently this is missing a mut. With mut the behavior is correct. We need to make sure mutating a thread_local static that does not have mut does not compile.

#![feature(thread_local)]

#[thread_local]
static mut S: &str = "before";

fn set_s() {
    unsafe { S = "after" };
}

fn main() {
    println!("{}", unsafe { S });
    set_s();
    println!("{}", unsafe { S });
}
$ cargo run --release
before
after

All 3 comments

Ah, apparently this is missing a mut. With mut the behavior is correct. We need to make sure mutating a thread_local static that does not have mut does not compile.

#![feature(thread_local)]

#[thread_local]
static mut S: &str = "before";

fn set_s() {
    unsafe { S = "after" };
}

fn main() {
    println!("{}", unsafe { S });
    set_s();
    println!("{}", unsafe { S });
}
$ cargo run --release
before
after

cc @pnkfelix @nikomatsakis Did #55150 fix this by any chance?

It looks like this is fixed on nightly; I'm guessing #55150 is the reason. We probably should add some regression tests for the cases listed here.

Was this page helpful?
0 / 5 - 0 ratings