diff options
Diffstat (limited to 'library/std/src')
60 files changed, 313 insertions, 359 deletions
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c5a5991cc81..ec774e62deb 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -93,7 +93,7 @@ pub use alloc_crate::alloc::*; /// /// ```rust /// use std::alloc::{System, GlobalAlloc, Layout}; -/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; /// /// struct Counter; /// @@ -103,14 +103,14 @@ pub use alloc_crate::alloc::*; /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 { /// let ret = System.alloc(layout); /// if !ret.is_null() { -/// ALLOCATED.fetch_add(layout.size(), SeqCst); +/// ALLOCATED.fetch_add(layout.size(), Relaxed); /// } /// ret /// } /// /// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { /// System.dealloc(ptr, layout); -/// ALLOCATED.fetch_sub(layout.size(), SeqCst); +/// ALLOCATED.fetch_sub(layout.size(), Relaxed); /// } /// } /// @@ -118,7 +118,7 @@ pub use alloc_crate::alloc::*; /// static A: Counter = Counter; /// /// fn main() { -/// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst)); +/// println!("allocated bytes before main: {}", ALLOCATED.load(Relaxed)); /// } /// ``` /// diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 42a68496fc4..6640c7fb162 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -709,6 +709,7 @@ impl File { // `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows. impl AsInner<fs_imp::File> for File { + #[inline] fn as_inner(&self) -> &fs_imp::File { &self.inner } @@ -1087,12 +1088,14 @@ impl OpenOptions { } impl AsInner<fs_imp::OpenOptions> for OpenOptions { + #[inline] fn as_inner(&self) -> &fs_imp::OpenOptions { &self.0 } } impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions { + #[inline] fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 } @@ -1352,6 +1355,7 @@ impl fmt::Debug for Metadata { } impl AsInner<fs_imp::FileAttr> for Metadata { + #[inline] fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 } @@ -1604,6 +1608,7 @@ impl FileType { } impl AsInner<fs_imp::FileType> for FileType { + #[inline] fn as_inner(&self) -> &fs_imp::FileType { &self.0 } @@ -1616,6 +1621,7 @@ impl FromInner<fs_imp::FilePermissions> for Permissions { } impl AsInner<fs_imp::FilePermissions> for Permissions { + #[inline] fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 } @@ -1770,6 +1776,7 @@ impl fmt::Debug for DirEntry { } impl AsInner<fs_imp::DirEntry> for DirEntry { + #[inline] fn as_inner(&self) -> &fs_imp::DirEntry { &self.0 } @@ -2284,6 +2291,11 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. /// +/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path. +/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent. +/// +/// Consider ignoring the error if validating the removal is not required for your use case. +/// /// [`fs::remove_file`]: remove_file /// [`fs::remove_dir`]: remove_dir /// @@ -2505,6 +2517,7 @@ impl DirBuilder { } impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder { + #[inline] fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder { &mut self.inner } diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 401def18458..a8a0b9f122d 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -919,6 +919,7 @@ fn symlink_noexist() { #[test] fn read_link() { + let tmpdir = tmpdir(); if cfg!(windows) { // directory symlink assert_eq!(check!(fs::read_link(r"C:\Users\All Users")), Path::new(r"C:\ProgramData")); @@ -933,8 +934,11 @@ fn read_link() { Path::new(r"C:\Users") ); } + // Check that readlink works with non-drive paths on Windows. + let link = tmpdir.join("link_unc"); + check!(symlink_dir(r"\\localhost\c$\", &link)); + assert_eq!(check!(fs::read_link(&link)), Path::new(r"\\localhost\c$\")); } - let tmpdir = tmpdir(); let link = tmpdir.join("link"); if !got_symlink_permission(&tmpdir) { return; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 4cd7885bd4a..9e09ce337bc 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -268,7 +268,7 @@ pub(crate) use self::stdio::attempt_print_to_stderr; #[unstable(feature = "internal_output_capture", issue = "none")] #[doc(no_inline, hidden)] pub use self::stdio::set_output_capture; -#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; #[unstable(feature = "print_internals", issue = "none")] pub use self::stdio::{_eprint, _print}; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index b2c57b8ddc7..9098d36ee53 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1047,7 +1047,7 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) { } /// Trait to determine if a descriptor/handle refers to a terminal/tty. -#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "is_terminal", since = "1.70.0")] pub trait IsTerminal: crate::sealed::Sealed { /// Returns `true` if the descriptor/handle refers to a terminal/tty. /// @@ -1063,7 +1063,7 @@ pub trait IsTerminal: crate::sealed::Sealed { /// Note that this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior - #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_terminal", since = "1.70.0")] fn is_terminal(&self) -> bool; } @@ -1072,7 +1072,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_terminal", since = "1.70.0")] impl IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 4b42ad65ee6..541e95d229b 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -691,6 +691,7 @@ impl Write for &TcpStream { } impl AsInner<net_imp::TcpStream> for TcpStream { + #[inline] fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } @@ -1033,6 +1034,7 @@ impl Iterator for IntoIncoming { impl FusedIterator for IntoIncoming {} impl AsInner<net_imp::TcpListener> for TcpListener { + #[inline] fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 864e1b0f345..9628bcc5108 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -788,6 +788,7 @@ impl UdpSocket { // `AsRawSocket`/`IntoRawSocket`/`FromRawSocket` on Windows. impl AsInner<net_imp::UdpSocket> for UdpSocket { + #[inline] fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 } diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs index 4e88ab8ff5c..fe40d6319c2 100644 --- a/library/std/src/os/android/net.rs +++ b/library/std/src/os/android/net.rs @@ -1,8 +1,8 @@ //! Android-specific networking functionality. -#![stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "unix_socket_abstract", since = "1.70.0")] -#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 6a6e6f33158..2180d2974d5 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -201,7 +201,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_terminal", since = "1.70.0")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs index fcb3bb83485..c8e734d740b 100644 --- a/library/std/src/os/linux/net.rs +++ b/library/std/src/os/linux/net.rs @@ -1,8 +1,8 @@ //! Linux-specific networking functionality. -#![stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "unix_socket_abstract", since = "1.70.0")] -#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 540363c0349..2b3ff76d7a4 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -52,6 +52,7 @@ pub struct PidFd { } impl AsInner<FileDesc> for PidFd { + #[inline] fn as_inner(&self) -> &FileDesc { &self.inner } @@ -70,6 +71,7 @@ impl IntoInner<FileDesc> for PidFd { } impl AsRawFd for PidFd { + #[inline] fn as_raw_fd(&self) -> RawFd { self.as_inner().as_raw_fd() } diff --git a/library/std/src/os/net/linux_ext/addr.rs b/library/std/src/os/net/linux_ext/addr.rs index ea8102c9cc0..aed772056e1 100644 --- a/library/std/src/os/net/linux_ext/addr.rs +++ b/library/std/src/os/net/linux_ext/addr.rs @@ -4,7 +4,7 @@ use crate::os::unix::net::SocketAddr; use crate::sealed::Sealed; /// Platform-specific extensions to [`SocketAddr`]. -#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub trait SocketAddrExt: Sealed { /// Creates a Unix socket address in the abstract namespace. /// @@ -37,7 +37,7 @@ pub trait SocketAddrExt: Sealed { /// Ok(()) /// } /// ``` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] fn from_abstract_name<N>(name: N) -> crate::io::Result<SocketAddr> where N: AsRef<[u8]>; @@ -59,6 +59,6 @@ pub trait SocketAddrExt: Sealed { /// Ok(()) /// } /// ``` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] fn as_abstract_name(&self) -> Option<&[u8]>; } diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs index e7423dce613..62e78cc50d4 100644 --- a/library/std/src/os/net/linux_ext/mod.rs +++ b/library/std/src/os/net/linux_ext/mod.rs @@ -2,7 +2,7 @@ #![doc(cfg(any(target_os = "linux", target_os = "android")))] -#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub(crate) mod addr; #[unstable(feature = "tcp_quickack", issue = "96256")] diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 52a0da5bf1a..6c99e8c3620 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -245,12 +245,12 @@ impl SocketAddr { } } -#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] impl Sealed for SocketAddr {} #[doc(cfg(any(target_os = "android", target_os = "linux")))] #[cfg(any(doc, target_os = "android", target_os = "linux"))] -#[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "unix_socket_abstract", since = "1.70.0")] impl linux_ext::addr::SocketAddrExt for SocketAddr { fn as_abstract_name(&self) -> Option<&[u8]> { if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 41cdcda4613..34db54235f1 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -118,7 +118,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixDatagram> { unsafe { let socket = UnixDatagram::unbound()?; @@ -233,7 +233,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn connect_addr(&self, socket_addr: &SocketAddr) -> io::Result<()> { unsafe { cvt(libc::connect( @@ -532,7 +532,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn send_to_addr(&self, buf: &[u8], socket_addr: &SocketAddr) -> io::Result<usize> { unsafe { let count = cvt(libc::sendto( diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 83f0debe676..5be8aebc70f 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -106,7 +106,7 @@ impl UnixListener { /// Ok(()) /// } /// ``` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 5aa3fb92576..bf2a51b5edb 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -122,7 +122,7 @@ impl UnixStream { /// Ok(()) /// } /// ```` - #[stable(feature = "unix_socket_abstract", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result<UnixStream> { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 11948cecad8..9b77cd8321b 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -389,7 +389,7 @@ macro_rules! impl_is_terminal { #[unstable(feature = "sealed", issue = "none")] impl crate::sealed::Sealed for $t {} - #[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_terminal", since = "1.70.0")] impl crate::io::IsTerminal for $t { #[inline] fn is_terminal(&self) -> bool { diff --git a/library/std/src/path.rs b/library/std/src/path.rs index e5abd02a1bc..198996c5f70 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1395,11 +1395,16 @@ impl PathBuf { /// /// let mut buf = PathBuf::from("/"); /// assert!(buf.file_name() == None); - /// buf.set_file_name("bar"); - /// assert!(buf == PathBuf::from("/bar")); + /// + /// buf.set_file_name("foo.txt"); + /// assert!(buf == PathBuf::from("/foo.txt")); /// assert!(buf.file_name().is_some()); - /// buf.set_file_name("baz.txt"); - /// assert!(buf == PathBuf::from("/baz.txt")); + /// + /// buf.set_file_name("bar.txt"); + /// assert!(buf == PathBuf::from("/bar.txt")); + /// + /// buf.set_file_name("baz"); + /// assert!(buf == PathBuf::from("/baz")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) { @@ -1509,7 +1514,7 @@ impl PathBuf { /// path.as_mut_os_string().push("baz"); /// assert_eq!(path, Path::new("/foo/barbaz")); /// ``` - #[stable(feature = "path_as_mut_os_str", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "path_as_mut_os_str", since = "1.70.0")] #[must_use] #[inline] pub fn as_mut_os_string(&mut self) -> &mut OsString { @@ -2074,7 +2079,7 @@ impl Path { /// path.as_mut_os_str().make_ascii_lowercase(); /// assert_eq!(path, Path::new("foo.txt")); /// ``` - #[stable(feature = "path_as_mut_os_str", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "path_as_mut_os_str", since = "1.70.0")] #[must_use] #[inline] pub fn as_mut_os_str(&mut self) -> &mut OsStr { @@ -2562,7 +2567,8 @@ impl Path { /// ``` /// use std::path::{Path, PathBuf}; /// - /// let path = Path::new("/tmp/foo.txt"); + /// let path = Path::new("/tmp/foo.png"); + /// assert_eq!(path.with_file_name("bar"), PathBuf::from("/tmp/bar")); /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt")); /// /// let path = Path::new("/tmp"); diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 2aefd7c513d..7a7a7737635 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -91,10 +91,10 @@ pub use core::prelude::v1::cfg_eval; )] pub use core::prelude::v1::type_ascribe; -// The file so far is equivalent to src/libcore/prelude/v1.rs, -// and below to src/liballoc/prelude.rs. -// Those files are duplicated rather than using glob imports -// because we want docs to show these re-exports as pointing to within `std`. +// The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated +// rather than glob imported because we want docs to show these re-exports as +// pointing to within `std`. +// Below are the items from the alloc crate. #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 3df990e5dd9..e06ccb5b287 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -1,8 +1,7 @@ // `library/{std,core}/src/primitive_docs.rs` should have the same contents. // These are different files so that relative links work properly without // having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same. -#[cfg_attr(bootstrap, doc(primitive = "bool"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "bool")] +#[rustc_doc_primitive = "bool"] #[doc(alias = "true")] #[doc(alias = "false")] /// The boolean type. @@ -64,8 +63,7 @@ #[stable(feature = "rust1", since = "1.0.0")] mod prim_bool {} -#[cfg_attr(bootstrap, doc(primitive = "never"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "never")] +#[rustc_doc_primitive = "never"] #[doc(alias = "!")] // /// The `!` type, also called "never". @@ -276,8 +274,7 @@ mod prim_bool {} #[unstable(feature = "never_type", issue = "35121")] mod prim_never {} -#[cfg_attr(bootstrap, doc(primitive = "char"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "char")] +#[rustc_doc_primitive = "char"] #[allow(rustdoc::invalid_rust_codeblocks)] /// A character type. /// @@ -401,8 +398,7 @@ mod prim_never {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_char {} -#[cfg_attr(bootstrap, doc(primitive = "unit"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "unit")] +#[rustc_doc_primitive = "unit"] #[doc(alias = "(")] #[doc(alias = ")")] #[doc(alias = "()")] @@ -464,8 +460,7 @@ impl Copy for () { // empty } -#[cfg_attr(bootstrap, doc(primitive = "pointer"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "pointer")] +#[rustc_doc_primitive = "pointer"] #[doc(alias = "ptr")] #[doc(alias = "*")] #[doc(alias = "*const")] @@ -581,8 +576,7 @@ impl Copy for () { #[stable(feature = "rust1", since = "1.0.0")] mod prim_pointer {} -#[cfg_attr(bootstrap, doc(primitive = "array"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "array")] +#[rustc_doc_primitive = "array"] #[doc(alias = "[]")] #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases #[doc(alias = "[T; N]")] @@ -616,6 +610,9 @@ mod prim_pointer {} /// if the element type allows it. As a stopgap, trait implementations are /// statically generated up to size 32. /// +/// Arrays of sizes from 1 to 12 (inclusive) implement [`From<Tuple>`], where `Tuple` +/// is a homogenous [prim@tuple] of appropriate length. +/// /// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on /// an array. Indeed, this provides most of the API for working with arrays. /// @@ -678,6 +675,13 @@ mod prim_pointer {} /// move_away(roa); /// ``` /// +/// Arrays can be created from homogenous tuples of appropriate length: +/// +/// ``` +/// let tuple: (u32, u32, u32) = (1, 2, 3); +/// let array: [u32; 3] = tuple.into(); +/// ``` +/// /// # Editions /// /// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call @@ -780,11 +784,11 @@ mod prim_pointer {} /// [`Borrow`]: borrow::Borrow /// [`BorrowMut`]: borrow::BorrowMut /// [slice pattern]: ../reference/patterns.html#slice-patterns +/// [`From<Tuple>`]: convert::From #[stable(feature = "rust1", since = "1.0.0")] mod prim_array {} -#[cfg_attr(bootstrap, doc(primitive = "slice"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "slice")] +#[rustc_doc_primitive = "slice"] #[doc(alias = "[")] #[doc(alias = "]")] #[doc(alias = "[]")] @@ -876,8 +880,7 @@ mod prim_array {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_slice {} -#[cfg_attr(bootstrap, doc(primitive = "str"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "str")] +#[rustc_doc_primitive = "str"] /// String slices. /// /// *[See also the `std::str` module](crate::str).* @@ -944,8 +947,7 @@ mod prim_slice {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} -#[cfg_attr(bootstrap, doc(primitive = "tuple"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "tuple")] +#[rustc_doc_primitive = "tuple"] #[doc(alias = "(")] #[doc(alias = ")")] #[doc(alias = "()")] @@ -1009,7 +1011,9 @@ mod prim_str {} /// * [`Debug`] /// * [`Default`] /// * [`Hash`] +/// * [`From<[T; N]>`][from] /// +/// [from]: convert::From /// [`Debug`]: fmt::Debug /// [`Hash`]: hash::Hash /// @@ -1060,6 +1064,13 @@ mod prim_str {} /// assert_eq!(y, 5); /// ``` /// +/// Homogenous tuples can be created from arrays of appropriate length: +/// +/// ``` +/// let array: [u32; 3] = [1, 2, 3]; +/// let tuple: (u32, u32, u32) = array.into(); +/// ``` +/// #[stable(feature = "rust1", since = "1.0.0")] mod prim_tuple {} @@ -1088,8 +1099,7 @@ impl<T: Copy> Copy for (T,) { // empty } -#[cfg_attr(bootstrap, doc(primitive = "f32"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "f32")] +#[rustc_doc_primitive = "f32"] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// /// This type can represent a wide range of decimal numbers, like `3.5`, `27`, @@ -1155,8 +1165,7 @@ impl<T: Copy> Copy for (T,) { #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} -#[cfg_attr(bootstrap, doc(primitive = "f64"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "f64")] +#[rustc_doc_primitive = "f64"] /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). /// /// This type is very similar to [`f32`], but has increased @@ -1171,78 +1180,67 @@ mod prim_f32 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} -#[cfg_attr(bootstrap, doc(primitive = "i8"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i8")] +#[rustc_doc_primitive = "i8"] // /// The 8-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i8 {} -#[cfg_attr(bootstrap, doc(primitive = "i16"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i16")] +#[rustc_doc_primitive = "i16"] // /// The 16-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i16 {} -#[cfg_attr(bootstrap, doc(primitive = "i32"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i32")] +#[rustc_doc_primitive = "i32"] // /// The 32-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i32 {} -#[cfg_attr(bootstrap, doc(primitive = "i64"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i64")] +#[rustc_doc_primitive = "i64"] // /// The 64-bit signed integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_i64 {} -#[cfg_attr(bootstrap, doc(primitive = "i128"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "i128")] +#[rustc_doc_primitive = "i128"] // /// The 128-bit signed integer type. #[stable(feature = "i128", since = "1.26.0")] mod prim_i128 {} -#[cfg_attr(bootstrap, doc(primitive = "u8"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u8")] +#[rustc_doc_primitive = "u8"] // /// The 8-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u8 {} -#[cfg_attr(bootstrap, doc(primitive = "u16"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u16")] +#[rustc_doc_primitive = "u16"] // /// The 16-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u16 {} -#[cfg_attr(bootstrap, doc(primitive = "u32"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u32")] +#[rustc_doc_primitive = "u32"] // /// The 32-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u32 {} -#[cfg_attr(bootstrap, doc(primitive = "u64"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u64")] +#[rustc_doc_primitive = "u64"] // /// The 64-bit unsigned integer type. #[stable(feature = "rust1", since = "1.0.0")] mod prim_u64 {} -#[cfg_attr(bootstrap, doc(primitive = "u128"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "u128")] +#[rustc_doc_primitive = "u128"] // /// The 128-bit unsigned integer type. #[stable(feature = "i128", since = "1.26.0")] mod prim_u128 {} -#[cfg_attr(bootstrap, doc(primitive = "isize"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "isize")] +#[rustc_doc_primitive = "isize"] // /// The pointer-sized signed integer type. /// @@ -1252,8 +1250,7 @@ mod prim_u128 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_isize {} -#[cfg_attr(bootstrap, doc(primitive = "usize"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "usize")] +#[rustc_doc_primitive = "usize"] // /// The pointer-sized unsigned integer type. /// @@ -1263,8 +1260,7 @@ mod prim_isize {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_usize {} -#[cfg_attr(bootstrap, doc(primitive = "reference"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "reference")] +#[rustc_doc_primitive = "reference"] #[doc(alias = "&")] #[doc(alias = "&mut")] // @@ -1396,8 +1392,7 @@ mod prim_usize {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_ref {} -#[cfg_attr(bootstrap, doc(primitive = "fn"))] -#[cfg_attr(not(bootstrap), rustc_doc_primitive = "fn")] +#[rustc_doc_primitive = "fn"] // /// Function pointers, like `fn(usize) -> bool`. /// diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 0ab72f7ea7a..bf22c2d46c9 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -211,6 +211,7 @@ pub struct Child { impl crate::sealed::Sealed for Child {} impl AsInner<imp::Process> for Child { + #[inline] fn as_inner(&self) -> &imp::Process { &self.handle } @@ -304,6 +305,7 @@ impl Write for &ChildStdin { } impl AsInner<AnonPipe> for ChildStdin { + #[inline] fn as_inner(&self) -> &AnonPipe { &self.inner } @@ -373,6 +375,7 @@ impl Read for ChildStdout { } impl AsInner<AnonPipe> for ChildStdout { + #[inline] fn as_inner(&self) -> &AnonPipe { &self.inner } @@ -438,6 +441,7 @@ impl Read for ChildStderr { } impl AsInner<AnonPipe> for ChildStderr { + #[inline] fn as_inner(&self) -> &AnonPipe { &self.inner } @@ -1107,12 +1111,14 @@ impl fmt::Debug for Command { } impl AsInner<imp::Command> for Command { + #[inline] fn as_inner(&self) -> &imp::Command { &self.inner } } impl AsInnerMut<imp::Command> for Command { + #[inline] fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner } @@ -1605,6 +1611,7 @@ impl ExitStatus { } impl AsInner<imp::ExitStatus> for ExitStatus { + #[inline] fn as_inner(&self) -> &imp::ExitStatus { &self.0 } @@ -1884,6 +1891,7 @@ impl From<u8> for ExitCode { } impl AsInner<imp::ExitCode> for ExitCode { + #[inline] fn as_inner(&self) -> &imp::ExitCode { &self.0 } diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 19641753ffe..f6a7c0a9f75 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -177,7 +177,7 @@ pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; #[unstable(feature = "lazy_cell", issue = "109736")] pub use self::lazy_lock::LazyLock; -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] pub use self::once_lock::OnceLock; pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard}; diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 36951c4f13e..e83bc35ee98 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -30,7 +30,7 @@ use crate::sync::Once; /// assert!(value.is_some()); /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); /// ``` -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] pub struct OnceLock<T> { once: Once, // Whether or not the value is initialized is tracked by `once.is_completed()`. @@ -59,8 +59,8 @@ impl<T> OnceLock<T> { /// Creates a new empty cell. #[inline] #[must_use] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] + #[rustc_const_stable(feature = "once_cell", since = "1.70.0")] pub const fn new() -> OnceLock<T> { OnceLock { once: Once::new(), @@ -74,7 +74,7 @@ impl<T> OnceLock<T> { /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. #[inline] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get(&self) -> Option<&T> { if self.is_initialized() { // Safe b/c checked is_initialized @@ -88,7 +88,7 @@ impl<T> OnceLock<T> { /// /// Returns `None` if the cell is empty. This method never blocks. #[inline] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_mut(&mut self) -> Option<&mut T> { if self.is_initialized() { // Safe b/c checked is_initialized and we have a unique access @@ -124,7 +124,7 @@ impl<T> OnceLock<T> { /// } /// ``` #[inline] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn set(&self, value: T) -> Result<(), T> { let mut value = Some(value); self.get_or_init(|| value.take().unwrap()); @@ -162,7 +162,7 @@ impl<T> OnceLock<T> { /// assert_eq!(value, &92); /// ``` #[inline] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_or_init<F>(&self, f: F) -> &T where F: FnOnce() -> T, @@ -239,7 +239,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn into_inner(mut self) -> Option<T> { self.take() } @@ -264,7 +264,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.get(), None); /// ``` #[inline] - #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "once_cell", since = "1.70.0")] pub fn take(&mut self) -> Option<T> { if self.is_initialized() { self.once = Once::new(); @@ -333,17 +333,17 @@ impl<T> OnceLock<T> { // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] unsafe impl<T: Sync + Send> Sync for OnceLock<T> {} -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] unsafe impl<T: Send> Send for OnceLock<T> {} -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {} -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {} -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T> Default for OnceLock<T> { /// Creates a new empty cell. /// @@ -362,7 +362,7 @@ impl<T> Default for OnceLock<T> { } } -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -372,7 +372,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { } } -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: Clone> Clone for OnceLock<T> { #[inline] fn clone(&self) -> OnceLock<T> { @@ -387,7 +387,7 @@ impl<T: Clone> Clone for OnceLock<T> { } } -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T> From<T> for OnceLock<T> { /// Create a new cell with its contents set to `value`. /// @@ -414,7 +414,7 @@ impl<T> From<T> for OnceLock<T> { } } -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: PartialEq> PartialEq for OnceLock<T> { #[inline] fn eq(&self, other: &OnceLock<T>) -> bool { @@ -422,10 +422,10 @@ impl<T: PartialEq> PartialEq for OnceLock<T> { } } -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] impl<T: Eq> Eq for OnceLock<T> {} -#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_cell", since = "1.70.0")] unsafe impl<#[may_dangle] T> Drop for OnceLock<T> { #[inline] fn drop(&mut self) { diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs index 914e017f7ff..447044a798b 100644 --- a/library/std/src/sys/common/thread_local/fast_local.rs +++ b/library/std/src/sys/common/thread_local/fast_local.rs @@ -11,7 +11,7 @@ use crate::{fmt, mem, panic}; 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)] + #[inline] #[deny(unsafe_op_in_unsafe_fn)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, @@ -78,7 +78,7 @@ pub macro thread_local_inner { #[inline] fn __init() -> $t { $init } - #[cfg_attr(not(bootstrap), inline)] + #[inline] unsafe fn __getit( init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index a7528c06c9d..951d509ec95 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -6,7 +6,7 @@ cfg_if::cfg_if! { mod static_local; #[doc(hidden)] pub use static_local::{Key, thread_local_inner}; - } else if #[cfg(all(target_thread_local))] { + } else if #[cfg(target_thread_local)] { #[doc(hidden)] mod fast_local; #[doc(hidden)] diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs index e9516f9983f..d004897df28 100644 --- a/library/std/src/sys/common/thread_local/os_local.rs +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -11,7 +11,7 @@ use crate::{fmt, marker, panic, ptr}; 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)] + #[inline] #[deny(unsafe_op_in_unsafe_fn)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs index 3a2cdd301ea..ccde05aa1d7 100644 --- a/library/std/src/sys/hermit/fd.rs +++ b/library/std/src/sys/hermit/fd.rs @@ -75,6 +75,7 @@ impl FromRawFd for FileDesc { } impl AsInner<OwnedFd> for FileDesc { + #[inline] fn as_inner(&self) -> &OwnedFd { &self.fd } diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index cf0b271761f..4bb735668d2 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -367,12 +367,14 @@ impl DirBuilder { } impl AsInner<FileDesc> for File { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } } impl AsInnerMut<FileDesc> for File { + #[inline] fn as_inner_mut(&mut self) -> &mut FileDesc { &mut self.0 } @@ -397,6 +399,7 @@ impl AsFd for File { } impl AsRawFd for File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index d6f64a29719..8c2d489d6a3 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -340,6 +340,7 @@ impl Socket { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } @@ -364,6 +365,7 @@ impl AsFd for Socket { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/sgx/fd.rs b/library/std/src/sys/sgx/fd.rs index 0c02a107691..b3686d0e283 100644 --- a/library/std/src/sys/sgx/fd.rs +++ b/library/std/src/sys/sgx/fd.rs @@ -62,6 +62,7 @@ impl FileDesc { } impl AsInner<Fd> for FileDesc { + #[inline] fn as_inner(&self) -> &Fd { &self.fd } diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 923be5eb944..03620a08f2c 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -24,6 +24,7 @@ impl Socket { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.inner } @@ -220,6 +221,7 @@ impl TcpStream { } impl AsInner<Socket> for TcpStream { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } @@ -304,6 +306,7 @@ impl TcpListener { } impl AsInner<Socket> for TcpListener { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 7d7bfae1432..0bd2bc3b961 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -112,6 +112,7 @@ impl FileDesc { } impl AsInner<c_int> for FileDesc { + #[inline] fn as_inner(&self) -> &c_int { &self.fd } @@ -462,6 +463,7 @@ impl Socket { } impl AsInner<c_int> for Socket { + #[inline] fn as_inner(&self) -> &c_int { self.0.as_inner() } diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index ce5c048f252..45f96478fc3 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -481,6 +481,7 @@ impl<'a> Read for &'a FileDesc { } impl AsInner<OwnedFd> for FileDesc { + #[inline] fn as_inner(&self) -> &OwnedFd { &self.0 } @@ -505,6 +506,7 @@ impl AsFd for FileDesc { } impl AsRawFd for FileDesc { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index abef170dd5a..b398fd5eb24 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -547,6 +547,7 @@ impl FileAttr { } impl AsInner<stat64> for FileAttr { + #[inline] fn as_inner(&self) -> &stat64 { &self.stat } @@ -1193,8 +1194,6 @@ impl File { None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), } }; - #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))] - let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; cfg_if::cfg_if! { if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] { // Redox doesn't appear to support `UTIME_OMIT`. @@ -1206,6 +1205,7 @@ impl File { "setting file times not supported", )) } else if #[cfg(any(target_os = "android", target_os = "macos"))] { + let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; // futimens requires macOS 10.13, and Android API level 19 cvt(unsafe { weak!(fn futimens(c_int, *const libc::timespec) -> c_int); @@ -1232,6 +1232,22 @@ impl File { })?; Ok(()) } else { + #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))] + { + use crate::sys::{time::__timespec64, weak::weak}; + + // Added in glibc 2.34 + weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int); + + if let Some(futimens64) = __futimens64.get() { + let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64()) + .unwrap_or(__timespec64::new(0, libc::UTIME_OMIT as _)); + let times = [to_timespec(times.accessed), to_timespec(times.modified)]; + cvt(unsafe { futimens64(self.as_raw_fd(), times.as_ptr()) })?; + return Ok(()); + } + } + let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; cvt(unsafe { libc::futimens(self.as_raw_fd(), times.as_ptr()) })?; Ok(()) } @@ -1254,12 +1270,14 @@ impl DirBuilder { } impl AsInner<FileDesc> for File { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } } impl AsInnerMut<FileDesc> for File { + #[inline] fn as_inner_mut(&mut self) -> &mut FileDesc { &mut self.0 } @@ -1284,6 +1302,7 @@ impl AsFd for File { } impl AsRawFd for File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs index 9967588939a..ee016887e70 100644 --- a/library/std/src/sys/unix/l4re.rs +++ b/library/std/src/sys/unix/l4re.rs @@ -129,6 +129,7 @@ pub mod net { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } @@ -153,6 +154,7 @@ pub mod net { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } @@ -183,6 +185,7 @@ pub mod net { unimpl!(); } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -305,6 +308,7 @@ pub mod net { unimpl!(); } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -371,6 +375,7 @@ pub mod net { unimpl!(); } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 573bfa6587e..39edb136c24 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -490,6 +490,7 @@ impl Socket { } impl AsInner<FileDesc> for Socket { + #[inline] fn as_inner(&self) -> &FileDesc { &self.0 } @@ -514,6 +515,7 @@ impl AsFd for Socket { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs index 017e2af29d4..488217f3941 100644 --- a/library/std/src/sys/unix/os_str.rs +++ b/library/std/src/sys/unix/os_str.rs @@ -89,6 +89,7 @@ impl IntoInner<Vec<u8>> for Buf { } impl AsInner<[u8]> for Buf { + #[inline] fn as_inner(&self) -> &[u8] { &self.inner } diff --git a/library/std/src/sys/unix/pipe.rs b/library/std/src/sys/unix/pipe.rs index dc17c9fac46..938a46bfdd8 100644 --- a/library/std/src/sys/unix/pipe.rs +++ b/library/std/src/sys/unix/pipe.rs @@ -135,6 +135,7 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> } impl AsRawFd for AnonPipe { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 6f53583409d..a61d926ca8b 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -166,6 +166,16 @@ impl Timespec { } self.to_timespec() } + + #[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") + ))] + pub fn to_timespec64(&self) -> __timespec64 { + __timespec64::new(self.tv_sec, self.tv_nsec.0 as _) + } } impl From<libc::timespec> for Timespec { @@ -196,6 +206,18 @@ pub(in crate::sys::unix) struct __timespec64 { target_pointer_width = "32", not(target_arch = "riscv32") ))] +impl __timespec64 { + pub(in crate::sys::unix) fn new(tv_sec: i64, tv_nsec: i32) -> Self { + Self { tv_sec, tv_nsec, _padding: 0 } + } +} + +#[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") +))] impl From<__timespec64> for Timespec { fn from(t: __timespec64) -> Timespec { Timespec::new(t.tv_sec, t.tv_nsec.into()) diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs index 15b22c620d5..e1a38de6471 100644 --- a/library/std/src/sys/unsupported/mod.rs +++ b/library/std/src/sys/unsupported/mod.rs @@ -22,6 +22,7 @@ pub mod thread; #[cfg(target_thread_local)] pub mod thread_local_dtor; pub mod thread_local_key; +pub mod thread_parking; pub mod time; mod common; diff --git a/library/std/src/sys/unsupported/thread_parking.rs b/library/std/src/sys/unsupported/thread_parking.rs new file mode 100644 index 00000000000..197078bb186 --- /dev/null +++ b/library/std/src/sys/unsupported/thread_parking.rs @@ -0,0 +1,11 @@ +use crate::pin::Pin; +use crate::time::Duration; + +pub struct Parker {} + +impl Parker { + pub unsafe fn new_in_place(_parker: *mut Parker) {} + pub unsafe fn park(self: Pin<&Self>) {} + pub unsafe fn park_timeout(self: Pin<&Self>, _dur: Duration) {} + pub fn unpark(self: Pin<&Self>) {} +} diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index 191db4b60f7..9a8b2a0be5b 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -275,12 +275,14 @@ impl WasiFd { } impl AsInner<OwnedFd> for WasiFd { + #[inline] fn as_inner(&self) -> &OwnedFd { &self.fd } } impl AsInnerMut<OwnedFd> for WasiFd { + #[inline] fn as_inner_mut(&mut self) -> &mut OwnedFd { &mut self.fd } @@ -305,6 +307,7 @@ impl AsFd for WasiFd { } impl AsRawFd for WasiFd { + #[inline] fn as_raw_fd(&self) -> RawFd { self.fd.as_raw_fd() } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 3a205267e34..8d1dbf59155 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -498,6 +498,7 @@ impl File { } impl AsInner<WasiFd> for File { + #[inline] fn as_inner(&self) -> &WasiFd { &self.fd } @@ -522,6 +523,7 @@ impl AsFd for File { } impl AsRawFd for File { + #[inline] fn as_raw_fd(&self) -> RawFd { self.fd.as_raw_fd() } diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index c468ae395fc..a2223708024 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -47,6 +47,8 @@ pub mod thread; pub mod thread_local_dtor; #[path = "../unsupported/thread_local_key.rs"] pub mod thread_local_key; +#[path = "../unsupported/thread_parking.rs"] +pub mod thread_parking; pub mod time; cfg_if::cfg_if! { diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 59d94a3686d..2239880ffbe 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -17,6 +17,7 @@ pub struct TcpStream { } impl AsInner<WasiFd> for Socket { + #[inline] fn as_inner(&self) -> &WasiFd { &self.0 } @@ -41,6 +42,7 @@ impl AsFd for Socket { } impl AsRawFd for Socket { + #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } @@ -184,6 +186,7 @@ impl TcpStream { } } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -274,6 +277,7 @@ impl TcpListener { } } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -284,6 +288,7 @@ impl TcpListener { } impl AsInner<Socket> for TcpListener { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } @@ -436,6 +441,7 @@ impl UdpSocket { unsupported() } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -446,6 +452,7 @@ impl UdpSocket { } impl AsInner<Socket> for UdpSocket { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs index 77ebe3c4ac6..6c05b56e1bf 100644 --- a/library/std/src/sys/wasm/mod.rs +++ b/library/std/src/sys/wasm/mod.rs @@ -70,6 +70,8 @@ cfg_if::cfg_if! { pub mod once; #[path = "../unsupported/thread.rs"] pub mod thread; + #[path = "../unsupported/thread_parking.rs"] + pub mod thread_parking; } } diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs index 43c0cdb657e..5bfd8b52ed0 100644 --- a/library/std/src/sys/windows/args.rs +++ b/library/std/src/sys/windows/args.rs @@ -313,6 +313,9 @@ pub(crate) fn make_bat_command_line( /// /// This is necessary because cmd.exe does not support verbatim paths. pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> { + from_wide_to_user_path(to_u16s(path)?) +} +pub(crate) fn from_wide_to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { use crate::ptr; use crate::sys::windows::fill_utf16_buf; @@ -325,8 +328,6 @@ pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> { const N: u16 = b'N' as _; const C: u16 = b'C' as _; - let mut path = to_u16s(path)?; - // Early return if the path is too long to remove the verbatim prefix. const LEGACY_MAX_PATH: usize = 260; if path.len() > LEGACY_MAX_PATH { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 956db577d53..fe052c8281b 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -477,7 +477,7 @@ impl File { fn reparse_point( &self, space: &mut Align8<[MaybeUninit<u8>]>, - ) -> io::Result<(c::DWORD, *const c::REPARSE_DATA_BUFFER)> { + ) -> io::Result<(c::DWORD, *mut c::REPARSE_DATA_BUFFER)> { unsafe { let mut bytes = 0; cvt({ @@ -496,7 +496,7 @@ impl File { ) })?; const _: () = assert!(core::mem::align_of::<c::REPARSE_DATA_BUFFER>() <= 8); - Ok((bytes, space.0.as_ptr().cast::<c::REPARSE_DATA_BUFFER>())) + Ok((bytes, space.0.as_mut_ptr().cast::<c::REPARSE_DATA_BUFFER>())) } } @@ -506,22 +506,22 @@ impl File { unsafe { let (path_buffer, subst_off, subst_len, relative) = match (*buf).ReparseTag { c::IO_REPARSE_TAG_SYMLINK => { - let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER = - ptr::addr_of!((*buf).rest).cast(); + let info: *mut c::SYMBOLIC_LINK_REPARSE_BUFFER = + ptr::addr_of_mut!((*buf).rest).cast(); assert!(info.is_aligned()); ( - ptr::addr_of!((*info).PathBuffer).cast::<u16>(), + ptr::addr_of_mut!((*info).PathBuffer).cast::<u16>(), (*info).SubstituteNameOffset / 2, (*info).SubstituteNameLength / 2, (*info).Flags & c::SYMLINK_FLAG_RELATIVE != 0, ) } c::IO_REPARSE_TAG_MOUNT_POINT => { - let info: *const c::MOUNT_POINT_REPARSE_BUFFER = - ptr::addr_of!((*buf).rest).cast(); + let info: *mut c::MOUNT_POINT_REPARSE_BUFFER = + ptr::addr_of_mut!((*buf).rest).cast(); assert!(info.is_aligned()); ( - ptr::addr_of!((*info).PathBuffer).cast::<u16>(), + ptr::addr_of_mut!((*info).PathBuffer).cast::<u16>(), (*info).SubstituteNameOffset / 2, (*info).SubstituteNameLength / 2, false, @@ -535,13 +535,20 @@ impl File { } }; let subst_ptr = path_buffer.add(subst_off.into()); - let mut subst = slice::from_raw_parts(subst_ptr, subst_len as usize); + let subst = slice::from_raw_parts_mut(subst_ptr, subst_len as usize); // Absolute paths start with an NT internal namespace prefix `\??\` // We should not let it leak through. if !relative && subst.starts_with(&[92u16, 63u16, 63u16, 92u16]) { - subst = &subst[4..]; + // Turn `\??\` into `\\?\` (a verbatim path). + subst[1] = b'\\' as u16; + // Attempt to convert to a more user-friendly path. + let user = super::args::from_wide_to_user_path( + subst.iter().copied().chain([0]).collect(), + )?; + Ok(PathBuf::from(OsString::from_wide(&user.strip_suffix(&[0]).unwrap_or(&user)))) + } else { + Ok(PathBuf::from(OsString::from_wide(subst))) } - Ok(PathBuf::from(OsString::from_wide(subst))) } } @@ -832,6 +839,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result< } impl AsInner<Handle> for File { + #[inline] fn as_inner(&self) -> &Handle { &self.handle } @@ -1132,26 +1140,29 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io &dir, &name, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY, - )?; - dirlist.push(child_dir); - } else { - for i in 1..=MAX_RETRIES { - let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); - match result { - Ok(f) => delete(&f)?, - // Already deleted, so skip. - Err(e) if e.kind() == io::ErrorKind::NotFound => break, - // Retry a few times if the file is locked or a delete is already in progress. - Err(e) - if i < MAX_RETRIES - && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) - || e.raw_os_error() - == Some(c::ERROR_SHARING_VIOLATION as _)) => {} - // Otherwise return the error. - Err(e) => return Err(e), - } - thread::yield_now(); + ); + // On success, add the handle to the queue. + // If opening the directory fails we treat it the same as a file + if let Ok(child_dir) = child_dir { + dirlist.push(child_dir); + continue; + } + } + for i in 1..=MAX_RETRIES { + let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); + match result { + Ok(f) => delete(&f)?, + // Already deleted, so skip. + Err(e) if e.kind() == io::ErrorKind::NotFound => break, + // Retry a few times if the file is locked or a delete is already in progress. + Err(e) + if i < MAX_RETRIES + && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) + || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {} + // Otherwise return the error. + Err(e) => return Err(e), } + thread::yield_now(); } } // If there were no more files then delete the directory. diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index b290f4070e8..c7677d1c13a 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -34,6 +34,7 @@ impl Handle { } impl AsInner<OwnedHandle> for Handle { + #[inline] fn as_inner(&self) -> &OwnedHandle { &self.0 } diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index ee1f5482b47..8158713fa84 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -446,6 +446,7 @@ impl<'a> Read for &'a Socket { } impl AsInner<OwnedSocket> for Socket { + #[inline] fn as_inner(&self) -> &OwnedSocket { &self.0 } diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs index 4bdd8c505ff..2f2b0e56e08 100644 --- a/library/std/src/sys/windows/os_str.rs +++ b/library/std/src/sys/windows/os_str.rs @@ -27,6 +27,7 @@ impl FromInner<Wtf8Buf> for Buf { } impl AsInner<Wtf8> for Buf { + #[inline] fn as_inner(&self) -> &Wtf8 { &self.inner } diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index cb24caa1e8a..652c695fc57 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -239,6 +239,7 @@ impl TcpStream { Ok(TcpStream { inner: sock }) } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -352,6 +353,7 @@ impl TcpStream { } impl AsInner<Socket> for TcpStream { + #[inline] fn as_inner(&self) -> &Socket { &self.inner } @@ -427,6 +429,7 @@ impl TcpListener { Ok(TcpListener { inner: sock }) } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } @@ -517,6 +520,7 @@ impl UdpSocket { Ok(UdpSocket { inner: sock }) } + #[inline] pub fn socket(&self) -> &Socket { &self.inner } diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs index 89360e45601..204834984a2 100644 --- a/library/std/src/sys_common/thread_local_key.rs +++ b/library/std/src/sys_common/thread_local_key.rs @@ -87,31 +87,6 @@ pub struct StaticKey { dtor: Option<unsafe extern "C" fn(*mut u8)>, } -/// A type for a safely managed OS-based TLS slot. -/// -/// This type allocates an OS TLS key when it is initialized and will deallocate -/// the key when it falls out of scope. When compared with `StaticKey`, this -/// type is entirely safe to use. -/// -/// Implementations will likely, however, contain unsafe code as this type only -/// operates on `*mut u8`, a raw pointer. -/// -/// # Examples -/// -/// ```ignore (cannot-doctest-private-modules) -/// use tls::os::Key; -/// -/// let key = Key::new(None); -/// assert!(key.get().is_null()); -/// key.set(1 as *mut u8); -/// assert!(!key.get().is_null()); -/// -/// drop(key); // deallocate this TLS slot. -/// ``` -pub struct Key { - key: imp::Key, -} - /// Constant initialization value for static TLS keys. /// /// This value specifies no destructor by default. @@ -194,39 +169,3 @@ impl StaticKey { } } } - -impl Key { - /// Creates a new managed OS TLS key. - /// - /// This key will be deallocated when the key falls out of scope. - /// - /// The argument provided is an optionally-specified destructor for the - /// value of this TLS key. When a thread exits and the value for this key - /// is non-null the destructor will be invoked. The TLS value will be reset - /// to null before the destructor is invoked. - /// - /// Note that the destructor will not be run when the `Key` goes out of - /// scope. - #[inline] - pub fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key { - Key { key: unsafe { imp::create(dtor) } } - } - - /// See StaticKey::get - #[inline] - pub fn get(&self) -> *mut u8 { - unsafe { imp::get(self.key) } - } - - /// See StaticKey::set - #[inline] - pub fn set(&self, val: *mut u8) { - unsafe { imp::set(self.key, val) } - } -} - -impl Drop for Key { - fn drop(&mut self) { - unsafe { imp::destroy(self.key) } - } -} diff --git a/library/std/src/sys_common/thread_local_key/tests.rs b/library/std/src/sys_common/thread_local_key/tests.rs index 6f32b858f09..6a44c65d918 100644 --- a/library/std/src/sys_common/thread_local_key/tests.rs +++ b/library/std/src/sys_common/thread_local_key/tests.rs @@ -1,24 +1,6 @@ -use super::{Key, StaticKey}; +use super::StaticKey; use core::ptr; -fn assert_sync<T: Sync>() {} -fn assert_send<T: Send>() {} - -#[test] -fn smoke() { - assert_sync::<Key>(); - assert_send::<Key>(); - - let k1 = Key::new(None); - let k2 = Key::new(None); - assert!(k1.get().is_null()); - assert!(k2.get().is_null()); - k1.set(ptr::invalid_mut(1)); - k2.set(ptr::invalid_mut(2)); - assert_eq!(k1.get() as usize, 1); - assert_eq!(k2.get() as usize, 2); -} - #[test] fn statik() { static K1: StaticKey = StaticKey::new(None); diff --git a/library/std/src/sys_common/thread_parking/generic.rs b/library/std/src/sys_common/thread_parking/generic.rs deleted file mode 100644 index 3209bffe353..00000000000 --- a/library/std/src/sys_common/thread_parking/generic.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! Parker implementation based on a Mutex and Condvar. - -use crate::pin::Pin; -use crate::sync::atomic::AtomicUsize; -use crate::sync::atomic::Ordering::SeqCst; -use crate::sync::{Condvar, Mutex}; -use crate::time::Duration; - -const EMPTY: usize = 0; -const PARKED: usize = 1; -const NOTIFIED: usize = 2; - -pub struct Parker { - state: AtomicUsize, - lock: Mutex<()>, - cvar: Condvar, -} - -impl Parker { - /// Construct the generic parker. The UNIX parker implementation - /// requires this to happen in-place. - pub unsafe fn new_in_place(parker: *mut Parker) { - parker.write(Parker { - state: AtomicUsize::new(EMPTY), - lock: Mutex::new(()), - cvar: Condvar::new(), - }); - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park(self: Pin<&Self>) { - // If we were previously notified then we consume this notification and - // return quickly. - if self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() { - return; - } - - // Otherwise we need to coordinate going to sleep - let mut m = self.lock.lock().unwrap(); - match self.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { - Ok(_) => {} - Err(NOTIFIED) => { - // We must read here, even though we know it will be `NOTIFIED`. - // This is because `unpark` may have been called again since we read - // `NOTIFIED` in the `compare_exchange` above. We must perform an - // acquire operation that synchronizes with that `unpark` to observe - // any writes it made before the call to unpark. To do that we must - // read from the write it made to `state`. - let old = self.state.swap(EMPTY, SeqCst); - assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); - return; - } // should consume this notification, so prohibit spurious wakeups in next park. - Err(_) => panic!("inconsistent park state"), - } - loop { - m = self.cvar.wait(m).unwrap(); - match self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst) { - Ok(_) => return, // got a notification - Err(_) => {} // spurious wakeup, go back to sleep - } - } - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { - // Like `park` above we have a fast path for an already-notified thread, and - // afterwards we start coordinating for a sleep. - // return quickly. - if self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() { - return; - } - let m = self.lock.lock().unwrap(); - match self.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { - Ok(_) => {} - Err(NOTIFIED) => { - // We must read again here, see `park`. - let old = self.state.swap(EMPTY, SeqCst); - assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); - return; - } // should consume this notification, so prohibit spurious wakeups in next park. - Err(_) => panic!("inconsistent park_timeout state"), - } - - // Wait with a timeout, and if we spuriously wake up or otherwise wake up - // from a notification we just want to unconditionally set the state back to - // empty, either consuming a notification or un-flagging ourselves as - // parked. - let (_m, _result) = self.cvar.wait_timeout(m, dur).unwrap(); - match self.state.swap(EMPTY, SeqCst) { - NOTIFIED => {} // got a notification, hurray! - PARKED => {} // no notification, alas - n => panic!("inconsistent park_timeout state: {n}"), - } - } - - // This implementation doesn't require `Pin`, but other implementations do. - pub fn unpark(self: Pin<&Self>) { - // To ensure the unparked thread will observe any writes we made - // before this call, we must perform a release operation that `park` - // can synchronize with. To do that we must write `NOTIFIED` even if - // `state` is already `NOTIFIED`. That is why this must be a swap - // rather than a compare-and-swap that returns if it reads `NOTIFIED` - // on failure. - match self.state.swap(NOTIFIED, SeqCst) { - EMPTY => return, // no one was waiting - NOTIFIED => return, // already unparked - PARKED => {} // gotta go wake someone up - _ => panic!("inconsistent state in unpark"), - } - - // There is a period between when the parked thread sets `state` to - // `PARKED` (or last checked `state` in the case of a spurious wake - // up) and when it actually waits on `cvar`. If we were to notify - // during this period it would be ignored and then when the parked - // thread went to sleep it would never wake up. Fortunately, it has - // `lock` locked at this stage so we can acquire `lock` to wait until - // it is ready to receive the notification. - // - // Releasing `lock` before the call to `notify_one` means that when the - // parked thread wakes it doesn't get woken only to have to wait for us - // to release `lock`. - drop(self.lock.lock().unwrap()); - self.cvar.notify_one() - } -} diff --git a/library/std/src/sys_common/thread_parking/mod.rs b/library/std/src/sys_common/thread_parking/mod.rs index e8e028bb330..c4d3f9ea2f4 100644 --- a/library/std/src/sys_common/thread_parking/mod.rs +++ b/library/std/src/sys_common/thread_parking/mod.rs @@ -18,10 +18,7 @@ cfg_if::cfg_if! { ))] { mod id; pub use id::Parker; - } else if #[cfg(any(windows, target_family = "unix"))] { - pub use crate::sys::thread_parking::Parker; } else { - mod generic; - pub use generic::Parker; + pub use crate::sys::thread_parking::Parker; } } diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index bc588bdbb3c..ff96c35fb0b 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -501,6 +501,7 @@ pub struct Wtf8 { } impl AsInner<[u8]> for Wtf8 { + #[inline] fn as_inner(&self) -> &[u8] { &self.bytes } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index fa08fdc1653..3b7c31826b9 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -134,10 +134,28 @@ impl<T: 'static> fmt::Debug for LocalKey<T> { /// thread_local! { /// pub static FOO: RefCell<u32> = RefCell::new(1); /// -/// #[allow(unused)] /// static BAR: RefCell<f32> = RefCell::new(1.0); /// } -/// # fn main() {} +/// +/// FOO.with(|foo| assert_eq!(*foo.borrow(), 1)); +/// BAR.with(|bar| assert_eq!(*bar.borrow(), 1.0)); +/// ``` +/// +/// This macro supports a special `const {}` syntax that can be used +/// when the initialization expression can be evaluated as a constant. +/// This can enable a more efficient thread local implementation that +/// can avoid lazy initialization. For types that do not +/// [need to be dropped][crate::mem::needs_drop], this can enable an +/// even more efficient implementation that does not need to +/// track any additional state. +/// +/// ``` +/// use std::cell::Cell; +/// thread_local! { +/// pub static FOO: Cell<u32> = const { Cell::new(1) }; +/// } +/// +/// FOO.with(|foo| assert_eq!(foo.get(), 1)); /// ``` /// /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 5c2e9da70fb..00e2857a137 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -119,7 +119,7 @@ pub use core::time::TryFromFloatSecsError; /// [QueryPerformanceCounter]: https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode -/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get +/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime /// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html /// @@ -224,7 +224,7 @@ pub struct Instant(time::Instant); /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode /// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html /// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime -/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get +/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get /// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime /// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime /// |
