about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/io/stdio.rs2
-rw-r--r--library/std/src/sync/mpmc/mod.rs3
-rw-r--r--library/std/src/sync/mpmc/tests.rs14
-rw-r--r--library/std/src/sync/mpmc/waker.rs2
-rw-r--r--library/std/src/sys/net/connection/socket.rs9
-rw-r--r--library/std/src/sys/net/connection/socket/unix.rs7
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs36
-rw-r--r--library/std/src/sys/pal/unix/thread.rs19
-rw-r--r--library/std/src/thread/local.rs11
9 files changed, 70 insertions, 33 deletions
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 661c422811a..017862c7f3a 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -20,7 +20,7 @@ type LocalStream = Arc<Mutex<Vec<u8>>>;
 
 thread_local! {
     /// Used by the test crate to capture the output of the print macros and panics.
-    static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = {
+    static OUTPUT_CAPTURE: Cell<Option<LocalStream>> = const {
         Cell::new(None)
     }
 }
diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs
index 8caa2dcfad9..8712332dd27 100644
--- a/library/std/src/sync/mpmc/mod.rs
+++ b/library/std/src/sync/mpmc/mod.rs
@@ -1382,3 +1382,6 @@ impl<T> fmt::Debug for Receiver<T> {
         f.pad("Receiver { .. }")
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/sync/mpmc/tests.rs b/library/std/src/sync/mpmc/tests.rs
new file mode 100644
index 00000000000..6deb4dc2fe0
--- /dev/null
+++ b/library/std/src/sync/mpmc/tests.rs
@@ -0,0 +1,14 @@
+// Ensure that thread_local init with `const { 0 }` still has unique address at run-time
+#[test]
+fn waker_current_thread_id() {
+    let first = super::waker::current_thread_id();
+    let t = crate::thread::spawn(move || {
+        let second = super::waker::current_thread_id();
+        assert_ne!(first, second);
+        assert_eq!(second, super::waker::current_thread_id());
+    });
+
+    assert_eq!(first, super::waker::current_thread_id());
+    t.join().unwrap();
+    assert_eq!(first, super::waker::current_thread_id());
+}
diff --git a/library/std/src/sync/mpmc/waker.rs b/library/std/src/sync/mpmc/waker.rs
index 1895466f95d..f5e764e69bd 100644
--- a/library/std/src/sync/mpmc/waker.rs
+++ b/library/std/src/sync/mpmc/waker.rs
@@ -204,6 +204,6 @@ impl Drop for SyncWaker {
 pub fn current_thread_id() -> usize {
     // `u8` is not drop so this variable will be available during thread destruction,
     // whereas `thread::current()` would not be
-    thread_local! { static DUMMY: u8 = 0 }
+    thread_local! { static DUMMY: u8 = const { 0 } }
     DUMMY.with(|x| (x as *const u8).addr())
 }
diff --git a/library/std/src/sys/net/connection/socket.rs b/library/std/src/sys/net/connection/socket.rs
index b4f0a783680..ddd74b42615 100644
--- a/library/std/src/sys/net/connection/socket.rs
+++ b/library/std/src/sys/net/connection/socket.rs
@@ -557,10 +557,13 @@ impl TcpListener {
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
+        // The `accept` function will fill in the storage with the address,
+        // so we don't need to zero it here.
+        // reference: https://linux.die.net/man/2/accept4
+        let mut storage: mem::MaybeUninit<c::sockaddr_storage> = mem::MaybeUninit::uninit();
         let mut len = mem::size_of_val(&storage) as c::socklen_t;
-        let sock = self.inner.accept((&raw mut storage) as *mut _, &mut len)?;
-        let addr = unsafe { socket_addr_from_c(&storage, len as usize)? };
+        let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
+        let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
         Ok((TcpStream { inner: sock }, addr))
     }
 
diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs
index 34ab26bc117..29fb47ddca3 100644
--- a/library/std/src/sys/net/connection/socket/unix.rs
+++ b/library/std/src/sys/net/connection/socket/unix.rs
@@ -322,7 +322,10 @@ impl Socket {
         buf: &mut [u8],
         flags: c_int,
     ) -> io::Result<(usize, SocketAddr)> {
-        let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
+        // The `recvfrom` function will fill in the storage with the address,
+        // so we don't need to zero it here.
+        // reference: https://linux.die.net/man/2/recvfrom
+        let mut storage: mem::MaybeUninit<libc::sockaddr_storage> = mem::MaybeUninit::uninit();
         let mut addrlen = mem::size_of_val(&storage) as libc::socklen_t;
 
         let n = cvt(unsafe {
@@ -335,7 +338,7 @@ impl Socket {
                 &mut addrlen,
             )
         })?;
-        Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? }))
+        Ok((n as usize, unsafe { socket_addr_from_c(storage.as_ptr(), addrlen as usize)? }))
     }
 
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index db5c6bd3a1c..43ece63457f 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -319,21 +319,27 @@ mod imp {
     ))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         let mut ret = None;
-        let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
+        let mut attr: mem::MaybeUninit<libc::pthread_attr_t> = mem::MaybeUninit::uninit();
+        if !cfg!(target_os = "freebsd") {
+            attr = mem::MaybeUninit::zeroed();
+        }
         #[cfg(target_os = "freebsd")]
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+        assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
         #[cfg(target_os = "freebsd")]
-        let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
+        let e = libc::pthread_attr_get_np(libc::pthread_self(), attr.as_mut_ptr());
         #[cfg(not(target_os = "freebsd"))]
-        let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
+        let e = libc::pthread_getattr_np(libc::pthread_self(), attr.as_mut_ptr());
         if e == 0 {
             let mut stackaddr = crate::ptr::null_mut();
             let mut stacksize = 0;
-            assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
+            assert_eq!(
+                libc::pthread_attr_getstack(attr.as_ptr(), &mut stackaddr, &mut stacksize),
+                0
+            );
             ret = Some(stackaddr);
         }
         if e == 0 || cfg!(target_os = "freebsd") {
-            assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+            assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0);
         }
         ret
     }
@@ -509,16 +515,20 @@ mod imp {
     // FIXME: I am probably not unsafe.
     unsafe fn current_guard() -> Option<Range<usize>> {
         let mut ret = None;
-        let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
+
+        let mut attr: mem::MaybeUninit<libc::pthread_attr_t> = mem::MaybeUninit::uninit();
+        if !cfg!(target_os = "freebsd") {
+            attr = mem::MaybeUninit::zeroed();
+        }
         #[cfg(target_os = "freebsd")]
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+        assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
         #[cfg(target_os = "freebsd")]
-        let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
+        let e = libc::pthread_attr_get_np(libc::pthread_self(), attr.as_mut_ptr());
         #[cfg(not(target_os = "freebsd"))]
-        let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
+        let e = libc::pthread_getattr_np(libc::pthread_self(), attr.as_mut_ptr());
         if e == 0 {
             let mut guardsize = 0;
-            assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut guardsize), 0);
+            assert_eq!(libc::pthread_attr_getguardsize(attr.as_ptr(), &mut guardsize), 0);
             if guardsize == 0 {
                 if cfg!(all(target_os = "linux", target_env = "musl")) {
                     // musl versions before 1.1.19 always reported guard
@@ -531,7 +541,7 @@ mod imp {
             }
             let mut stackptr = crate::ptr::null_mut::<libc::c_void>();
             let mut size = 0;
-            assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackptr, &mut size), 0);
+            assert_eq!(libc::pthread_attr_getstack(attr.as_ptr(), &mut stackptr, &mut size), 0);
 
             let stackaddr = stackptr.addr();
             ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) {
@@ -552,7 +562,7 @@ mod imp {
             };
         }
         if e == 0 || cfg!(target_os = "freebsd") {
-            assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+            assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0);
         }
         ret
     }
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 69c99782f0b..37d5e01790a 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -49,24 +49,27 @@ impl Thread {
     pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         let p = Box::into_raw(Box::new(p));
         let mut native: libc::pthread_t = mem::zeroed();
-        let mut attr: libc::pthread_attr_t = mem::zeroed();
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+        let mut attr: mem::MaybeUninit<libc::pthread_attr_t> = mem::MaybeUninit::uninit();
+        assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
 
         #[cfg(target_os = "espidf")]
         if stack > 0 {
             // Only set the stack if a non-zero value is passed
             // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used
             assert_eq!(
-                libc::pthread_attr_setstacksize(&mut attr, cmp::max(stack, min_stack_size(&attr))),
+                libc::pthread_attr_setstacksize(
+                    attr.as_mut_ptr(),
+                    cmp::max(stack, min_stack_size(&attr))
+                ),
                 0
             );
         }
 
         #[cfg(not(target_os = "espidf"))]
         {
-            let stack_size = cmp::max(stack, min_stack_size(&attr));
+            let stack_size = cmp::max(stack, min_stack_size(attr.as_ptr()));
 
-            match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
+            match libc::pthread_attr_setstacksize(attr.as_mut_ptr(), stack_size) {
                 0 => {}
                 n => {
                     assert_eq!(n, libc::EINVAL);
@@ -77,16 +80,16 @@ impl Thread {
                     let page_size = os::page_size();
                     let stack_size =
                         (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
-                    assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+                    assert_eq!(libc::pthread_attr_setstacksize(attr.as_mut_ptr(), stack_size), 0);
                 }
             };
         }
 
-        let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
+        let ret = libc::pthread_create(&mut native, attr.as_ptr(), thread_start, p as *mut _);
         // Note: if the thread creation fails and this assert fails, then p will
         // be leaked. However, an alternative design could cause double-free
         // which is clearly worse.
-        assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+        assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0);
 
         return if ret != 0 {
             // The thread failed to start and as a result p was not consumed. Therefore, it is
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index ca04aa4ada4..d5a5d10205d 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -50,7 +50,8 @@ use crate::fmt;
 /// use std::cell::Cell;
 /// use std::thread;
 ///
-/// thread_local!(static FOO: Cell<u32> = Cell::new(1));
+/// // explicit `const {}` block enables more efficient initialization
+/// thread_local!(static FOO: Cell<u32> = const { Cell::new(1) });
 ///
 /// assert_eq!(FOO.get(), 1);
 /// FOO.set(2);
@@ -138,7 +139,7 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
 /// use std::cell::{Cell, RefCell};
 ///
 /// thread_local! {
-///     pub static FOO: Cell<u32> = Cell::new(1);
+///     pub static FOO: Cell<u32> = const { Cell::new(1) };
 ///
 ///     static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]);
 /// }
@@ -394,7 +395,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// use std::cell::Cell;
     ///
     /// thread_local! {
-    ///     static X: Cell<i32> = Cell::new(1);
+    ///     static X: Cell<i32> = const { Cell::new(1) };
     /// }
     ///
     /// assert_eq!(X.get(), 1);
@@ -423,7 +424,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// use std::cell::Cell;
     ///
     /// thread_local! {
-    ///     static X: Cell<Option<i32>> = Cell::new(Some(1));
+    ///     static X: Cell<Option<i32>> = const { Cell::new(Some(1)) };
     /// }
     ///
     /// assert_eq!(X.take(), Some(1));
@@ -453,7 +454,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// use std::cell::Cell;
     ///
     /// thread_local! {
-    ///     static X: Cell<i32> = Cell::new(1);
+    ///     static X: Cell<i32> = const { Cell::new(1) };
     /// }
     ///
     /// assert_eq!(X.replace(2), 1);