Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure and rename std thread_local internals to make it less of a maze #110861

Merged
merged 3 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 16 additions & 23 deletions library/std/src/sys/common/thread_local/fast_local.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use super::lazy::LazyKeyInner;
use crate::cell::Cell;
use crate::sys::thread_local_dtor::register_dtor;
use crate::{fmt, mem, panic};

#[doc(hidden)]
#[macro_export]
#[allow_internal_unstable(
thread_local_internals,
cfg_target_thread_local,
thread_local,
libstd_thread_internals
)]
#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
#[allow_internal_unsafe]
macro_rules! __thread_local_inner {
#[unstable(feature = "thread_local_internals", issue = "none")]
#[rustc_macro_transparency = "semitransparent"]
pub macro thread_local_inner {
// used to generate the `LocalKey` value for const-initialized thread locals
(@key $t:ty, const $init:expr) => {{
#[cfg_attr(not(bootstrap), inline)]
Expand Down Expand Up @@ -49,7 +50,7 @@ macro_rules! __thread_local_inner {
// 0 == we haven't registered a destructor, so do
// so now.
0 => {
$crate::thread::__LocalKeyInner::<$t>::register_dtor(
$crate::thread::local_impl::Key::<$t>::register_dtor(
$crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
destroy,
);
Expand All @@ -69,7 +70,7 @@ macro_rules! __thread_local_inner {
unsafe {
$crate::thread::LocalKey::new(__getit)
}
}};
}},

// used to generate the `LocalKey` value for `thread_local!`
(@key $t:ty, $init:expr) => {
Expand All @@ -82,8 +83,8 @@ macro_rules! __thread_local_inner {
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
#[thread_local]
static __KEY: $crate::thread::__LocalKeyInner<$t> =
$crate::thread::__LocalKeyInner::<$t>::new();
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::<$t>::new();

// FIXME: remove the #[allow(...)] marker when macros don't
// raise warning for missing/extraneous unsafe blocks anymore.
Expand All @@ -107,20 +108,13 @@ macro_rules! __thread_local_inner {
$crate::thread::LocalKey::new(__getit)
}
}
};
},
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
$crate::__thread_local_inner!(@key $t, $($init)*);
}
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
},
}

#[doc(hidden)]
pub mod fast {
use super::super::lazy::LazyKeyInner;
use crate::cell::Cell;
use crate::sys::thread_local_dtor::register_dtor;
use crate::{fmt, mem, panic};

#[derive(Copy, Clone)]
enum DtorState {
Unregistered,
Expand Down Expand Up @@ -251,4 +245,3 @@ pub mod fast {
rtabort!("thread local panicked on drop");
}
}
}
33 changes: 11 additions & 22 deletions library/std/src/sys/common/thread_local/mod.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
//! The following module declarations are outside cfg_if because the internal
//! `__thread_local_internal` macro does not seem to be exported properly when using cfg_if
#![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]

#[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics")))))]
mod fast_local;
#[cfg(all(
not(target_thread_local),
not(all(target_family = "wasm", not(target_feature = "atomics")))
))]
mod os_local;
#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
mod static_local;

#[cfg(not(test))]
cfg_if::cfg_if! {
if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] {
#[doc(hidden)]
pub use static_local::statik::Key;
} else if #[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics")))))] {
mod static_local;
#[doc(hidden)]
pub use static_local::{Key, thread_local_inner};
} else if #[cfg(all(target_thread_local))] {
#[doc(hidden)]
pub use fast_local::fast::Key;
} else if #[cfg(all(not(target_thread_local), not(all(target_family = "wasm", not(target_feature = "atomics")))))] {
mod fast_local;
#[doc(hidden)]
pub use fast_local::{Key, thread_local_inner};
} else {
#[doc(hidden)]
mod os_local;
#[doc(hidden)]
pub use os_local::os::Key;
pub use os_local::{Key, thread_local_inner};
}
}

#[doc(hidden)]
#[cfg(test)]
pub use realstd::thread::__LocalKeyInner as Key;

mod lazy {
use crate::cell::UnsafeCell;
use crate::hint;
Expand Down
41 changes: 17 additions & 24 deletions library/std/src/sys/common/thread_local/os_local.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use super::lazy::LazyKeyInner;
use crate::cell::Cell;
use crate::sys_common::thread_local_key::StaticKey as OsStaticKey;
use crate::{fmt, marker, panic, ptr};

#[doc(hidden)]
#[macro_export]
#[allow_internal_unstable(
thread_local_internals,
cfg_target_thread_local,
thread_local,
libstd_thread_internals
)]
#[allow_internal_unstable(thread_local_internals)]
#[allow_internal_unsafe]
macro_rules! __thread_local_inner {
#[unstable(feature = "thread_local_internals", issue = "none")]
#[rustc_macro_transparency = "semitransparent"]
pub macro thread_local_inner {
// used to generate the `LocalKey` value for const-initialized thread locals
(@key $t:ty, const $init:expr) => {{
#[cfg_attr(not(bootstrap), inline)]
Expand All @@ -21,8 +22,8 @@ macro_rules! __thread_local_inner {
// same implementation as below for os thread locals.
#[inline]
const fn __init() -> $t { INIT_EXPR }
static __KEY: $crate::thread::__LocalKeyInner<$t> =
$crate::thread::__LocalKeyInner::new();
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::new();
#[allow(unused_unsafe)]
unsafe {
__KEY.get(move || {
Expand All @@ -41,7 +42,7 @@ macro_rules! __thread_local_inner {
unsafe {
$crate::thread::LocalKey::new(__getit)
}
}};
}},

// used to generate the `LocalKey` value for `thread_local!`
(@key $t:ty, $init:expr) => {
Expand All @@ -55,8 +56,8 @@ macro_rules! __thread_local_inner {
unsafe fn __getit(
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
static __KEY: $crate::thread::__LocalKeyInner<$t> =
$crate::thread::__LocalKeyInner::new();
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::new();

// FIXME: remove the #[allow(...)] marker when macros don't
// raise warning for missing/extraneous unsafe blocks anymore.
Expand All @@ -80,20 +81,13 @@ macro_rules! __thread_local_inner {
$crate::thread::LocalKey::new(__getit)
}
}
};
},
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
$crate::__thread_local_inner!(@key $t, $($init)*);
}
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
},
}

#[doc(hidden)]
pub mod os {
use super::super::lazy::LazyKeyInner;
use crate::cell::Cell;
use crate::sys_common::thread_local_key::StaticKey as OsStaticKey;
use crate::{fmt, marker, panic, ptr};

/// Use a regular global static to store this key; the state provided will then be
/// thread-local.
pub struct Key<T> {
Expand Down Expand Up @@ -194,4 +188,3 @@ pub mod os {
rtabort!("thread local panicked on drop");
}
}
}
32 changes: 13 additions & 19 deletions library/std/src/sys/common/thread_local/static_local.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use super::lazy::LazyKeyInner;
use crate::fmt;

#[doc(hidden)]
#[macro_export]
#[allow_internal_unstable(
thread_local_internals,
cfg_target_thread_local,
thread_local,
libstd_thread_internals
)]
#[allow_internal_unstable(thread_local_internals)]
#[allow_internal_unsafe]
macro_rules! __thread_local_inner {
#[unstable(feature = "thread_local_internals", issue = "none")]
#[rustc_macro_transparency = "semitransparent"]
pub macro thread_local_inner {
// used to generate the `LocalKey` value for const-initialized thread locals
(@key $t:ty, const $init:expr) => {{
#[inline] // see comments below
Expand All @@ -30,7 +29,7 @@ macro_rules! __thread_local_inner {
unsafe {
$crate::thread::LocalKey::new(__getit)
}
}};
}},

// used to generate the `LocalKey` value for `thread_local!`
(@key $t:ty, $init:expr) => {
Expand All @@ -41,8 +40,8 @@ macro_rules! __thread_local_inner {
unsafe fn __getit(
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
static __KEY: $crate::thread::__LocalKeyInner<$t> =
$crate::thread::__LocalKeyInner::new();
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::new();

// FIXME: remove the #[allow(...)] marker when macros don't
// raise warning for missing/extraneous unsafe blocks anymore.
Expand All @@ -66,19 +65,15 @@ macro_rules! __thread_local_inner {
$crate::thread::LocalKey::new(__getit)
}
}
};
},
($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => {
$(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> =
$crate::__thread_local_inner!(@key $t, $($init)*);
}
$crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*);
},
}

/// On some targets like wasm there's no threads, so no need to generate
/// thread locals and we can instead just use plain statics!
#[doc(hidden)]
pub mod statik {
use super::super::lazy::LazyKeyInner;
use crate::fmt;

pub struct Key<T> {
inner: LazyKeyInner<T>,
Expand Down Expand Up @@ -112,4 +107,3 @@ pub mod statik {
Some(value)
}
}
}
8 changes: 4 additions & 4 deletions library/std/src/thread/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,23 +153,23 @@ macro_rules! thread_local {
() => {};

($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => (
$crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
$crate::thread_local!($($rest)*);
);

($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => (
$crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init);
);

// process multiple declarations
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => (
$crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
$crate::thread_local!($($rest)*);
);

// handle a single declaration
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => (
$crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
$crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init);
);
}

Expand Down
7 changes: 5 additions & 2 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,12 @@ pub use self::local::{AccessError, LocalKey};
// by the elf linker. "static" is for single-threaded platforms where a global
// static is sufficient.

// Implementation details used by the thread_local!{} macro.
#[doc(hidden)]
#[unstable(feature = "libstd_thread_internals", issue = "none")]
pub use crate::sys::common::thread_local::Key as __LocalKeyInner;
#[unstable(feature = "thread_local_internals", issue = "none")]
pub mod local_impl {
pub use crate::sys::common::thread_local::{thread_local_inner, Key};
}

////////////////////////////////////////////////////////////////////////////////
// Builder
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ui/macros/macro-local-data-key-priv.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ note: the constant `baz` is defined here
|
LL | thread_local!(static baz: f64 = 0.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::__thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/threads-sendsync/issue-43733-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl<T> Key<T> {
}

#[cfg(target_thread_local)]
use std::thread::__LocalKeyInner as Key;
use std::thread::local_impl::Key;

static __KEY: Key<()> = Key::new();
//~^ ERROR `UnsafeCell<Option<()>>` cannot be shared between threads
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/threads-sendsync/issue-43733.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/issue-43733.rs:21:5
--> $DIR/issue-43733.rs:19:5
|
LL | __KEY.get(Default::default)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/issue-43733.rs:26:42
--> $DIR/issue-43733.rs:24:42
|
LL | static FOO: std::thread::LocalKey<Foo> = std::thread::LocalKey::new(__getit);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
Expand Down
8 changes: 3 additions & 5 deletions tests/ui/threads-sendsync/issue-43733.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// ignore-wasm32
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
// normalize-stderr-test: "__LocalKeyInner::<T>::get" -> "$$LOCALKEYINNER::<T>::get"
// normalize-stderr-test: "__LocalKeyInner::<T>::get" -> "$$LOCALKEYINNER::<T>::get"
#![feature(thread_local)]
#![feature(cfg_target_thread_local, thread_local_internals)]

Expand All @@ -12,15 +10,15 @@ type Foo = std::cell::RefCell<String>;

#[cfg(target_thread_local)]
#[thread_local]
static __KEY: std::thread::__LocalKeyInner<Foo> = std::thread::__LocalKeyInner::new();
static __KEY: std::thread::local_impl::Key<Foo> = std::thread::local_impl::Key::new();

#[cfg(not(target_thread_local))]
static __KEY: std::thread::__LocalKeyInner<Foo> = std::thread::__LocalKeyInner::new();
static __KEY: std::thread::local_impl::Key<Foo> = std::thread::local_impl::Key::new();

fn __getit(_: Option<&mut Option<RefCell<String>>>) -> std::option::Option<&'static Foo> {
__KEY.get(Default::default)
//[mir]~^ ERROR call to unsafe function is unsafe
//[thir]~^^ ERROR call to unsafe function `__
//[thir]~^^ ERROR call to unsafe function `Key::<T>::get`
}

static FOO: std::thread::LocalKey<Foo> = std::thread::LocalKey::new(__getit);
Expand Down
Loading