diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs
index 88d937a7db1..8d51732e035 100644
--- a/library/std/src/sys_common/thread_info.rs
+++ b/library/std/src/sys_common/thread_info.rs
@@ -1,46 +1,51 @@
 #![allow(dead_code)] // stack_guard isn't used right now on all platforms
 
-use crate::cell::RefCell;
+use crate::cell::OnceCell;
 use crate::sys::thread::guard::Guard;
 use crate::thread::Thread;
 
 struct ThreadInfo {
-    stack_guard: Option<Guard>,
-    thread: Thread,
+    stack_guard: OnceCell<Guard>,
+    thread: OnceCell<Thread>,
 }
 
-thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = const { RefCell::new(None) } }
+thread_local! {
+   static THREAD_INFO: ThreadInfo = const { ThreadInfo {
+       stack_guard: OnceCell::new(),
+       thread: OnceCell::new()
+   } };
+}
 
 impl ThreadInfo {
     fn with<R, F>(f: F) -> Option<R>
     where
-        F: FnOnce(&mut ThreadInfo) -> R,
+        F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
     {
         THREAD_INFO
             .try_with(move |thread_info| {
-                let mut thread_info = thread_info.borrow_mut();
-                let thread_info = thread_info.get_or_insert_with(|| ThreadInfo {
-                    stack_guard: None,
-                    thread: Thread::new(None),
-                });
-                f(thread_info)
+                let thread = thread_info.thread.get_or_init(|| Thread::new(None));
+                f(thread, &thread_info.stack_guard)
             })
             .ok()
     }
 }
 
 pub fn current_thread() -> Option<Thread> {
-    ThreadInfo::with(|info| info.thread.clone())
+    ThreadInfo::with(|thread, _| thread.clone())
 }
 
 pub fn stack_guard() -> Option<Guard> {
-    ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o)
+    ThreadInfo::with(|_, guard| guard.get().cloned()).flatten()
 }
 
+/// Set new thread info, panicking if it has already been initialized
+#[allow(unreachable_code, unreachable_patterns)] // some platforms don't use stack_guard
 pub fn set(stack_guard: Option<Guard>, thread: Thread) {
     THREAD_INFO.with(move |thread_info| {
-        let mut thread_info = thread_info.borrow_mut();
-        rtassert!(thread_info.is_none());
-        *thread_info = Some(ThreadInfo { stack_guard, thread });
+        rtassert!(thread_info.stack_guard.get().is_none() && thread_info.thread.get().is_none());
+        if let Some(guard) = stack_guard {
+            thread_info.stack_guard.set(guard).unwrap();
+        }
+        thread_info.thread.set(thread).unwrap();
     });
 }