(try on playpen)
#![feature(const_fn, drop_types_in_const, thread_local_internals)]
type Foo = std::cell::RefCell<String>;
static __KEY: std::thread::__FastLocalKeyInner<Foo> =
std::thread::__FastLocalKeyInner::new();
fn __getit() -> std::option::Option<
&'static std::cell::UnsafeCell<
std::option::Option<Foo>>>
{
__KEY.get()
}
static FOO: std::thread::LocalKey<Foo> =
std::thread::LocalKey::new(__getit, Default::default);
fn main() {
FOO.with(|foo| println!("{}", foo.borrow()));
std::thread::spawn(|| {
FOO.with(|foo| *foo.borrow_mut() += "foo");
}).join().unwrap();
FOO.with(|foo| println!("{}", foo.borrow()));
}
Discovered while working on a sound fix for #17954. The problem is this decision which prevents the thread_local! macro from using unsafe to state that it actually has a #[thread_local] static to use in LocalKey. Without that, anything of 'static lifetime (which is btw quite wrong for #[thread_local]) and the right type can be used, from safe code.
While we can change the APIs all we want, going back to the correct solution of #[allow(unsafe_code)] could be a breaking change, without unsafety hygiene.
cc @rust-lang/libs
(try on playpen)
Discovered while working on a sound fix for #17954. The problem is this decision which prevents the
thread_local!macro from usingunsafeto state that it actually has a#[thread_local]staticto use inLocalKey. Without that, anything of'staticlifetime (which is btw quite wrong for#[thread_local]) and the right type can be used, from safe code.While we can change the APIs all we want, going back to the correct solution of
#[allow(unsafe_code)]could be a breaking change, without unsafety hygiene.cc @rust-lang/libs