From 47e5c8910aa41c0077b480d328b24d5e92eb6f9e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Oct 2026 09:36:13 +0000 Subject: [PATCH] thread::LocalKey: document meaning of 'inner' function argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * thread::LocalKey: document meaning of 'inner' function argument * nit Co-authored-by: Jonas Böttiger --- library/std/src/sys/thread_local/native/mod.rs | 7 +++++-- library/std/src/thread/local.rs | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/thread_local/native/mod.rs b/library/std/src/sys/thread_local/native/mod.rs index 209a8790def08..30c7cde3954e5 100644 --- a/library/std/src/sys/thread_local/native/mod.rs +++ b/library/std/src/sys/thread_local/native/mod.rs @@ -59,8 +59,9 @@ pub macro thread_local_inner { unsafe { $crate::thread::LocalKey::new(const { + // We're okay to ignore `__rust_std_internal_init` as we never panic. if $crate::mem::needs_drop::<$t>() { - |_| { + |__rust_std_internal_init| { #[thread_local] $(#[$align_attr])* static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::EagerStorage<$t> @@ -68,7 +69,7 @@ pub macro thread_local_inner { __RUST_STD_INTERNAL_VAL.get() } } else { - |_| { + |__rust_std_internal_init| { #[thread_local] $(#[$align_attr])* static __RUST_STD_INTERNAL_VAL: $t = __RUST_STD_INTERNAL_INIT; @@ -92,6 +93,8 @@ pub macro thread_local_inner { unsafe { $crate::thread::LocalKey::new(const { + // `__rust_std_internal_init_fn` may panic so we must only call it if there is no + // `__rust_std_internal_init`. if $crate::mem::needs_drop::<$t>() { |__rust_std_internal_init| { #[thread_local] diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 18b0f3263ad59..8285682c81ba0 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -127,7 +127,14 @@ pub struct LocalKey { // trivially devirtualizable by LLVM because the value of `inner` never // changes and the constant should be readonly within a crate. This mainly // only runs into problems when TLS statics are exported across crates. - inner: fn(Option<&mut Option>) -> *const T, + // + // The argument of the function, `init`, can be used to initialize the key for the current + // thread: if it is not yet initialized, and if the argument is `Some(&mut Some(val))`, the + // inner `val` should be `take`en out and used as the initial value instead of the default. + // Also, in that case `inner` *must not* panic. However, it is okay (but potentially + // inefficient) for `inner` to ignore `init` and use a default value as long as that is + // guaranteed not to panic. + inner: fn(/* init */ Option<&mut Option>) -> *const T, } #[stable(feature = "std_debug", since = "1.16.0")]