diff --git a/library/std/src/sys/thread_local/native/lazy.rs b/library/std/src/sys/thread_local/native/lazy.rs index 02939a74fc089..b16beb109c6fc 100644 --- a/library/std/src/sys/thread_local/native/lazy.rs +++ b/library/std/src/sys/thread_local/native/lazy.rs @@ -56,27 +56,22 @@ where /// The `self` reference must remain valid until the TLS destructor is run. #[inline] pub unsafe fn get_or_init(&self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { - if let State::Alive = self.state.get() { - self.value.get().cast() - } else { - unsafe { self.get_or_init_slow(i, f) } + match self.state.get() { + State::Alive => self.value.get().cast(), + State::Destroyed(_) => ptr::null(), + State::Uninitialized => unsafe { self.get_or_init_slow(i, f) }, } } /// # Safety - /// The `self` reference must remain valid until the TLS destructor is run. + /// * The state of `self` must be `Uninitalized`. + /// * The `self` reference must remain valid until the TLS destructor is run. #[cold] unsafe fn get_or_init_slow( &self, i: Option<&mut Option>, f: impl FnOnce() -> T, ) -> *const T { - match self.state.get() { - State::Uninitialized => {} - State::Alive => return self.value.get().cast(), - State::Destroyed(_) => return ptr::null(), - } - let v = i.and_then(Option::take).unwrap_or_else(f); // SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 9f7a29236e926..4becaa67532ab 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -181,30 +181,25 @@ impl Storage { pub fn get(&'static self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { let key = self.key.force(); let ptr = unsafe { get(key) as *mut Value }; - if ptr.addr() > 1 { + match ptr.addr() { // SAFETY: the check ensured the pointer is safe (its destructor // is not running) + it is coming from a trusted source (self). - unsafe { &(*ptr).value } - } else { + 2.. => unsafe { &(*ptr).value }, + // destructor is running + 1 => ptr::null(), // SAFETY: trivially correct. - unsafe { Self::try_initialize(key, ptr, i, f) } + 0 => unsafe { Self::try_initialize(key, i, f) }, } } /// # Safety /// * `key` must be the result of calling `self.key.force()` - /// * `ptr` must be the current value associated with `key`. + /// * The current pointer associated with `key` must be null. unsafe fn try_initialize( key: Key, - ptr: *mut Value, i: Option<&mut Option>, f: impl FnOnce() -> T, ) -> *const T { - if ptr.addr() == 1 { - // destructor is running - return ptr::null(); - } - let value = AlignedBox::::new(Value { value: i.and_then(Option::take).unwrap_or_else(f), key,