From c496af64edf92e9e77f02fa552cd69019f7b2c35 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 8 Nov 2024 20:29:07 +0000 Subject: [PATCH 01/11] Add as_slice/into_slice for IoSlice/IoSliceMut. Co-authored-by: Mike Pedersen Co-authored-by: Nathan West --- library/std/src/io/mod.rs | 45 +++++++++++++++++++++++ library/std/src/io/tests.rs | 14 +++++++ library/std/src/sys/pal/hermit/io.rs | 7 +++- library/std/src/sys/pal/solid/io.rs | 7 +++- library/std/src/sys/pal/unix/io.rs | 7 +++- library/std/src/sys/pal/unsupported/io.rs | 7 +++- library/std/src/sys/pal/wasi/io.rs | 7 +++- library/std/src/sys/pal/windows/io.rs | 7 +++- 8 files changed, 95 insertions(+), 6 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 71dfd0676c9..21e70774954 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1340,6 +1340,25 @@ impl<'a> IoSliceMut<'a> { bufs[0].advance(left); } } + + /// Get the underlying bytes as a mutable slice with the original lifetime. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_slice_as_bytes)] + /// use std::io::IoSliceMut; + /// + /// let mut data = *b"abcdef"; + /// let io_slice = IoSliceMut::new(&mut data); + /// io_slice.into_slice()[0] = b'A'; + /// + /// assert_eq!(&data, b"Abcdef"); + /// ``` + #[unstable(feature = "io_slice_as_bytes", issue = "132818")] + pub const fn into_slice(self) -> &'a mut [u8] { + self.0.into_slice() + } } #[stable(feature = "iovec", since = "1.36.0")] @@ -1482,6 +1501,32 @@ impl<'a> IoSlice<'a> { bufs[0].advance(left); } } + + /// Get the underlying bytes as a slice with the original lifetime. + /// + /// This doesn't borrow from `self`, so is less restrictive than calling + /// `.deref()`, which does. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_slice_as_bytes)] + /// use std::io::IoSlice; + /// + /// let data = b"abcdef"; + /// + /// let mut io_slice = IoSlice::new(data); + /// let tail = &io_slice.as_slice()[3..]; + /// + /// // This works because `tail` doesn't borrow `io_slice` + /// io_slice = IoSlice::new(tail); + /// + /// assert_eq!(io_slice.as_slice(), b"def"); + /// ``` + #[unstable(feature = "io_slice_as_bytes", issue = "132818")] + pub const fn as_slice(self) -> &'a [u8] { + self.0.as_slice() + } } #[stable(feature = "iovec", since = "1.36.0")] diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 56b71c47dc7..89e806c0891 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -531,6 +531,20 @@ fn io_slice_advance_slices_beyond_total_length() { assert!(bufs.is_empty()); } +#[test] +fn io_slice_as_slice() { + let buf = [1; 8]; + let slice = IoSlice::new(&buf).as_slice(); + assert_eq!(slice, buf); +} + +#[test] +fn io_slice_into_slice() { + let mut buf = [1; 8]; + let slice = IoSliceMut::new(&mut buf).into_slice(); + assert_eq!(slice, [1; 8]); +} + /// Creates a new writer that reads from at most `n_bufs` and reads /// `per_call` bytes (in total) per call to write. fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter { diff --git a/library/std/src/sys/pal/hermit/io.rs b/library/std/src/sys/pal/hermit/io.rs index aad1eef71e9..0424a1ac55a 100644 --- a/library/std/src/sys/pal/hermit/io.rs +++ b/library/std/src/sys/pal/hermit/io.rs @@ -33,7 +33,7 @@ impl<'a> IoSlice<'a> { } #[inline] - pub fn as_slice(&self) -> &[u8] { + pub const fn as_slice(&self) -> &'a [u8] { unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } } } @@ -70,6 +70,11 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } } + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } + } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } diff --git a/library/std/src/sys/pal/solid/io.rs b/library/std/src/sys/pal/solid/io.rs index 4b1f788a492..9ef4b7049b6 100644 --- a/library/std/src/sys/pal/solid/io.rs +++ b/library/std/src/sys/pal/solid/io.rs @@ -33,7 +33,7 @@ impl<'a> IoSlice<'a> { } #[inline] - pub fn as_slice(&self) -> &[u8] { + pub const fn as_slice(&self) -> &'a [u8] { unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } } } @@ -70,6 +70,11 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } } + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } + } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } diff --git a/library/std/src/sys/pal/unix/io.rs b/library/std/src/sys/pal/unix/io.rs index 181c35a971e..0d5a152dc0d 100644 --- a/library/std/src/sys/pal/unix/io.rs +++ b/library/std/src/sys/pal/unix/io.rs @@ -33,7 +33,7 @@ impl<'a> IoSlice<'a> { } #[inline] - pub fn as_slice(&self) -> &[u8] { + pub const fn as_slice(&self) -> &'a [u8] { unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } } } @@ -70,6 +70,11 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } } + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } + } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } diff --git a/library/std/src/sys/pal/unsupported/io.rs b/library/std/src/sys/pal/unsupported/io.rs index 6372fca74e0..604735d32d5 100644 --- a/library/std/src/sys/pal/unsupported/io.rs +++ b/library/std/src/sys/pal/unsupported/io.rs @@ -15,7 +15,7 @@ impl<'a> IoSlice<'a> { } #[inline] - pub fn as_slice(&self) -> &[u8] { + pub const fn as_slice(&self) -> &'a [u8] { self.0 } } @@ -40,6 +40,11 @@ impl<'a> IoSliceMut<'a> { self.0 } + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + self.0 + } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { self.0 diff --git a/library/std/src/sys/pal/wasi/io.rs b/library/std/src/sys/pal/wasi/io.rs index b7c2f03daa0..57f81bc6257 100644 --- a/library/std/src/sys/pal/wasi/io.rs +++ b/library/std/src/sys/pal/wasi/io.rs @@ -30,7 +30,7 @@ impl<'a> IoSlice<'a> { } #[inline] - pub fn as_slice(&self) -> &[u8] { + pub const fn as_slice(&self) -> &'a [u8] { unsafe { slice::from_raw_parts(self.vec.buf as *const u8, self.vec.buf_len) } } } @@ -67,6 +67,11 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts(self.vec.buf as *const u8, self.vec.buf_len) } } + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.buf_len) } + } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.buf_len) } diff --git a/library/std/src/sys/pal/windows/io.rs b/library/std/src/sys/pal/windows/io.rs index 1e7d02908f6..f2865d2ffc1 100644 --- a/library/std/src/sys/pal/windows/io.rs +++ b/library/std/src/sys/pal/windows/io.rs @@ -36,7 +36,7 @@ impl<'a> IoSlice<'a> { } #[inline] - pub fn as_slice(&self) -> &[u8] { + pub const fn as_slice(&self) -> &'a [u8] { unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) } } } @@ -74,6 +74,11 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) } } + #[inline] + pub const fn into_slice(self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) } + } + #[inline] pub fn as_mut_slice(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) } From fb3edb2fc7c0ff8ec51dbebc11a455b53767d236 Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 13 Nov 2024 05:26:31 +0000 Subject: [PATCH 02/11] [illumos] use pipe2 to create anonymous pipes pipe2 allows the newly-created pipe to atomically be CLOEXEC. pipe2 was added to illumos a long time ago: https://github.com/illumos/illumos-gate/commit/5dbfd19ad5fcc2b779f40f80fa05c1bd28fd0b4e. I've verified that this change passes all tests. --- library/std/src/sys/pal/unix/pipe.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index f0ebc767bad..4a992e32a91 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -23,6 +23,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { target_os = "dragonfly", target_os = "freebsd", target_os = "hurd", + target_os = "illumos", target_os = "linux", target_os = "netbsd", target_os = "openbsd", From 0df3ef4435beda2711abcb992fae1969398b9a7c Mon Sep 17 00:00:00 2001 From: Christopher Berner Date: Tue, 12 Nov 2024 20:02:47 -0800 Subject: [PATCH 03/11] Fix compilation error on Solaris due to flock usage PR 130999 added the file_lock feature, but libc does not define flock() for the Solaris platform leading to a compilation error. Additionally, I went through all the Tier 2 platforms and read through their documentation to see whether flock was implemented. This turned up 5 more Unix platforms where flock is not supported, even though it may exist in the libc crate. --- library/std/src/fs/tests.rs | 28 +++++++++++ library/std/src/sys/pal/unix/fs.rs | 80 ++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 05efed6b5df..018e1958641 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -204,6 +204,13 @@ fn file_test_io_seek_and_write() { } #[test] +#[cfg(any( + windows, + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", +))] fn file_lock_multiple_shared() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_lock_multiple_shared_test.txt"); @@ -220,6 +227,13 @@ fn file_lock_multiple_shared() { } #[test] +#[cfg(any( + windows, + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", +))] fn file_lock_blocking() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_lock_blocking_test.txt"); @@ -237,6 +251,13 @@ fn file_lock_blocking() { } #[test] +#[cfg(any( + windows, + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", +))] fn file_lock_drop() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_lock_dup_test.txt"); @@ -251,6 +272,13 @@ fn file_lock_drop() { } #[test] +#[cfg(any( + windows, + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", +))] fn file_lock_dup() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_lock_dup_test.txt"); diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index be2363862ee..96f99efb21e 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1254,16 +1254,54 @@ impl File { } } + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + ))] pub fn lock(&self) -> io::Result<()> { cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_EX) })?; return Ok(()); } + #[cfg(not(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + )))] + pub fn lock(&self) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "lock() not supported")) + } + + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + ))] pub fn lock_shared(&self) -> io::Result<()> { cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_SH) })?; return Ok(()); } + #[cfg(not(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + )))] + pub fn lock_shared(&self) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "lock_shared() not supported")) + } + + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + ))] pub fn try_lock(&self) -> io::Result { let result = cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) }); if let Err(ref err) = result { @@ -1275,6 +1313,22 @@ impl File { return Ok(true); } + #[cfg(not(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + )))] + pub fn try_lock(&self) -> io::Result { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "try_lock() not supported")) + } + + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + ))] pub fn try_lock_shared(&self) -> io::Result { let result = cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_SH | libc::LOCK_NB) }); if let Err(ref err) = result { @@ -1286,11 +1340,37 @@ impl File { return Ok(true); } + #[cfg(not(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + )))] + pub fn try_lock_shared(&self) -> io::Result { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "try_lock_shared() not supported")) + } + + #[cfg(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + ))] pub fn unlock(&self) -> io::Result<()> { cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_UN) })?; return Ok(()); } + #[cfg(not(any( + target_os = "freebsd", + target_os = "linux", + target_os = "netbsd", + target_vendor = "apple", + )))] + pub fn unlock(&self) -> io::Result<()> { + Err(io::const_io_error!(io::ErrorKind::Unsupported, "unlock() not supported")) + } + pub fn truncate(&self, size: u64) -> io::Result<()> { let size: off64_t = size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; From 2cb7aeaba5df5bc84bebbe611dd0df811c9b3aa2 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Thu, 14 Nov 2024 10:24:38 +0900 Subject: [PATCH 04/11] docs: Fix missing period in methods for integer types --- library/core/src/num/int_macros.rs | 8 ++++---- library/core/src/num/uint_macros.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 440e75c2113..4d24b102096 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1300,7 +1300,7 @@ macro_rules! int_impl { } } - /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs` + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`. /// /// If `rhs` is larger or equal to the number of bits in `self`, /// the entire value is shifted out, and `0` is returned. @@ -1423,7 +1423,7 @@ macro_rules! int_impl { } } - /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs` + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`. /// /// If `rhs` is larger or equal to the number of bits in `self`, /// the entire value is shifted out, which yields `0` for a positive number, @@ -2389,7 +2389,7 @@ macro_rules! int_impl { (res, overflowed ^ (rhs < 0)) } - /// Calculates `self` - `rhs` + /// Calculates `self` - `rhs`. /// /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow /// would occur. If an overflow would have occurred then the wrapped value is returned. @@ -2470,7 +2470,7 @@ macro_rules! int_impl { (c, b != d) } - /// Calculates `self` - `rhs` with an unsigned `rhs` + /// Calculates `self` - `rhs` with an unsigned `rhs`. /// /// Returns a tuple of the subtraction along with a boolean indicating /// whether an arithmetic overflow would occur. If an overflow would diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 550b6a087f9..ca1baa5a157 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1490,7 +1490,7 @@ macro_rules! uint_impl { } } - /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs` + /// Unbounded shift left. Computes `self << rhs`, without bounding the value of `rhs`. /// /// If `rhs` is larger or equal to the number of bits in `self`, /// the entire value is shifted out, and `0` is returned. @@ -1613,7 +1613,7 @@ macro_rules! uint_impl { } } - /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs` + /// Unbounded shift right. Computes `self >> rhs`, without bounding the value of `rhs`. /// /// If `rhs` is larger or equal to the number of bits in `self`, /// the entire value is shifted out, and `0` is returned. @@ -2312,7 +2312,7 @@ macro_rules! uint_impl { (res, overflowed ^ (rhs < 0)) } - /// Calculates `self` - `rhs` + /// Calculates `self` - `rhs`. /// /// Returns a tuple of the subtraction along with a boolean indicating /// whether an arithmetic overflow would occur. If an overflow would From 17ed9483125f19e43b74aee559b2ea1867a0cac3 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Thu, 14 Nov 2024 10:39:33 +0900 Subject: [PATCH 05/11] docs: Fix missing colon in methods for primitive types --- library/core/src/num/uint_macros.rs | 18 +++++++++--------- library/core/src/str/mod.rs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index ca1baa5a157..eff743f6f6f 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2222,7 +2222,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] @@ -2320,7 +2320,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] @@ -2447,7 +2447,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] @@ -2478,7 +2478,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")] @@ -2506,7 +2506,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] @@ -2537,7 +2537,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")] @@ -2561,7 +2561,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));")] @@ -2586,7 +2586,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(4), (0x10, false));")] @@ -2612,7 +2612,7 @@ macro_rules! uint_impl { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(4), (0x1, false));")] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 0f7c2c999d0..5aecbf303f9 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2400,7 +2400,7 @@ impl str { /// /// # Examples /// - /// Basic usage + /// Basic usage: /// /// ``` /// let four: u32 = "4".parse().unwrap(); From 467ce2695a9efca6f2494be680e922ac541df2e3 Mon Sep 17 00:00:00 2001 From: Xing Xue Date: Mon, 11 Nov 2024 10:31:29 -0500 Subject: [PATCH 06/11] Include the "unwind" crate to link with libunwind instead of the "libc" crate. --- tests/ui/extern-flag/auxiliary/panic_handler.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/ui/extern-flag/auxiliary/panic_handler.rs b/tests/ui/extern-flag/auxiliary/panic_handler.rs index 5ca32fa992b..9140ceed229 100644 --- a/tests/ui/extern-flag/auxiliary/panic_handler.rs +++ b/tests/ui/extern-flag/auxiliary/panic_handler.rs @@ -1,14 +1,10 @@ -#![feature(lang_items)] +#![feature(lang_items, panic_unwind)] #![no_std] -// Since `rustc` generally passes `-nodefaultlibs` to the linker, -// Rust programs link necessary system libraries via `#[link()]` -// attributes in the `libc` crate. `libc` is a dependency of `std`, -// but as we are `#![no_std]`, we need to include it manually. -// Except on windows-msvc. -#![feature(rustc_private)] -#[cfg(not(all(windows, target_env = "msvc")))] -extern crate libc; +// Since the `unwind` crate is a dependency of the `std` crate, and we have +// `#![no_std]`, the unwinder is not included in the link command by default. +// We need to include crate `unwind` manually. +extern crate unwind; #[panic_handler] pub fn begin_panic_handler(_info: &core::panic::PanicInfo<'_>) -> ! { From 7711ba2d14207c9ca73ab72e60ddcc6654a909e1 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 14 Nov 2024 21:04:30 +0100 Subject: [PATCH 07/11] use `&raw` in `{read, write}_unaligned` documentation --- library/core/src/ptr/mod.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index b98e2b5eac8..603e9044217 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1407,9 +1407,8 @@ pub const unsafe fn read(src: *const T) -> T { /// As a result, using `&packed.unaligned as *const FieldType` causes immediate /// *undefined behavior* in your program. /// -/// Instead you must use the [`ptr::addr_of!`](addr_of) macro to -/// create the pointer. You may use that returned pointer together with this -/// function. +/// Instead you must use the `&raw const` syntax to create the pointer. +/// You may use that constructed pointer together with this function. /// /// An example of what not to do and how this relates to `read_unaligned` is: /// @@ -1427,7 +1426,7 @@ pub const unsafe fn read(src: *const T) -> T { /// /// // Take the address of a 32-bit integer which is not aligned. /// // In contrast to `&packed.unaligned as *const _`, this has no undefined behavior. -/// let unaligned = std::ptr::addr_of!(packed.unaligned); +/// let unaligned = &raw const packed.unaligned; /// /// let v = unsafe { std::ptr::read_unaligned(unaligned) }; /// assert_eq!(v, 0x01020304); @@ -1615,9 +1614,8 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// As a result, using `&packed.unaligned as *const FieldType` causes immediate /// *undefined behavior* in your program. /// -/// Instead, you must use the [`ptr::addr_of_mut!`](addr_of_mut) -/// macro to create the pointer. You may use that returned pointer together with -/// this function. +/// Instead, you must use the `&raw mut` syntax to create the pointer. +/// You may use that constructed pointer together with this function. /// /// An example of how to do it and how this relates to `write_unaligned` is: /// @@ -1632,7 +1630,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// /// // Take the address of a 32-bit integer which is not aligned. /// // In contrast to `&packed.unaligned as *mut _`, this has no undefined behavior. -/// let unaligned = std::ptr::addr_of_mut!(packed.unaligned); +/// let unaligned = &raw mut packed.unaligned; /// /// unsafe { std::ptr::write_unaligned(unaligned, 42) }; /// From ede8a74f1e73af264de44a73e531e270a3d65c99 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Thu, 14 Nov 2024 14:07:47 -0700 Subject: [PATCH 08/11] tests/run-make/simd-ffi: fix test crashing on x86 targets ... ... that do not have SSE2 support (e.g. i586) --- tests/run-make/simd-ffi/simd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run-make/simd-ffi/simd.rs b/tests/run-make/simd-ffi/simd.rs index b72078faafa..4b86b808d81 100644 --- a/tests/run-make/simd-ffi/simd.rs +++ b/tests/run-make/simd-ffi/simd.rs @@ -25,7 +25,7 @@ pub struct i32x4([i32; 4]); extern "C" { // _mm_sll_epi32 - #[cfg(any(target_arch = "x86", target_arch = "x86-64"))] + #[cfg(all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"))] #[link_name = "llvm.x86.sse2.psll.d"] fn integer(a: i32x4, b: i32x4) -> i32x4; @@ -42,7 +42,7 @@ extern "C" { // we still get type checking, but not as detailed as (ab)using // LLVM. #[cfg(not(any( - target_arch = "x86", + all(target_arch = "x86", target_feature = "sse2"), target_arch = "x86-64", target_arch = "arm", target_arch = "aarch64" From b77dbbd4fd2ed4083635f74612aa25b4be80fc43 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 14 Nov 2024 15:48:21 -0600 Subject: [PATCH 09/11] Pass `f16` and `f128` by value in `const_assert!` These types are currently passed by reference, which does not avoid the backend crashes. Change these back to being passed by value, which makes the types easier to detect for automatic inlining. --- library/core/src/num/f128.rs | 5 ++--- library/core/src/num/f16.rs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index c3862d99498..3fac1ef099f 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1258,9 +1258,8 @@ impl f128 { min <= max, "min > max, or either was NaN", "min > max, or either was NaN. min = {min:?}, max = {max:?}", - // FIXME(f16_f128): Passed by-ref to avoid codegen crashes - min: &f128 = &min, - max: &f128 = &max, + min: f128, + max: f128, ); if self < min { diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index ed35316cf8f..eaac19f22f7 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1235,9 +1235,8 @@ impl f16 { min <= max, "min > max, or either was NaN", "min > max, or either was NaN. min = {min:?}, max = {max:?}", - // FIXME(f16_f128): Passed by-ref to avoid codegen crashes - min: &f16 = &min, - max: &f16 = &max, + min: f16, + max: f16, ); if self < min { From 5d818914af2760972943db448d2a08de27900c96 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 14 Nov 2024 14:17:20 -0600 Subject: [PATCH 10/11] Always inline functions signatures containing `f16` or `f128` There are a handful of tier 2 and tier 3 targets that cause a LLVM crash or linker error when generating code that contains `f16` or `f128`. The cranelift backend also does not support these types. To work around this, every function in `std` or `core` that contains these types must be marked `#[inline]` in order to avoid sending any code to the backend unless specifically requested. However, this is inconvenient and easy to forget. Introduce a check for these types in the frontend that automatically inlines any function signatures that take or return `f16` or `f128`. Note that this is not a perfect fix because it does not account for the types being passed by reference or as members of aggregate types, but this is sufficient for what is currently needed in the standard library. Fixes: https://github.com/rust-lang/rust/issues/133035 Closes: https://github.com/rust-lang/rust/pull/133037 --- .../src/cross_crate_inline.rs | 10 +++++++ tests/codegen/float/f16-f128-inline.rs | 29 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/codegen/float/f16-f128-inline.rs diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 42cbece32d8..589be81558c 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -50,6 +50,16 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { _ => {} } + let sig = tcx.fn_sig(def_id).instantiate_identity(); + for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder())) + { + // FIXME(f16_f128): in order to avoid crashes building `core`, always inline to skip + // codegen if the function is not used. + if ty == &tcx.types.f16 || ty == &tcx.types.f128 { + return true; + } + } + // Don't do any inference when incremental compilation is enabled; the additional inlining that // inference permits also creates more work for small edits. if tcx.sess.opts.incremental.is_some() { diff --git a/tests/codegen/float/f16-f128-inline.rs b/tests/codegen/float/f16-f128-inline.rs new file mode 100644 index 00000000000..aa2c38c209e --- /dev/null +++ b/tests/codegen/float/f16-f128-inline.rs @@ -0,0 +1,29 @@ +//@ revisions: default nopt +//@[nopt] compile-flags: -Copt-level=0 -Zcross-crate-inline-threshold=never -Zmir-opt-level=0 -Cno-prepopulate-passes + +// Ensure that functions using `f16` and `f128` are always inlined to avoid crashes +// when the backend does not support these types. + +#![crate_type = "lib"] +#![feature(f128)] +#![feature(f16)] + +pub fn f16_arg(_a: f16) { + // CHECK-NOT: f16_arg + todo!() +} + +pub fn f16_ret() -> f16 { + // CHECK-NOT: f16_ret + todo!() +} + +pub fn f128_arg(_a: f128) { + // CHECK-NOT: f128_arg + todo!() +} + +pub fn f128_ret() -> f128 { + // CHECK-NOT: f128_ret + todo!() +} From 0733ed77d16a691863166561bc8b286a79fa8584 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Thu, 14 Nov 2024 14:08:39 -0700 Subject: [PATCH 11/11] tests/run-make/simd-ffi: use a generic LLVM intrinsics ... ... to do more comprehensive type checking --- tests/run-make/simd-ffi/simd.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/run-make/simd-ffi/simd.rs b/tests/run-make/simd-ffi/simd.rs index 4b86b808d81..9ea8eb8cf88 100644 --- a/tests/run-make/simd-ffi/simd.rs +++ b/tests/run-make/simd-ffi/simd.rs @@ -38,15 +38,13 @@ extern "C" { #[link_name = "llvm.aarch64.neon.maxs.v4i32"] fn integer(a: i32x4, b: i32x4) -> i32x4; - // just some substitute foreign symbol, not an LLVM intrinsic; so - // we still get type checking, but not as detailed as (ab)using - // LLVM. + // Use a generic LLVM intrinsic to do type checking on other platforms #[cfg(not(any( - all(target_arch = "x86", target_feature = "sse2"), - target_arch = "x86-64", + all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"), target_arch = "arm", target_arch = "aarch64" )))] + #[link_name = "llvm.smax.v4i32"] fn integer(a: i32x4, b: i32x4) -> i32x4; }