From 709ea7469f5093fb488607fcb966445c63d49a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=C3=AFssata?= Date: Mon, 11 Jul 2022 13:12:41 +0000 Subject: [PATCH 001/613] Add Read Impl for &Stdin --- library/std/src/io/stdio.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 261b570dee74f..e929eaa639696 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -445,6 +445,29 @@ impl Read for Stdin { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl Read for &Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.lock().read(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + self.lock().read_vectored(bufs) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.lock().is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.lock().read_to_end(buf) + } + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + self.lock().read_to_string(buf) + } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + self.lock().read_exact(buf) + } +} + // only used by platform-dependent io::copy specializations, i.e. unused on some platforms #[cfg(any(target_os = "linux", target_os = "android"))] impl StdinLock<'_> { From 93f2f2c8ee44a8cb469fd7e656599c2b9546a1af Mon Sep 17 00:00:00 2001 From: John Millikin Date: Wed, 25 Oct 2023 17:01:21 +0900 Subject: [PATCH 002/613] Convert `Unix{Datagram,Stream}::{set_}passcred()` to per-OS traits These methods are the pre-stabilized API for obtaining peer credentials from an `AF_UNIX` socket, part of the `unix_socket_ancillary_data` feature. Their current behavior is to get/set one of the `SO_PASSCRED` (Linux), `LOCAL_CREDS_PERSISTENT` (FreeBSD), or `LOCAL_CREDS` (NetBSD) socket options. On other targets the `{set_}passcred()` methods do not exist. There are two problems with this approach: 1. Having public methods only exist for certain targets isn't permitted in a stable `std` API. 2. These options have generally similar purposes, but they are non-POSIX and their details can differ in subtle and surprising ways (such as whether they continue to be set after the next call to `recvmsg()`). Splitting into OS-specific extension traits is the preferred solution to both problems. --- library/std/src/os/android/net.rs | 3 + library/std/src/os/freebsd/mod.rs | 1 + library/std/src/os/freebsd/net.rs | 65 +++++++++++++++++++ library/std/src/os/linux/net.rs | 3 + library/std/src/os/net/linux_ext/mod.rs | 3 + library/std/src/os/net/linux_ext/socket.rs | 63 ++++++++++++++++++ library/std/src/os/netbsd/mod.rs | 1 + library/std/src/os/netbsd/net.rs | 65 +++++++++++++++++++ library/std/src/os/unix/net/datagram.rs | 75 ++++------------------ library/std/src/os/unix/net/stream.rs | 75 ++++------------------ library/std/src/os/unix/net/tests.rs | 4 +- library/std/src/sys/pal/unix/net.rs | 26 +++++--- 12 files changed, 246 insertions(+), 138 deletions(-) create mode 100644 library/std/src/os/freebsd/net.rs create mode 100644 library/std/src/os/net/linux_ext/socket.rs create mode 100644 library/std/src/os/netbsd/net.rs diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs index fe40d6319c2ff..349e73eaabdaf 100644 --- a/library/std/src/os/android/net.rs +++ b/library/std/src/os/android/net.rs @@ -5,5 +5,8 @@ #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub use crate::os::net::linux_ext::socket::UnixSocketExt; + #[unstable(feature = "tcp_quickack", issue = "96256")] pub use crate::os::net::linux_ext::tcp::TcpStreamExt; diff --git a/library/std/src/os/freebsd/mod.rs b/library/std/src/os/freebsd/mod.rs index c072fae557fe0..39912e6970d45 100644 --- a/library/std/src/os/freebsd/mod.rs +++ b/library/std/src/os/freebsd/mod.rs @@ -3,4 +3,5 @@ #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; +pub mod net; pub mod raw; diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs new file mode 100644 index 0000000000000..33990d54caae0 --- /dev/null +++ b/library/std/src/os/freebsd/net.rs @@ -0,0 +1,65 @@ +//! FreeBSD-specific networking functionality. + +#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + +use crate::io; +use crate::os::unix::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// FreeBSD-specific functionality for `AF_UNIX` sockets [`UnixDatagram`] +/// and [`UnixStream`]. +/// +/// [`UnixDatagram`]: net::UnixDatagram +/// [`UnixStream`]: net::UnixStream +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub trait UnixSocketExt: Sealed { + /// Query the current setting of socket option `LOCAL_CREDS_PERSISTENT`. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn local_creds_persistent(&self) -> io::Result; + + /// Enable or disable socket option `LOCAL_CREDS_PERSISTENT`. + /// + /// This option enables the credentials of the sending process to be + /// received as a control message in [`AncillaryData`]. + /// + /// [`AncillaryData`]: net::AncillaryData + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_ancillary_data)] + /// use std::os::freebsd::net::UnixSocketExt; + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_local_creds_persistent(true).expect("set_local_creds_persistent failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>; +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixDatagram { + fn local_creds_persistent(&self) -> io::Result { + self.as_inner().local_creds_persistent() + } + + fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> { + self.as_inner().set_local_creds_persistent(local_creds_persistent) + } +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixStream { + fn local_creds_persistent(&self) -> io::Result { + self.as_inner().local_creds_persistent() + } + + fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> { + self.as_inner().set_local_creds_persistent(local_creds_persistent) + } +} diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs index c8e734d740b68..f898e70548706 100644 --- a/library/std/src/os/linux/net.rs +++ b/library/std/src/os/linux/net.rs @@ -5,5 +5,8 @@ #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub use crate::os::net::linux_ext::addr::SocketAddrExt; +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub use crate::os::net::linux_ext::socket::UnixSocketExt; + #[unstable(feature = "tcp_quickack", issue = "96256")] pub use crate::os::net::linux_ext::tcp::TcpStreamExt; diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs index 62e78cc50d4ab..d0979640c32ea 100644 --- a/library/std/src/os/net/linux_ext/mod.rs +++ b/library/std/src/os/net/linux_ext/mod.rs @@ -5,6 +5,9 @@ #[stable(feature = "unix_socket_abstract", since = "1.70.0")] pub(crate) mod addr; +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub(crate) mod socket; + #[unstable(feature = "tcp_quickack", issue = "96256")] pub(crate) mod tcp; diff --git a/library/std/src/os/net/linux_ext/socket.rs b/library/std/src/os/net/linux_ext/socket.rs new file mode 100644 index 0000000000000..4e4168f693c34 --- /dev/null +++ b/library/std/src/os/net/linux_ext/socket.rs @@ -0,0 +1,63 @@ +//! Linux and Android-specific socket functionality. + +use crate::io; +use crate::os::unix::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// Linux-specific functionality for `AF_UNIX` sockets [`UnixDatagram`] +/// and [`UnixStream`]. +/// +/// [`UnixDatagram`]: net::UnixDatagram +/// [`UnixStream`]: net::UnixStream +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub trait UnixSocketExt: Sealed { + /// Query the current setting of socket option `SO_PASSCRED`. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn passcred(&self) -> io::Result; + + /// Enable or disable socket option `SO_PASSCRED`. + /// + /// This option enables the credentials of the sending process to be + /// received as a control message in [`AncillaryData`]. + /// + /// [`AncillaryData`]: net::AncillaryData + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_ancillary_data)] + /// use std::os::linux::net::UnixSocketExt; + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_passcred(true).expect("set_passcred failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn set_passcred(&self, passcred: bool) -> io::Result<()>; +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixDatagram { + fn passcred(&self) -> io::Result { + self.as_inner().passcred() + } + + fn set_passcred(&self, passcred: bool) -> io::Result<()> { + self.as_inner().set_passcred(passcred) + } +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixStream { + fn passcred(&self) -> io::Result { + self.as_inner().passcred() + } + + fn set_passcred(&self, passcred: bool) -> io::Result<()> { + self.as_inner().set_passcred(passcred) + } +} diff --git a/library/std/src/os/netbsd/mod.rs b/library/std/src/os/netbsd/mod.rs index 497a51a1df6fd..2f21e98a6f4cb 100644 --- a/library/std/src/os/netbsd/mod.rs +++ b/library/std/src/os/netbsd/mod.rs @@ -3,4 +3,5 @@ #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; +pub mod net; pub mod raw; diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs new file mode 100644 index 0000000000000..5c82f43077d4c --- /dev/null +++ b/library/std/src/os/netbsd/net.rs @@ -0,0 +1,65 @@ +//! NetBSD-specific networking functionality. + +#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + +use crate::io; +use crate::os::unix::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// NetBSD-specific functionality for `AF_UNIX` sockets [`UnixDatagram`] +/// and [`UnixStream`]. +/// +/// [`UnixDatagram`]: net::UnixDatagram +/// [`UnixStream`]: net::UnixStream +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub trait UnixSocketExt: Sealed { + /// Query the current setting of socket option `LOCAL_CREDS`. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn local_creds(&self) -> io::Result; + + /// Enable or disable socket option `LOCAL_CREDS`. + /// + /// This option enables the credentials of the sending process to be + /// received as a control message in [`AncillaryData`]. + /// + /// [`AncillaryData`]: net::AncillaryData + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_ancillary_data)] + /// use std::os::netbsd::net::UnixSocketExt; + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_local_creds(true).expect("set_local_creds failed"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + fn set_local_creds(&self, local_creds: bool) -> io::Result<()>; +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixDatagram { + fn local_creds(&self) -> io::Result { + self.as_inner().local_creds() + } + + fn set_local_creds(&self, local_creds: bool) -> io::Result<()> { + self.as_inner().set_local_creds(local_creds) + } +} + +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +impl UnixSocketExt for net::UnixStream { + fn local_creds(&self) -> io::Result { + self.as_inner().local_creds() + } + + fn set_local_creds(&self, local_creds: bool) -> io::Result<()> { + self.as_inner().set_local_creds(local_creds) + } +} diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 0b4d955294ca5..df698c17f6cc2 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -6,6 +6,7 @@ use crate::io::{IoSlice, IoSliceMut}; use crate::net::Shutdown; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::path::Path; +use crate::sealed::Sealed; use crate::sys::cvt; use crate::sys::net::Socket; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -54,6 +55,10 @@ const MSG_NOSIGNAL: libc::c_int = 0x0; #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixDatagram(Socket); +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl Sealed for UnixDatagram {} + #[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixDatagram { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -802,69 +807,6 @@ impl UnixDatagram { self.0.set_nonblocking(nonblocking) } - /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. - /// - /// Set the socket option `SO_PASSCRED`. - /// - /// # Examples - /// - #[cfg_attr( - any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd", - ), - doc = "```no_run" - )] - #[cfg_attr( - not(any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - )), - doc = "```ignore" - )] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::UnixDatagram; - /// - /// fn main() -> std::io::Result<()> { - /// let sock = UnixDatagram::unbound()?; - /// sock.set_passcred(true).expect("set_passcred function failed"); - /// Ok(()) - /// } - /// ``` - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - self.0.set_passcred(passcred) - } - - /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. - /// This value can be change by [`set_passcred`]. - /// - /// Get the socket option `SO_PASSCRED`. - /// - /// [`set_passcred`]: UnixDatagram::set_passcred - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn passcred(&self) -> io::Result { - self.0.passcred() - } - /// Set the id of the socket for network filtering purpose /// #[cfg_attr( @@ -1038,3 +980,10 @@ impl From for UnixDatagram { unsafe { Self::from_raw_fd(owned.into_raw_fd()) } } } + +impl AsInner for UnixDatagram { + #[inline] + fn as_inner(&self) -> &Socket { + &self.0 + } +} diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index b1cd504e21939..9205160455dde 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -19,6 +19,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned ))] use crate::os::unix::ucred; use crate::path::Path; +use crate::sealed::Sealed; use crate::sys::cvt; use crate::sys::net::Socket; use crate::sys_common::{AsInner, FromInner}; @@ -59,6 +60,10 @@ pub use ucred::UCred; #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixStream(pub(super) Socket); +/// Allows extension traits within `std`. +#[unstable(feature = "sealed", issue = "none")] +impl Sealed for UnixStream {} + #[stable(feature = "unix_socket", since = "1.10.0")] impl fmt::Debug for UnixStream { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -394,69 +399,6 @@ impl UnixStream { self.0.set_nonblocking(nonblocking) } - /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. - /// - /// Set the socket option `SO_PASSCRED`. - /// - /// # Examples - /// - #[cfg_attr( - any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ), - doc = "```no_run" - )] - #[cfg_attr( - not(any( - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - )), - doc = "```ignore" - )] - /// #![feature(unix_socket_ancillary_data)] - /// use std::os::unix::net::UnixStream; - /// - /// fn main() -> std::io::Result<()> { - /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_passcred(true).expect("Couldn't set passcred"); - /// Ok(()) - /// } - /// ``` - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - self.0.set_passcred(passcred) - } - - /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. - /// This value can be change by [`set_passcred`]. - /// - /// Get the socket option `SO_PASSCRED`. - /// - /// [`set_passcred`]: UnixStream::set_passcred - #[cfg(any( - doc, - target_os = "android", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd" - ))] - #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] - pub fn passcred(&self) -> io::Result { - self.0.passcred() - } - /// Set the id of the socket for network filtering purpose /// #[cfg_attr( @@ -766,3 +708,10 @@ impl From for UnixStream { unsafe { Self::from_raw_fd(owned.into_raw_fd()) } } } + +impl AsInner for UnixStream { + #[inline] + fn as_inner(&self) -> &Socket { + &self.0 + } +} diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 6a6af9efd78ed..e456e41b21c88 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -8,10 +8,10 @@ use crate::thread; use crate::time::Duration; #[cfg(target_os = "android")] -use crate::os::android::net::SocketAddrExt; +use crate::os::android::net::{SocketAddrExt, UnixSocketExt}; #[cfg(target_os = "linux")] -use crate::os::linux::net::SocketAddrExt; +use crate::os::linux::net::{SocketAddrExt, UnixSocketExt}; macro_rules! or_panic { ($e:expr) => { diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs index 60546a3de4509..09750b6ffc897 100644 --- a/library/std/src/sys/pal/unix/net.rs +++ b/library/std/src/sys/pal/unix/net.rs @@ -465,25 +465,31 @@ impl Socket { } #[cfg(target_os = "netbsd")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, passcred as libc::c_int) + pub fn set_local_creds(&self, local_creds: bool) -> io::Result<()> { + setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, local_creds as libc::c_int) } #[cfg(target_os = "netbsd")] - pub fn passcred(&self) -> io::Result { - let passcred: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?; - Ok(passcred != 0) + pub fn local_creds(&self) -> io::Result { + let local_creds: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?; + Ok(local_creds != 0) } #[cfg(target_os = "freebsd")] - pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { - setsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT, passcred as libc::c_int) + pub fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> { + setsockopt( + self, + libc::AF_LOCAL, + libc::LOCAL_CREDS_PERSISTENT, + local_creds_persistent as libc::c_int, + ) } #[cfg(target_os = "freebsd")] - pub fn passcred(&self) -> io::Result { - let passcred: libc::c_int = getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?; - Ok(passcred != 0) + pub fn local_creds_persistent(&self) -> io::Result { + let local_creds_persistent: libc::c_int = + getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?; + Ok(local_creds_persistent != 0) } #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "vita")))] From 75fce09751683f7177c4f0718f33d572a0278e8f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 19 Nov 2023 13:42:13 -0500 Subject: [PATCH 003/613] Merge commit '2e8386e9fb3506cef991d04f8b3bc78f9a0c2630' into subtree-update_cg_gcc_2023-11-17 --- .github/workflows/ci.yml | 9 ++++-- .github/workflows/failures.yml | 5 +++- .github/workflows/m68k.yml | 9 ++++-- .github/workflows/release.yml | 9 ++++-- .github/workflows/stdarch.yml | 12 +++++--- Cargo.lock | 4 +-- build_sysroot/build_sysroot.sh | 4 +++ build_system/src/build.rs | 6 ++++ failing-ui-tests12.txt | 2 ++ ...0001-core-Disable-portable-simd-test.patch | 14 +++++----- rust-toolchain | 2 +- src/base.rs | 16 +++++------ src/int.rs | 25 +++++++++++++++-- src/lib.rs | 28 +++++++++++++++---- 14 files changed, 104 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65e7a697ab0df..308bc55ead71e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,8 +99,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ./y.sh build - cargo test + # TODO: remove --features master when it is back to the default. + ./y.sh build --features master + # TODO: remove --features master when it is back to the default. + cargo test --features master ./clean_all.sh - name: Prepare dependencies @@ -121,7 +123,8 @@ jobs: - name: Run tests run: | - ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} + # TODO: remove --features master when it is back to the default. + ./test.sh --features master --release --clean --build-sysroot ${{ matrix.commands }} duplicates: runs-on: ubuntu-latest diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index 27864dcadd0fe..ae8de79b773db 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -21,11 +21,14 @@ jobs: libgccjit_version: - gcc: "libgccjit.so" artifacts_branch: "master" + # TODO: switch back to --no-default-features in the case of libgccjit 12 when the default is to enable + # master again. + extra: "--features master" - gcc: "libgccjit_without_int128.so" artifacts_branch: "master-without-128bit-integers" + extra: "--features master" - gcc: "libgccjit12.so" artifacts_branch: "gcc12" - extra: "--no-default-features" # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin. # Not sure why it's not found otherwise. env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/" diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 55ee0a212142e..4d9d7e23dc2b5 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -114,8 +114,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore --cross - ./y.sh build --target-triple m68k-unknown-linux-gnu - CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test + # TODO: remove --features master when it is back to the default. + ./y.sh build --target-triple m68k-unknown-linux-gnu --features master + # TODO: remove --features master when it is back to the default. + CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test --features master ./clean_all.sh - name: Prepare dependencies @@ -136,4 +138,5 @@ jobs: - name: Run tests run: | - ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} + # TODO: remove --features master when it is back to the default. + ./test.sh --release --features master --clean --build-sysroot ${{ matrix.commands }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae1134177a77e..43b90fcec9337 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,8 +78,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot - cargo test + # TODO: remove --features master when it is back to the default. + EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot --features master + # TODO: remove --features master when it is back to the default. + cargo test --features master ./clean_all.sh - name: Prepare dependencies @@ -102,4 +104,5 @@ jobs: - name: Run tests run: | - EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} + # TODO: remove --features master when it is back to the default. + EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 28ac3cb65422f..42109ba3e0245 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -92,8 +92,10 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - ./y.sh build --release --release-sysroot - cargo test + # TODO: remove `--features master` when it is back to the default. + ./y.sh build --release --release-sysroot --features master + # TODO: remove --features master when it is back to the default. + cargo test --features master - name: Clean if: ${{ !matrix.cargo_runner }} @@ -111,12 +113,14 @@ jobs: uses: actions-rs/cargo@v1.0.3 with: command: build - args: --release + # TODO: remove `--features master` when it is back to the default. + args: --release --features master - name: Run tests if: ${{ !matrix.cargo_runner }} run: | - ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore + # TODO: remove `--features master` when it is back to the default. + ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} diff --git a/Cargo.lock b/Cargo.lock index b8e2e5d808044..7c18633692783 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033" +source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421" dependencies = [ "gccjit_sys", ] @@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#c52a218f5529321285b4489e5562a00e5428e033" +source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421" dependencies = [ "libc", ] diff --git a/build_sysroot/build_sysroot.sh b/build_sysroot/build_sysroot.sh index 116fd36e7a7b3..ebc7dc375b125 100755 --- a/build_sysroot/build_sysroot.sh +++ b/build_sysroot/build_sysroot.sh @@ -28,3 +28,7 @@ fi # Copy files to sysroot mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ cp -r target/$TARGET_TRIPLE/$sysroot_channel/deps/* sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ +# Copy the source files to the sysroot (Rust for Linux needs this). +source_dir=sysroot/lib/rustlib/src/rust +mkdir -p $source_dir +cp -r sysroot_src/library/ $source_dir diff --git a/build_system/src/build.rs b/build_system/src/build.rs index eaca7a987d6b8..f1c3701a946ec 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -194,6 +194,12 @@ fn build_sysroot( copier, )?; + // Copy the source files to the sysroot (Rust for Linux needs this). + let sysroot_src_path = "sysroot/lib/rustlib/src/rust"; + fs::create_dir_all(&sysroot_src_path) + .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_src_path, error))?; + run_command(&[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], None)?; + Ok(()) } diff --git a/failing-ui-tests12.txt b/failing-ui-tests12.txt index f91aa92531848..4af93939b0642 100644 --- a/failing-ui-tests12.txt +++ b/failing-ui-tests12.txt @@ -38,3 +38,5 @@ tests/ui/target-feature/missing-plusminus.rs tests/ui/sse2.rs tests/ui/codegen/issue-79865-llvm-miscompile.rs tests/ui/intrinsics/intrinsics-integer.rs +tests/ui/std-backtrace.rs +tests/ui/mir/alignment/packed.rs diff --git a/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch index 9520a5a39edcd..914ae986b50e7 100644 --- a/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch +++ b/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch @@ -1,6 +1,6 @@ -From 7bcd24ec6d4a96121874cb1ae5a23ea274aeff34 Mon Sep 17 00:00:00 2001 +From a5663265f797a43c502915c356fe7899c16cee92 Mon Sep 17 00:00:00 2001 From: None -Date: Thu, 19 Oct 2023 13:12:51 -0400 +Date: Sat, 18 Nov 2023 10:50:36 -0500 Subject: [PATCH] [core] Disable portable-simd test --- @@ -8,18 +8,18 @@ Subject: [PATCH] [core] Disable portable-simd test 1 file changed, 2 deletions(-) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs -index 5814ed4..194ad4c 100644 +index d0a119c..76fdece 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs -@@ -90,7 +90,6 @@ +@@ -89,7 +89,6 @@ + #![feature(never_type)] #![feature(unwrap_infallible)] - #![feature(pointer_byte_offsets)] #![feature(pointer_is_aligned)] -#![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(lazy_cell)] #![feature(unsized_tuple_coercion)] -@@ -157,7 +156,6 @@ mod pin; +@@ -155,7 +154,6 @@ mod pin; mod pin_macro; mod ptr; mod result; @@ -28,5 +28,5 @@ index 5814ed4..194ad4c 100644 mod str; mod str_lossy; -- -2.42.0 +2.42.1 diff --git a/rust-toolchain b/rust-toolchain index 205ec53b425bf..1962c217258a4 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-21" +channel = "nightly-2023-11-17" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/base.rs b/src/base.rs index 5073066c1383c..3ffdab8b16cab 100644 --- a/src/base.rs +++ b/src/base.rs @@ -3,7 +3,6 @@ use std::env; use std::time::Instant; use gccjit::{ - Context, FunctionType, GlobalKind, }; @@ -18,8 +17,9 @@ use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoMethods; use rustc_session::config::DebugInfo; use rustc_span::Symbol; +use rustc_target::spec::PanicStrategy; -use crate::{LockedTargetInfo, gcc_util}; +use crate::{LockedTargetInfo, gcc_util, new_context}; use crate::GccContext; use crate::builder::Builder; use crate::context::CodegenCx; @@ -88,20 +88,18 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = Context::default(); + let context = new_context(&tcx); - context.add_command_line_option("-fexceptions"); - context.add_driver_option("-fexceptions"); + if tcx.sess.panic_strategy() == PanicStrategy::Unwind { + context.add_command_line_option("-fexceptions"); + context.add_driver_option("-fexceptions"); + } let disabled_features: HashSet<_> = tcx.sess.opts.cg.target_feature.split(',') .filter(|feature| feature.starts_with('-')) .map(|string| &string[1..]) .collect(); - if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { - context.add_command_line_option("-masm=intel"); - } - if !disabled_features.contains("avx") && tcx.sess.target.arch == "x86_64" { // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. diff --git a/src/int.rs b/src/int.rs index ea8550d20f362..9b9b3ea4f8704 100644 --- a/src/int.rs +++ b/src/int.rs @@ -76,6 +76,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { a >> b } } + else if a_type.is_vector() && a_type.is_vector() { + a >> b + } else if a_native && !b_native { self.gcc_lshr(a, self.gcc_int_cast(b, a_type)) } @@ -144,7 +147,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn additive_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); - if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) { if a_type != b_type { if a_type.is_vector() { // Vector types need to be bitcast. @@ -158,6 +161,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.context.new_binary_op(None, operation, a_type, a, b) } else { + debug_assert!(a_type.dyncast_array().is_some()); + debug_assert!(b_type.dyncast_array().is_some()); let signed = a_type.is_compatible_with(self.i128_type); let func_name = match (operation, signed) { @@ -189,10 +194,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn multiplicative_operation(&self, operation: BinaryOp, operation_name: &str, signed: bool, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); - if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) { self.context.new_binary_op(None, operation, a_type, a, b) } else { + debug_assert!(a_type.dyncast_array().is_some()); + debug_assert!(b_type.dyncast_array().is_some()); let sign = if signed { "" @@ -337,6 +344,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let a_type = lhs.get_type(); let b_type = rhs.get_type(); + debug_assert!(a_type.dyncast_array().is_some()); + debug_assert!(b_type.dyncast_array().is_some()); let param_a = self.context.new_parameter(None, a_type, "a"); let param_b = self.context.new_parameter(None, b_type, "b"); let result_field = self.context.new_field(None, a_type, "result"); @@ -496,7 +505,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn gcc_xor(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); - if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { + if a_type.is_vector() && b_type.is_vector() { + let b = self.bitcast_if_needed(b, a_type); + a ^ b + } + else if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) { a ^ b } else { @@ -527,6 +540,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { a << b } } + else if a_type.is_vector() && a_type.is_vector() { + a << b + } else if a_native && !b_native { self.gcc_shl(a, self.gcc_int_cast(b, a_type)) } @@ -690,6 +706,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let a_native = self.is_native_int_type_or_bool(a_type); let b_native = self.is_native_int_type_or_bool(b_type); if a_type.is_vector() && b_type.is_vector() { + let b = self.bitcast_if_needed(b, a_type); self.context.new_binary_op(None, operation, a_type, a, b) } else if a_native && b_native { @@ -748,6 +765,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return self.context.new_cast(None, value, dest_typ); } + debug_assert!(value_type.dyncast_array().is_some()); let name_suffix = match self.type_kind(dest_typ) { TypeKind::Float => "tisf", @@ -781,6 +799,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return self.context.new_cast(None, value, dest_typ); } + debug_assert!(value_type.dyncast_array().is_some()); let name_suffix = match self.type_kind(value_type) { TypeKind::Float => "sfti", diff --git a/src/lib.rs b/src/lib.rs index fd4af984bc039..fb60d7713324b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,8 @@ extern crate rustc_errors; extern crate rustc_fluent_macro; extern crate rustc_fs_util; extern crate rustc_hir; +#[cfg(feature="master")] +extern crate rustc_interface; extern crate rustc_macros; extern crate rustc_metadata; extern crate rustc_middle; @@ -86,7 +88,7 @@ use std::sync::atomic::Ordering; use gccjit::{Context, OptimizationLevel}; #[cfg(feature="master")] -use gccjit::TargetInfo; +use gccjit::{TargetInfo, Version}; #[cfg(not(feature="master"))] use gccjit::CType; use errors::LTONotSupported; @@ -244,17 +246,33 @@ impl CodegenBackend for GccCodegenBackend { } } +fn new_context<'gcc, 'tcx>(tcx: &TyCtxt<'tcx>) -> Context<'gcc> { + let context = Context::default(); + if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { + context.add_command_line_option("-masm=intel"); + } + #[cfg(feature="master")] + { + let version = Version::get(); + let version = format!("{}.{}.{}", version.major, version.minor, version.patch); + context.set_output_ident(&format!("rustc version {} with libgccjit {}", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + version, + )); + } + // TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + context +} + impl ExtraBackendMethods for GccCodegenBackend { fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module { let mut mods = GccContext { - context: Context::default(), + context: new_context(&tcx), should_combine_object_files: false, temp_dir: None, }; - if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { - mods.context.add_command_line_option("-masm=intel"); - } unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); } mods } From 456754c21a4a9e8889ac4c4ca645b5861febe1b8 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 19 Nov 2023 13:51:56 -0500 Subject: [PATCH 004/613] Pass TyCtxt by value --- src/base.rs | 2 +- src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/base.rs b/src/base.rs index 3ffdab8b16cab..b0788718da4d1 100644 --- a/src/base.rs +++ b/src/base.rs @@ -88,7 +88,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = new_context(&tcx); + let context = new_context(tcx); if tcx.sess.panic_strategy() == PanicStrategy::Unwind { context.add_command_line_option("-fexceptions"); diff --git a/src/lib.rs b/src/lib.rs index fb60d7713324b..8c7bae0c8866d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -246,7 +246,7 @@ impl CodegenBackend for GccCodegenBackend { } } -fn new_context<'gcc, 'tcx>(tcx: &TyCtxt<'tcx>) -> Context<'gcc> { +fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { let context = Context::default(); if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { context.add_command_line_option("-masm=intel"); @@ -268,7 +268,7 @@ fn new_context<'gcc, 'tcx>(tcx: &TyCtxt<'tcx>) -> Context<'gcc> { impl ExtraBackendMethods for GccCodegenBackend { fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module { let mut mods = GccContext { - context: new_context(&tcx), + context: new_context(tcx), should_combine_object_files: false, temp_dir: None, }; From a412e9c411ff13aaea0c88aeee0ad55690f2e2ce Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 22 Nov 2023 07:40:14 -0500 Subject: [PATCH 005/613] Update README --- Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Readme.md b/Readme.md index 95fc6374c09ae..20871ceb814c3 100644 --- a/Readme.md +++ b/Readme.md @@ -295,6 +295,9 @@ git pull origin master git checkout -b subtree-update_cg_gcc_YYYY-MM-DD PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master git push + +# Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. +PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name ``` TODO: write a script that does the above. From 4de5d372aab05f2c893ef83d08884e1ccfa72475 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 22 Nov 2023 09:22:39 +1100 Subject: [PATCH 006/613] Avoid need for `{D,Subd}iagnosticMessage` imports. The `fluent_messages!` macro produces uses of `crate::{D,Subd}iagnosticMessage`, which means that every crate using the macro must have this import: ``` use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; ``` This commit changes the macro to instead use `rustc_errors::{D,Subd}iagnosticMessage`, which avoids the need for the imports. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 8c7bae0c8866d..dcf7a4124c279 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods}; -use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage}; +use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; From 8e13be084a316883b4aadabbc9ff08aaaf676aa6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 22 Nov 2023 09:53:07 +1100 Subject: [PATCH 007/613] Use `rustc_fluent_macro::fluent_messages!` directly. Currently we always do this: ``` use rustc_fluent_macro::fluent_messages; ... fluent_messages! { "./example.ftl" } ``` But there is no need, we can just do this everywhere: ``` rustc_fluent_macro::fluent_messages! { "./example.ftl" } ``` which is shorter. --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index dcf7a4124c279..d54057615d2d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,7 +102,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods}; use rustc_errors::{ErrorGuaranteed, Handler}; -use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::util::Providers; @@ -116,7 +115,7 @@ use tempfile::TempDir; use crate::back::lto::ModuleBuffer; use crate::gcc_util::target_cpu; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub struct PrintOnPanic String>(pub F); From cc7c9bea1546f9dc07b39feab2d1af776804ee84 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Sat, 7 Oct 2023 23:59:58 -0500 Subject: [PATCH 008/613] implement simd_bswap intrinsic Implements lane-local byte swapping through vector shuffles. While this is more setup than non-vector shuffles, this implementation can shuffle multiple integers concurrently. Signed-off-by: Andy Sadler --- src/intrinsic/simd.rs | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 85d3e7234a0e6..3356d6f4a4b89 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -1,3 +1,5 @@ +use std::iter::FromIterator; + use gccjit::ToRValue; use gccjit::{BinaryOp, RValue, Type}; #[cfg(feature = "master")] @@ -156,6 +158,58 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op)); } + if name == sym::simd_bswap { + let vector = args[0].immediate(); + let ret = match in_elem.kind() { + ty::Int(i) if i.bit_width() == Some(8) => vector, + ty::Uint(i) if i.bit_width() == Some(8) => vector, + ty::Int(_) | ty::Uint(_) => { + let v_type = vector.get_type(); + let vector_type = v_type.unqualified().dyncast_vector().expect("vector type"); + let elem_type = vector_type.get_element_type(); + let elem_size_bytes = elem_type.get_size(); + let type_size_bytes = elem_size_bytes as u64 * in_len; + + let shuffle_indices = Vec::from_iter(0..type_size_bytes); + let byte_vector_type = bx.context.new_vector_type(bx.type_u8(), type_size_bytes); + let byte_vector = bx.context.new_bitcast(None, args[0].immediate(), byte_vector_type); + + #[cfg(not(feature = "master"))] + let shuffled = { + let new_elements: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _) + .flat_map(|x| x.iter().rev()) + .map(|&i| { + let index = bx.context.new_rvalue_from_long(bx.u64_type, i as _); + bx.extract_element(byte_vector, index) + }) + .collect(); + + bx.context.new_rvalue_from_vector(None, byte_vector_type, &new_elements) + }; + #[cfg(feature = "master")] + let shuffled = { + let indices: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _) + .flat_map(|x| x.iter().rev()) + .map(|&i| bx.context.new_rvalue_from_int(bx.u8_type, i as _)) + .collect(); + + let mask = bx.context.new_rvalue_from_vector(None, byte_vector_type, &indices); + bx.context.new_rvalue_vector_perm(None, byte_vector, byte_vector, mask) + }; + bx.context.new_bitcast(None, shuffled, v_type) + } + _ => { + return_error!(InvalidMonomorphization::UnsupportedOperation { + span, + name, + in_ty, + in_elem, + }); + } + }; + return Ok(ret); + } + if name == sym::simd_shuffle { // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. From 6d13f949ee67dbed3ee9a1da5533d3a55c03e774 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Thu, 9 Nov 2023 19:49:06 -0600 Subject: [PATCH 009/613] remove generic-bswap-byte from failing test list Signed-off-by: Andy Sadler --- failing-ui-tests.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 22044eabe9697..4b2c3f64a176f 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -57,7 +57,6 @@ tests/ui/coroutine/panic-safe.rs tests/ui/issues/issue-14875.rs tests/ui/issues/issue-29948.rs tests/ui/panics/nested_panic_caught.rs -tests/ui/simd/intrinsic/generic-bswap-byte.rs tests/ui/const_prop/ice-issue-111353.rs tests/ui/process/println-with-broken-pipe.rs tests/ui/panic-runtime/lto-abort.rs From 70586a23a7fbe5b78752438587db86678f53ee2f Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Sun, 8 Oct 2023 00:13:10 -0500 Subject: [PATCH 010/613] fix simd_frem intrinsic implementation The simd intrinsic handler was delegating implementation of `simd_frem` to `Builder::frem`, which wasn't able to handle vector-typed inputs. To fix this, teach this method how to handle vector inputs. Signed-off-by: Andy Sadler --- src/builder.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index b8a8c144dc90b..4ae56a41e529a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -606,12 +606,29 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // ../../../gcc/gcc/cfgexpand.cc:6069 // 0x7f0101bf9194 execute // ../../../gcc/gcc/cfgexpand.cc:6795 - if a.get_type().is_compatible_with(self.cx.float_type) { + let a_type = a.get_type(); + let a_type_unqualified = a_type.unqualified(); + if a_type.is_compatible_with(self.cx.float_type) { let fmodf = self.context.get_builtin_function("fmodf"); // FIXME(antoyo): this seems to produce the wrong result. return self.context.new_call(None, fmodf, &[a, b]); } - assert_eq!(a.get_type().unqualified(), self.cx.double_type); + else if let Some(vector_type) = a_type_unqualified.dyncast_vector() { + assert_eq!(a_type_unqualified, b.get_type().unqualified()); + + let num_units = vector_type.get_num_units(); + let new_elements: Vec<_> = (0..num_units) + .map(|i| { + let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _); + let x = self.extract_element(a, index).to_rvalue(); + let y = self.extract_element(b, index).to_rvalue(); + self.frem(x, y) + }) + .collect(); + + return self.context.new_rvalue_from_vector(None, a_type, &new_elements) + } + assert_eq!(a_type_unqualified, self.cx.double_type); let fmod = self.context.get_builtin_function("fmod"); return self.context.new_call(None, fmod, &[a, b]); From 8d42a82b6e86b30e9a18cd12e2a89fd7b261bdd3 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Sun, 8 Oct 2023 18:49:16 -0500 Subject: [PATCH 011/613] impl simd_bitreverse intrinsic If we're running against a patched libgccjit, use an algorithm similar to what LLVM uses for this intrinsic. Otherwise, fallback to a per-element bitreverse. Signed-off-by: Andy Sadler --- src/intrinsic/simd.rs | 213 +++++++++++++++++++++++++++++++++--------- 1 file changed, 168 insertions(+), 45 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 3356d6f4a4b89..2469e8d4c62ee 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -23,6 +23,8 @@ use rustc_target::abi::Align; use crate::builder::Builder; #[cfg(feature = "master")] use crate::context::CodegenCx; +#[cfg(not(feature = "master"))] +use crate::common::SignType; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( bx: &mut Builder<'a, 'gcc, 'tcx>, @@ -158,56 +160,177 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op)); } + let simd_bswap = |bx: &mut Builder<'a, 'gcc, 'tcx>, vector: RValue<'gcc>| -> RValue<'gcc> { + let v_type = vector.get_type(); + let vector_type = v_type.unqualified().dyncast_vector().expect("vector type"); + let elem_type = vector_type.get_element_type(); + let elem_size_bytes = elem_type.get_size(); + if elem_size_bytes == 1 { + return vector; + } + + let type_size_bytes = elem_size_bytes as u64 * in_len; + let shuffle_indices = Vec::from_iter(0..type_size_bytes); + let byte_vector_type = bx.context.new_vector_type(bx.type_u8(), type_size_bytes); + let byte_vector = bx.context.new_bitcast(None, args[0].immediate(), byte_vector_type); + + #[cfg(not(feature = "master"))] + let shuffled = { + let new_elements: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _) + .flat_map(|x| x.iter().rev()) + .map(|&i| { + let index = bx.context.new_rvalue_from_long(bx.u64_type, i as _); + bx.extract_element(byte_vector, index) + }) + .collect(); + + bx.context.new_rvalue_from_vector(None, byte_vector_type, &new_elements) + }; + #[cfg(feature = "master")] + let shuffled = { + let indices: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _) + .flat_map(|x| x.iter().rev()) + .map(|&i| bx.context.new_rvalue_from_int(bx.u8_type, i as _)) + .collect(); + + let mask = bx.context.new_rvalue_from_vector(None, byte_vector_type, &indices); + bx.context.new_rvalue_vector_perm(None, byte_vector, byte_vector, mask) + }; + bx.context.new_bitcast(None, shuffled, v_type) + }; + + if name == sym::simd_bswap || name == sym::simd_bitreverse { + require!( + bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, + InvalidMonomorphization::UnsupportedOperation { + span, + name, + in_ty, + in_elem, + } + ); + } + if name == sym::simd_bswap { - let vector = args[0].immediate(); - let ret = match in_elem.kind() { - ty::Int(i) if i.bit_width() == Some(8) => vector, - ty::Uint(i) if i.bit_width() == Some(8) => vector, - ty::Int(_) | ty::Uint(_) => { - let v_type = vector.get_type(); - let vector_type = v_type.unqualified().dyncast_vector().expect("vector type"); - let elem_type = vector_type.get_element_type(); - let elem_size_bytes = elem_type.get_size(); - let type_size_bytes = elem_size_bytes as u64 * in_len; - - let shuffle_indices = Vec::from_iter(0..type_size_bytes); - let byte_vector_type = bx.context.new_vector_type(bx.type_u8(), type_size_bytes); - let byte_vector = bx.context.new_bitcast(None, args[0].immediate(), byte_vector_type); - - #[cfg(not(feature = "master"))] - let shuffled = { - let new_elements: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _) - .flat_map(|x| x.iter().rev()) - .map(|&i| { - let index = bx.context.new_rvalue_from_long(bx.u64_type, i as _); - bx.extract_element(byte_vector, index) - }) - .collect(); + return Ok(simd_bswap(bx, args[0].immediate())); + } - bx.context.new_rvalue_from_vector(None, byte_vector_type, &new_elements) - }; - #[cfg(feature = "master")] - let shuffled = { - let indices: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _) - .flat_map(|x| x.iter().rev()) - .map(|&i| bx.context.new_rvalue_from_int(bx.u8_type, i as _)) - .collect(); - - let mask = bx.context.new_rvalue_from_vector(None, byte_vector_type, &indices); - bx.context.new_rvalue_vector_perm(None, byte_vector, byte_vector, mask) - }; - bx.context.new_bitcast(None, shuffled, v_type) + // We use a different algorithm from non-vector bitreverse to take advantage of most + // processors' vector shuffle units. It works like this: + // 1. Generate pre-reversed low and high nibbles as a vector. + // 2. Byte-swap the input. + // 3. Mask off the low and high nibbles of each byte in the byte-swapped input. + // 4. Shuffle the pre-reversed low and high-nibbles using the masked nibbles as a shuffle mask. + // 5. Combine the results of the shuffle back together and cast back to the original type. + #[cfg(feature = "master")] + if name == sym::simd_bitreverse { + let vector = args[0].immediate(); + let v_type = vector.get_type(); + let vector_type = v_type.unqualified().dyncast_vector().expect("vector type"); + let elem_type = vector_type.get_element_type(); + let elem_size_bytes = elem_type.get_size(); + + let type_size_bytes = elem_size_bytes as u64 * in_len; + // We need to ensure at least 16 entries in our vector type, since the pre-reversed vectors + // we generate below have 16 entries in them. `new_rvalue_vector_perm` requires the mask + // vector to be of the same length as the source vectors. + let byte_vector_type_size = type_size_bytes.max(16); + + let byte_vector_type = bx.context.new_vector_type(bx.u8_type, type_size_bytes); + let long_byte_vector_type = bx.context.new_vector_type(bx.u8_type, byte_vector_type_size); + + // Step 1: Generate pre-reversed low and high nibbles as a vector. + let zero_byte = bx.context.new_rvalue_zero(bx.u8_type); + let hi_nibble_elements: Vec<_> = (0u8..16) + .map(|x| bx.context.new_rvalue_from_int(bx.u8_type, x.reverse_bits() as _)) + .chain((16..byte_vector_type_size).map(|_| zero_byte)) + .collect(); + let hi_nibble = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &hi_nibble_elements); + + let lo_nibble_elements: Vec<_> = (0u8..16) + .map(|x| bx.context.new_rvalue_from_int(bx.u8_type, (x.reverse_bits() >> 4) as _)) + .chain((16..byte_vector_type_size).map(|_| zero_byte)) + .collect(); + let lo_nibble = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &lo_nibble_elements); + + let mask = bx.context.new_rvalue_from_vector( + None, + long_byte_vector_type, + &vec![bx.context.new_rvalue_from_int(bx.u8_type, 0x0f); byte_vector_type_size as _]); + + let four_vec = bx.context.new_rvalue_from_vector( + None, + long_byte_vector_type, + &vec![bx.context.new_rvalue_from_int(bx.u8_type, 4); byte_vector_type_size as _]); + + // Step 2: Byte-swap the input. + let swapped = simd_bswap(bx, args[0].immediate()); + let byte_vector = bx.context.new_bitcast(None, swapped, byte_vector_type); + + // We're going to need to extend the vector with zeros to make sure that the types are the + // same, since that's what new_rvalue_vector_perm expects. + let byte_vector = if byte_vector_type_size > type_size_bytes { + let mut byte_vector_elements = Vec::with_capacity(byte_vector_type_size as _); + for i in 0..type_size_bytes { + let idx = bx.context.new_rvalue_from_int(bx.u32_type, i as _); + let val = bx.extract_element(byte_vector, idx); + byte_vector_elements.push(val); } - _ => { - return_error!(InvalidMonomorphization::UnsupportedOperation { - span, - name, - in_ty, - in_elem, - }); + for _ in type_size_bytes..byte_vector_type_size { + byte_vector_elements.push(zero_byte); } + bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &byte_vector_elements) + } else { + bx.context.new_bitcast(None, byte_vector, long_byte_vector_type) }; - return Ok(ret); + + // Step 3: Mask off the low and high nibbles of each byte in the byte-swapped input. + let masked_hi = (byte_vector >> four_vec) & mask; + let masked_lo = byte_vector & mask; + + // Step 4: Shuffle the pre-reversed low and high-nibbles using the masked nibbles as a shuffle mask. + let hi = bx.context.new_rvalue_vector_perm(None, hi_nibble, hi_nibble, masked_lo); + let lo = bx.context.new_rvalue_vector_perm(None, lo_nibble, lo_nibble, masked_hi); + + // Step 5: Combine the results of the shuffle back together and cast back to the original type. + let result = hi | lo; + let cast_ty = bx.context.new_vector_type(elem_type, byte_vector_type_size / (elem_size_bytes as u64)); + + // we might need to truncate if sizeof(v_type) < sizeof(cast_type) + if type_size_bytes < byte_vector_type_size { + let cast_result = bx.context.new_bitcast(None, result, cast_ty); + let elems: Vec<_> = (0..in_len) + .map(|i| { + let idx = bx.context.new_rvalue_from_int(bx.u32_type, i as _); + bx.extract_element(cast_result, idx) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(None, v_type, &elems)) + } else { + // avoid the unnecessary truncation as an optimization. + return Ok(bx.context.new_bitcast(None, result, v_type)); + } + } + // since gcc doesn't have vector shuffle methods available in non-patched builds, fallback to + // component-wise bitreverses if they're not available. + #[cfg(not(feature = "master"))] + if name == sym::simd_bitreverse { + let vector = args[0].immediate(); + let vector_ty = vector.get_type(); + let vector_type = vector_ty.unqualified().dyncast_vector().expect("vector type"); + let num_elements = vector_type.get_num_units(); + + let elem_type = vector_type.get_element_type(); + let elem_size_bytes = elem_type.get_size(); + let num_type = elem_type.to_unsigned(bx.cx); + let new_elements: Vec<_> = (0..num_elements) + .map(|idx| { + let index = bx.context.new_rvalue_from_long(num_type, idx as _); + let extracted_value = bx.extract_element(vector, index).to_rvalue(); + bx.bit_reverse(elem_size_bytes as u64 * 8, extracted_value) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(None, vector_ty, &new_elements)); } if name == sym::simd_shuffle { From 03e11a214e9b6295bb06a53f849b117e75986cf6 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Thu, 19 Oct 2023 20:01:22 -0500 Subject: [PATCH 012/613] impl simd_ctlz/simd_cttz intrinsic Signed-off-by: Andy Sadler --- src/intrinsic/simd.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 2469e8d4c62ee..5991f061c10cc 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -333,6 +333,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.context.new_rvalue_from_vector(None, vector_ty, &new_elements)); } + if name == sym::simd_ctlz || name == sym::simd_cttz { + let vector = args[0].immediate(); + let elements: Vec<_> = (0..in_len) + .map(|i| { + let index = bx.context.new_rvalue_from_long(bx.i32_type, i as i64); + let value = bx.extract_element(vector, index).to_rvalue(); + if name == sym::simd_ctlz { + bx.count_leading_zeroes(value.get_type().get_size() as u64 * 8, value) + } else { + bx.count_trailing_zeroes(value.get_type().get_size() as u64 * 8, value) + } + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(None, vector.get_type(), &elements)); + } + if name == sym::simd_shuffle { // Make sure this is actually an array, since typeck only checks the length-suffixed // version of this intrinsic. From 3a221320eb49bf464fd332c2be244ca3a783d1ac Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Thu, 9 Nov 2023 19:07:44 -0600 Subject: [PATCH 013/613] fix simd_neg implementation for ints gcc_not would panic upon encountering a vector type, which is not what we want here. Signed-off-by: Andy Sadler --- src/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/int.rs b/src/int.rs index 9b9b3ea4f8704..b69e073c4d94d 100644 --- a/src/int.rs +++ b/src/int.rs @@ -48,7 +48,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn gcc_neg(&self, a: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); - if self.is_native_int_type(a_type) { + if self.is_native_int_type(a_type) || a_type.is_vector() { self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) } else { From 17b2c46c8896adf07ae8f70b0d8b70227b5f4c71 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Thu, 9 Nov 2023 19:49:34 -0600 Subject: [PATCH 014/613] remove generic-arithmetic-pass from failing tests This test now passes when tested with a patched libgccjit. However, due to [some compiler bugs][1], we can't enable this for non-patched libgccjit yet. [1]: https://github.com/sadlerap/rustc_codegen_gcc/actions/runs/6820180639/job/18548672444#step:15:4375 Signed-off-by: Andy Sadler --- failing-ui-tests.txt | 1 - failing-ui-tests12.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/failing-ui-tests.txt b/failing-ui-tests.txt index 4b2c3f64a176f..023fe9d7e8311 100644 --- a/failing-ui-tests.txt +++ b/failing-ui-tests.txt @@ -13,7 +13,6 @@ tests/ui/sepcomp/sepcomp-extern.rs tests/ui/sepcomp/sepcomp-fns-backwards.rs tests/ui/sepcomp/sepcomp-fns.rs tests/ui/sepcomp/sepcomp-statics.rs -tests/ui/simd/intrinsic/generic-arithmetic-pass.rs tests/ui/asm/x86_64/may_unwind.rs tests/ui/backtrace.rs tests/ui/catch-unwind-bang.rs diff --git a/failing-ui-tests12.txt b/failing-ui-tests12.txt index 24ef7bb8d709e..fef259c53f490 100644 --- a/failing-ui-tests12.txt +++ b/failing-ui-tests12.txt @@ -9,6 +9,7 @@ tests/ui/packed/packed-struct-vec.rs tests/ui/packed/packed-tuple-struct-layout.rs tests/ui/simd/array-type.rs tests/ui/simd/intrinsic/float-minmax-pass.rs +tests/ui/simd/intrinsic/generic-arithmetic-pass.rs tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs tests/ui/simd/intrinsic/generic-as.rs tests/ui/simd/intrinsic/generic-cast-pass.rs From bb4d0be014957067ea1386948fc1d691fff64918 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 2 Dec 2023 16:28:28 +0100 Subject: [PATCH 015/613] Fix build instructions --- Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 20871ceb814c3..9db1dec103232 100644 --- a/Readme.md +++ b/Readme.md @@ -59,13 +59,13 @@ Then you can run commands like this: ```bash $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking -$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release +$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release --features master ``` To run the tests: ```bash -$ ./test.sh --release +$ ./test.sh --release --features master ``` ## Usage From f9a228df48f24f6596aeac5373efe9ee78e7f037 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 4 Dec 2023 08:43:18 +1100 Subject: [PATCH 016/613] Rename some arguments. `sess` is a terribly misleading name for a `Handler`! This confused me for a bit. --- src/errors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 4bf3b71f503d6..5fc4b12d7e699 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -111,8 +111,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub(crate) struct MissingFeatures; impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); + fn into_diagnostic(self, handler: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); if let Some(span) = self.span { diag.set_span(span); }; From 04f32f2016495ec8aabf6ba00b47a5665811eae6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Nov 2023 16:05:35 +0100 Subject: [PATCH 017/613] Allow rustfmt to run on `build_system` --- .rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index c7ad93bafe36c..87f034950e3b2 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1 +1 @@ -disable_all_formatting = true +ignore = ["/src", "/tests"] From 7b76ac4eb74f3cf8e0d616b82f8135fd7fd7ccab Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 8 Nov 2023 17:31:56 +0100 Subject: [PATCH 018/613] Rustify `test.sh` --- build_system/src/build.rs | 128 ++-- build_system/src/config.rs | 332 ++++++---- build_system/src/prepare.rs | 18 +- build_system/src/test.rs | 1141 ++++++++++++++++++++++++++++++++++- build_system/src/utils.rs | 104 +++- 5 files changed, 1518 insertions(+), 205 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index f1c3701a946ec..6390458d4fd03 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -1,7 +1,5 @@ -use crate::config::{set_config, ConfigInfo}; -use crate::utils::{ - get_gcc_path, run_command, run_command_with_output_and_env, walk_dir, -}; +use crate::config::ConfigInfo; +use crate::utils::{get_gcc_path, run_command, run_command_with_output_and_env, walk_dir}; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; @@ -10,10 +8,9 @@ use std::path::Path; #[derive(Default)] struct BuildArg { codegen_release_channel: bool, - sysroot_release_channel: bool, - sysroot_panic_abort: bool, flags: Vec, gcc_path: String, + config_info: ConfigInfo, } impl BuildArg { @@ -29,13 +26,9 @@ impl BuildArg { while let Some(arg) = args.next() { match arg.as_str() { "--release" => build_arg.codegen_release_channel = true, - "--release-sysroot" => build_arg.sysroot_release_channel = true, "--no-default-features" => { build_arg.flags.push("--no-default-features".to_string()); } - "--sysroot-panic-abort" => { - build_arg.sysroot_panic_abort = true; - }, "--features" => { if let Some(arg) = args.next() { build_arg.flags.push("--features".to_string()); @@ -63,12 +56,14 @@ impl BuildArg { if args.next().is_some() { // Handled in config.rs. } else { - return Err( - "Expected a value after `--target`, found nothing".to_string() - ); + return Err("Expected a value after `--target`, found nothing".to_string()); + } + } + arg => { + if !build_arg.config_info.parse_argument(arg, &mut args)? { + return Err(format!("Unknown argument `{}`", arg)); } } - arg => return Err(format!("Unknown argument `{}`", arg)), } } Ok(Some(build_arg)) @@ -80,28 +75,26 @@ impl BuildArg { `build` command help: --release : Build codegen in release mode - --release-sysroot : Build sysroot in release mode - --sysroot-panic-abort : Build the sysroot without unwinding support. --no-default-features : Add `--no-default-features` flag - --features [arg] : Add a new feature [arg] - --target-triple [arg] : Set the target triple to [arg] - --help : Show this help -"# - ) + --features [arg] : Add a new feature [arg]"# + ); + ConfigInfo::show_usage(); + println!(" --help : Show this help"); } } -fn build_sysroot( - env: &mut HashMap, - args: &BuildArg, +fn build_sysroot_inner( + env: &HashMap, + sysroot_panic_abort: bool, + sysroot_release_channel: bool, config: &ConfigInfo, + start_dir: Option<&Path>, ) -> Result<(), String> { - std::env::set_current_dir("build_sysroot") - .map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?; + let start_dir = start_dir.unwrap_or_else(|| Path::new(".")); // Cleanup for previous run // Clean target dir except for build scripts and incremental cache let _ = walk_dir( - "target", + start_dir.join("target"), |dir: &Path| { for top in &["debug", "release"] { let _ = fs::remove_dir_all(dir.join(top).join("build")); @@ -138,23 +131,22 @@ fn build_sysroot( |_| Ok(()), ); - let _ = fs::remove_file("Cargo.lock"); - let _ = fs::remove_file("test_target/Cargo.lock"); - let _ = fs::remove_dir_all("sysroot"); + let _ = fs::remove_file(start_dir.join("Cargo.lock")); + let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock")); + let _ = fs::remove_dir_all(start_dir.join("sysroot")); // Builds libs - let mut rustflags = env - .get("RUSTFLAGS") - .cloned() - .unwrap_or_default(); - if args.sysroot_panic_abort { + let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + if sysroot_panic_abort { rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } - env.insert( - "RUSTFLAGS".to_string(), - format!("{} -Zmir-opt-level=3", rustflags), - ); - let channel = if args.sysroot_release_channel { + rustflags.push_str(" -Z force-unstable-if-unmarked"); + let channel = if sysroot_release_channel { + let mut env = env.clone(); + env.insert( + "RUSTFLAGS".to_string(), + format!("{} -Zmir-opt-level=3", rustflags), + ); run_command_with_output_and_env( &[ &"cargo", @@ -163,33 +155,34 @@ fn build_sysroot( &config.target, &"--release", ], - None, + Some(start_dir), Some(&env), )?; "release" } else { run_command_with_output_and_env( - &[ - &"cargo", - &"build", - &"--target", - &config.target, - ], - None, + &[&"cargo", &"build", &"--target", &config.target], + Some(start_dir), Some(env), )?; "debug" }; // Copy files to sysroot - let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", config.target_triple); - fs::create_dir_all(&sysroot_path) - .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?; + let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple)); + fs::create_dir_all(&sysroot_path).map_err(|error| { + format!( + "Failed to create directory `{}`: {:?}", + sysroot_path.display(), + error + ) + })?; let copier = |dir_to_copy: &Path| { + // FIXME: should not use shell command! run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ()) }; walk_dir( - &format!("target/{}/{}/deps", config.target_triple, channel), + start_dir.join(&format!("target/{}/{}/deps", config.target_triple, channel)), copier, copier, )?; @@ -203,7 +196,22 @@ fn build_sysroot( Ok(()) } -fn build_codegen(args: &BuildArg) -> Result<(), String> { +pub fn build_sysroot( + env: &HashMap, + sysroot_panic_abort: bool, + sysroot_release_channel: bool, + config: &ConfigInfo, +) -> Result<(), String> { + build_sysroot_inner( + env, + sysroot_panic_abort, + sysroot_release_channel, + config, + Some(Path::new("build_sysroot")), + ) +} + +fn build_codegen(args: &mut BuildArg) -> Result<(), String> { let mut env = HashMap::new(); env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); @@ -223,7 +231,8 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - let config = set_config(&mut env, &[], Some(&args.gcc_path))?; + args.config_info + .setup(&mut env, &[], Some(&args.gcc_path))?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); @@ -237,18 +246,19 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> { println!("[BUILD] sysroot"); build_sysroot( - &mut env, - args, - &config, + &env, + args.config_info.sysroot_panic_abort, + args.config_info.sysroot_release_channel, + &args.config_info, )?; Ok(()) } pub fn run() -> Result<(), String> { - let args = match BuildArg::new()? { + let mut args = match BuildArg::new()? { Some(args) => args, None => return Ok(()), }; - build_codegen(&args)?; + build_codegen(&mut args)?; Ok(()) } diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 64d9bd73e01a3..763cac8edb66b 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -1,149 +1,229 @@ -use crate::utils::{get_gcc_path, get_os_name, get_rustc_host_triple}; +use crate::utils::{get_gcc_path, get_os_name, rustc_version_info, split_args}; use std::collections::HashMap; use std::env as std_env; +#[derive(Default)] pub struct ConfigInfo { pub target: String, pub target_triple: String, + pub host_triple: String, pub rustc_command: Vec, + pub run_in_vm: bool, + pub cargo_target_dir: String, + pub dylib_ext: String, + pub sysroot_release_channel: bool, + pub sysroot_panic_abort: bool, } -// Returns the beginning for the command line of rustc. -pub fn set_config( - env: &mut HashMap, - test_flags: &[String], - gcc_path: Option<&str>, -) -> Result { - env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - - let gcc_path = match gcc_path { - Some(path) => path.to_string(), - None => get_gcc_path()?, - }; - env.insert("GCC_PATH".to_string(), gcc_path.clone()); - - let os_name = get_os_name()?; - let dylib_ext = match os_name.as_str() { - "Linux" => "so", - "Darwin" => "dylib", - os => return Err(format!("unsupported OS `{}`", os)), - }; - let host_triple = get_rustc_host_triple()?; - let mut linker = None; - let mut target_triple = host_triple.clone(); - let mut target = target_triple.clone(); - - // We skip binary name and the command. - let mut args = std::env::args().skip(2); - - let mut set_target_triple = false; - let mut set_target = false; - while let Some(arg) = args.next() { - match arg.as_str() { - "--target-triple" => { - if let Some(arg) = args.next() { - target_triple = arg; - set_target_triple = true; - } else { +impl ConfigInfo { + /// Returns `true` if the argument was taken into account. + pub fn parse_argument( + &mut self, + arg: &str, + args: &mut impl Iterator, + ) -> Result { + match arg { + "--target-triple" => match args.next() { + Some(arg) if !arg.is_empty() => self.target_triple = arg.to_string(), + _ => { return Err( "Expected a value after `--target-triple`, found nothing".to_string() - ); + ) } }, - "--target" => { - if let Some(arg) = args.next() { - target = arg; - set_target = true; - } else { - return Err( - "Expected a value after `--target`, found nothing".to_string() - ); + "--target" => match args.next() { + Some(arg) if !arg.is_empty() => self.target = arg.to_string(), + _ => return Err("Expected a value after `--target`, found nothing".to_string()), + }, + "--out-dir" => match args.next() { + Some(arg) if !arg.is_empty() => { + // env.insert("CARGO_TARGET_DIR".to_string(), arg.to_string()); + self.cargo_target_dir = arg.to_string(); } + _ => return Err("Expected a value after `--out-dir`, found nothing".to_string()), }, - _ => (), + "--release-sysroot" => self.sysroot_release_channel = true, + "--sysroot-panic-abort" => self.sysroot_panic_abort = true, + _ => return Ok(false), } + Ok(true) } - if set_target_triple && !set_target { - target = target_triple.clone(); - } + pub fn setup( + &mut self, + env: &mut HashMap, + test_flags: &[String], + gcc_path: Option<&str>, + ) -> Result<(), String> { + env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - if host_triple != target_triple { - linker = Some(format!("-Clinker={}-gcc", target_triple)); - } - let current_dir = - std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; - let channel = if let Some(channel) = env.get("CHANNEL") { - channel.as_str() - } else { - "debug" - }; - let cg_backend_path = current_dir - .join("target") - .join(channel) - .join(&format!("librustc_codegen_gcc.{}", dylib_ext)); - let sysroot_path = current_dir.join("build_sysroot/sysroot"); - let mut rustflags = Vec::new(); - if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { - rustflags.push(cg_rustflags.clone()); - } - if let Some(linker) = linker { - rustflags.push(linker.to_string()); - } - rustflags.extend_from_slice(&[ - "-Csymbol-mangling-version=v0".to_string(), - "-Cdebuginfo=2".to_string(), - format!("-Zcodegen-backend={}", cg_backend_path.display()), - "--sysroot".to_string(), - sysroot_path.display().to_string(), - ]); - - // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. - // TODO(antoyo): remove when we can handle ThinLTO. - if !env.contains_key(&"FAT_LTO".to_string()) { - rustflags.push("-Clto=off".to_string()); - } - rustflags.extend_from_slice(test_flags); - // FIXME(antoyo): remove once the atomic shim is gone - if os_name == "Darwin" { + let gcc_path = match gcc_path { + Some(path) => path.to_string(), + None => get_gcc_path()?, + }; + env.insert("GCC_PATH".to_string(), gcc_path.clone()); + + if self.cargo_target_dir.is_empty() { + match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) { + Some(cargo_target_dir) => self.cargo_target_dir = cargo_target_dir.clone(), + None => self.cargo_target_dir = "target/out".to_string(), + } + } + + let os_name = get_os_name()?; + self.dylib_ext = match os_name.as_str() { + "Linux" => "so", + "Darwin" => "dylib", + os => return Err(format!("unsupported OS `{}`", os)), + } + .to_string(); + let rustc = match env.get("RUSTC") { + Some(r) if !r.is_empty() => r.to_string(), + _ => "rustc".to_string(), + }; + self.host_triple = rustc_version_info(Some(&rustc))?.host.unwrap_or_default(); + + if !self.target_triple.is_empty() && self.target.is_empty() { + self.target = self.target_triple.clone(); + } + if self.target.is_empty() { + self.target = self.host_triple.clone(); + } + if self.target_triple.is_empty() { + self.target_triple = self.host_triple.clone(); + } + + let mut linker = None; + + if self.host_triple != self.target_triple { + if self.target_triple == "m68k-unknown-linux-gnu" { + linker = Some("-Clinker=m68k-unknown-linux-gnu-gcc".to_string()); + } else if self.target_triple == "aarch64-unknown-linux-gnu" { + // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. + linker = Some("-Clinker=aarch64-linux-gnu-gcc".to_string()); + } else { + return Err("Unknown non-native platform".to_string()); + } + + self.run_in_vm = true; + } + + let current_dir = + std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; + let channel = if let Some(channel) = env.get("CHANNEL") { + channel.as_str() + } else { + "debug" + }; + + let has_builtin_backend = env + .get("BUILTIN_BACKEND") + .map(|backend| !backend.is_empty()) + .unwrap_or(false); + let cg_backend_path; + + let mut rustflags = Vec::new(); + if has_builtin_backend { + // It means we're building inside the rustc testsuite, so some options need to be handled + // a bit differently. + cg_backend_path = "gcc".to_string(); + + match env.get("RUSTC_SYSROOT") { + Some(rustc_sysroot) if !rustc_sysroot.is_empty() => { + rustflags.extend_from_slice(&["--sysroot".to_string(), rustc_sysroot.clone()]); + } + _ => {} + } + rustflags.push("-Cpanic=abort".to_string()); + } else { + cg_backend_path = current_dir + .join("target") + .join(channel) + .join(&format!("librustc_codegen_gcc.{}", self.dylib_ext)) + .display() + .to_string(); + let sysroot_path = current_dir.join("build_sysroot/sysroot"); + rustflags + .extend_from_slice(&["--sysroot".to_string(), sysroot_path.display().to_string()]); + }; + + if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { + rustflags.extend_from_slice(&split_args(&cg_rustflags)); + } + if let Some(linker) = linker { + rustflags.push(linker.to_string()); + } rustflags.extend_from_slice(&[ - "-Clink-arg=-undefined".to_string(), - "-Clink-arg=dynamic_lookup".to_string(), + "-Csymbol-mangling-version=v0".to_string(), + "-Cdebuginfo=2".to_string(), + format!("-Zcodegen-backend={}", cg_backend_path), ]); + + // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. + // TODO(antoyo): remove when we can handle ThinLTO. + if !env.contains_key(&"FAT_LTO".to_string()) { + rustflags.push("-Clto=off".to_string()); + } + rustflags.extend_from_slice(test_flags); + // FIXME(antoyo): remove once the atomic shim is gone + if os_name == "Darwin" { + rustflags.extend_from_slice(&[ + "-Clink-arg=-undefined".to_string(), + "-Clink-arg=dynamic_lookup".to_string(), + ]); + } + env.insert("RUSTFLAGS".to_string(), rustflags.join(" ")); + // display metadata load errors + env.insert("RUSTC_LOG".to_string(), "warn".to_string()); + + let sysroot = current_dir.join(&format!( + "build_sysroot/sysroot/lib/rustlib/{}/lib", + self.target_triple, + )); + let ld_library_path = format!( + "{target}:{sysroot}:{gcc_path}", + target = current_dir.join("target/out").display(), + sysroot = sysroot.display(), + ); + env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); + env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path); + + // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc. + // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH. + // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc + let path = std::env::var("PATH").unwrap_or_default(); + env.insert( + "PATH".to_string(), + format!( + "/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin{}{}", + if path.is_empty() { "" } else { ":" }, + path + ), + ); + + self.rustc_command = vec![rustc]; + self.rustc_command.extend_from_slice(&rustflags); + self.rustc_command.extend_from_slice(&[ + "-L".to_string(), + "crate=target/out".to_string(), + "--out-dir".to_string(), + self.cargo_target_dir.clone(), + ]); + + if !env.contains_key("RUSTC_LOG") { + env.insert("RUSTC_LOG".to_string(), "warn".to_string()); + } + Ok(()) + } + + pub fn show_usage() { + println!( + "\ + --target [arg] : Set the target to [arg] + --target-triple [arg] : Set the target triple to [arg] + --out-dir : Location where the files will be generated + --release-sysroot : Build sysroot in release mode + --sysroot-panic-abort : Build the sysroot without unwinding support." + ); } - env.insert("RUSTFLAGS".to_string(), rustflags.join(" ")); - // display metadata load errors - env.insert("RUSTC_LOG".to_string(), "warn".to_string()); - - let sysroot = current_dir.join(&format!( - "build_sysroot/sysroot/lib/rustlib/{}/lib", - target_triple - )); - let ld_library_path = format!( - "{target}:{sysroot}:{gcc_path}", - target = current_dir.join("target/out").display(), - sysroot = sysroot.display(), - ); - env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); - env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path); - - // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc. - // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH. - // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc - let path = std::env::var("PATH").unwrap_or_default(); - env.insert("PATH".to_string(), format!("/opt/gcc/bin:{}", path)); - - let mut rustc_command = vec!["rustc".to_string()]; - rustc_command.extend_from_slice(&rustflags); - rustc_command.extend_from_slice(&[ - "-L".to_string(), - "crate=target/out".to_string(), - "--out-dir".to_string(), - "target/out".to_string(), - ]); - Ok(ConfigInfo { - target, - target_triple, - rustc_command, - }) } diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 6c7c858683456..da9f8953ec3cb 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -4,7 +4,11 @@ use crate::utils::{cargo_install, git_clone, run_command, run_command_with_outpu use std::fs; use std::path::Path; -fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile: bool) -> Result<(), String> { +fn prepare_libcore( + sysroot_path: &Path, + libgccjit12_patches: bool, + cross_compile: bool, +) -> Result<(), String> { let rustc_path = match get_rustc_path() { Some(path) => path, None => return Err("`rustc` path not found".to_string()), @@ -88,10 +92,14 @@ fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile }, )?; if cross_compile { - walk_dir("cross_patches", |_| Ok(()), |file_path: &Path| { - patches.push(file_path.to_path_buf()); - Ok(()) - })?; + walk_dir( + "cross_patches", + |_| Ok(()), + |file_path: &Path| { + patches.push(file_path.to_path_buf()); + Ok(()) + }, + )?; } if libgccjit12_patches { walk_dir( diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 4c8c63e59ab7c..fb2b24da9a233 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,15 +1,1138 @@ -use crate::utils::run_command_with_output; +use crate::build; +use crate::config::ConfigInfo; +use crate::utils::{ + get_gcc_path, get_toolchain, run_command, run_command_with_env, + run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, +}; -fn get_args<'a>(args: &mut Vec<&'a dyn AsRef>, extra_args: &'a Vec) { - for extra_arg in extra_args { - args.push(extra_arg); +use std::collections::{BTreeSet, HashMap}; +use std::ffi::OsStr; +use std::fs::remove_dir_all; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +type Env = HashMap; +type Runner = &'static dyn Fn(&Env, &TestArg) -> Result<(), String>; +type Runners = HashMap<&'static str, (&'static str, Runner)>; + +fn get_runners() -> Runners { + let mut runners = HashMap::new(); + + runners.insert( + "--test-rustc", + ("Run all rustc tests", &test_rustc as Runner), + ); + runners.insert( + "--test-successful-rustc", + ("Run successful rustc tests", &test_successful_rustc), + ); + runners.insert( + "--test-failing-rustc", + ("Run failing rustc tests", &test_failing_rustc), + ); + runners.insert("--test-libcore", ("Run libcore tests", &test_libcore)); + runners.insert("--clean-ui-tests", ("Clean ui tests", &clean_ui_tests)); + runners.insert("--clean", ("Empty cargo target directory", &clean)); + runners.insert("--std-tests", ("Run std tests", &std_tests)); + runners.insert("--asm-tests", ("Run asm tests", &asm_tests)); + runners.insert( + "--extended-tests", + ("Run extended sysroot tests", &extended_sysroot_tests), + ); + runners.insert( + "--extended-rand-tests", + ("Run extended rand tests", &extended_rand_tests), + ); + runners.insert( + "--extended-regex-example-tests", + ( + "Run extended regex example tests", + &extended_regex_example_tests, + ), + ); + runners.insert( + "--extended-regex-tests", + ("Run extended regex tests", &extended_regex_tests), + ); + runners.insert("--mini-tests", ("Run mini tests", &mini_tests)); + + runners +} + +fn get_number_after_arg( + args: &mut impl Iterator, + option: &str, +) -> Result { + match args.next() { + Some(nb) if !nb.is_empty() => match usize::from_str(&nb) { + Ok(nb) => Ok(nb), + Err(_) => Err(format!( + "Expected a number after `{}`, found `{}`", + option, nb + )), + }, + _ => Err(format!( + "Expected a number after `{}`, found nothing", + option + )), + } +} + +fn show_usage() { + println!( + r#" +`test` command help: + + --release : Build codegen in release mode + --release-sysroot : Build sysroot in release mode + --sysroot-panic-abort : Build the sysroot without unwinding support. + --no-default-features : Add `--no-default-features` flag + --features [arg] : Add a new feature [arg] + --use-system-gcc : Use system installed libgccjit + --build-only : Only build rustc_codegen_gcc then exits + --use-backend : Useful only for rustc testsuite + --nb-parts : Used to split rustc_tests (for CI needs) + --current-part : Used with `--nb-parts`, allows you to specify which parts to test"# + ); + ConfigInfo::show_usage(); + for (option, (doc, _)) in get_runners() { + let needed_spaces = 23_usize.saturating_sub(option.len()); + let spaces: String = std::iter::repeat(' ').take(needed_spaces).collect(); + println!(" {}{}: {}", option, spaces, doc); } + println!(" --help : Show this help"); +} + +#[derive(Default, PartialEq, Eq, Clone, Copy)] +enum Channel { + #[default] + Debug, + Release, +} + +impl Channel { + pub fn as_str(self) -> &'static str { + match self { + Self::Debug => "debug", + Self::Release => "release", + } + } +} + +#[derive(Default)] +struct TestArg { + no_default_features: bool, + build_only: bool, + gcc_path: String, + channel: Channel, + sysroot_channel: Channel, + use_backend: bool, + runners: BTreeSet, + flags: Vec, + backend: Option, + nb_parts: Option, + current_part: Option, + sysroot_panic_abort: bool, + config_info: ConfigInfo, +} + +impl TestArg { + fn new() -> Result, String> { + let mut use_system_gcc = false; + let mut test_arg = Self::default(); + + // We skip binary name and the `test` command. + let mut args = std::env::args().skip(2); + let runners = get_runners(); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--release" => test_arg.channel = Channel::Release, + "--release-sysroot" => test_arg.sysroot_channel = Channel::Release, + "--no-default-features" => { + // To prevent adding it more than once. + if !test_arg.no_default_features { + test_arg.flags.push("--no-default-features".into()); + } + test_arg.no_default_features = true; + } + "--features" => match args.next() { + Some(feature) if !feature.is_empty() => { + test_arg + .flags + .extend_from_slice(&["--features".into(), feature]); + } + _ => { + return Err("Expected an argument after `--features`, found nothing".into()) + } + }, + "--use-system-gcc" => use_system_gcc = true, + "--build-only" => test_arg.build_only = true, + "--use-backend" => match args.next() { + Some(backend) if !backend.is_empty() => test_arg.backend = Some(backend), + _ => { + return Err( + "Expected an argument after `--use-backend`, found nothing".into() + ) + } + }, + "--nb-parts" => { + test_arg.nb_parts = Some(get_number_after_arg(&mut args, "--nb-parts")?); + } + "--current-part" => { + test_arg.current_part = + Some(get_number_after_arg(&mut args, "--current-part")?); + } + "--sysroot-panic-abort" => { + test_arg.sysroot_panic_abort = true; + } + "--help" => { + show_usage(); + return Ok(None); + } + x if runners.contains_key(x) => { + test_arg.runners.insert(x.into()); + } + arg => { + if !test_arg.config_info.parse_argument(arg, &mut args)? { + return Err(format!("Unknown option {}", arg)); + } + } + } + + test_arg.gcc_path = if use_system_gcc { + println!("Using system GCC"); + "gcc".to_string() + } else { + get_gcc_path()? + }; + } + Ok(Some(test_arg)) + } +} + +fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> { + if args.use_backend { + return Ok(()); + } + let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; + if args.channel == Channel::Release { + let mut env = env.clone(); + env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); + command.push(&"--release"); + for flag in args.flags.iter() { + command.push(flag); + } + run_command_with_output_and_env(&command, None, Some(&env)) + } else { + for flag in args.flags.iter() { + command.push(flag); + } + run_command_with_output_and_env(&command, None, Some(&env)) + } +} + +fn clean(_env: &Env, args: &TestArg) -> Result<(), String> { + let _ = std::fs::remove_dir_all(&args.config_info.cargo_target_dir); + let path = Path::new(&args.config_info.cargo_target_dir).join("gccjit"); + std::fs::create_dir_all(&path) + .map_err(|error| format!("failed to create folder `{}`: {:?}", path.display(), error)) +} + +fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[BUILD] mini_core"); + let crate_types = if args.config_info.host_triple != args.config_info.target_triple { + "lib" + } else { + "lib,dylib" + } + .to_string(); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/mini_core.rs", + &"--crate-name", + &"mini_core", + &"--crate-type", + &crate_types, + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_output_and_env(&command, None, Some(&env))?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[BUILD] example"); + command.clear(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/example.rs", + &"--crate-type", + &"lib", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_output_and_env(&command, None, Some(&env))?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] mini_core_hello_world"); + command.clear(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/mini_core_hello_world.rs", + &"--crate-name", + &"mini_core_hello_world", + &"--crate-type", + &"bin", + &"-g", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_output_and_env(&command, None, Some(&env))?; + + let command: &[&dyn AsRef] = &[ + &Path::new(&args.config_info.cargo_target_dir).join("mini_core_hello_world"), + &"abc", + &"bcd", + ]; + run_command_in_vm(&command, env, args)?; + Ok(()) +} + +fn build_sysroot(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[BUILD] sysroot"); + build::build_sysroot( + env, + args.config_info.sysroot_panic_abort, + args.config_info.sysroot_release_channel, + &args.config_info, + )?; + Ok(()) +} + +// TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible. +fn run_command_in_vm( + command: &[&dyn AsRef], + env: &Env, + args: &TestArg, +) -> Result<(), String> { + if !args.config_info.run_in_vm { + run_command_with_env(command, None, Some(env))?; + return Ok(()); + } + let vm_parent_dir = match env.get("CG_GCC_VM_DIR") { + Some(dir) if !dir.is_empty() => PathBuf::from(dir.clone()), + _ => std::env::current_dir().unwrap(), + }; + let vm_dir = "vm"; + let exe_to_run = command.first().unwrap(); + let exe = Path::new(&exe_to_run); + let exe_filename = exe.file_name().unwrap(); + let vm_home_dir = vm_parent_dir.join(vm_dir).join("home"); + let vm_exe_path = vm_home_dir.join(exe_filename); + let inside_vm_exe_path = Path::new("/home").join(exe_filename); + + let sudo_command: &[&dyn AsRef] = &[&"sudo", &"cp", &exe, &vm_exe_path]; + run_command_with_env(sudo_command, None, Some(env))?; + + let mut vm_command: Vec<&dyn AsRef> = + vec![&"sudo", &"chroot", &"qemu-m68k-static", &inside_vm_exe_path]; + vm_command.extend_from_slice(command); + run_command_with_env(&vm_command, Some(&vm_parent_dir), Some(env))?; + Ok(()) +} + +fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] arbitrary_self_types_pointers_and_wrappers"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/arbitrary_self_types_pointers_and_wrappers.rs", + &"--crate-name", + &"arbitrary_self_types_pointers_and_wrappers", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_env(&command, None, Some(env))?; + run_command_in_vm( + &[&Path::new(&args.config_info.cargo_target_dir) + .join("arbitrary_self_types_pointers_and_wrappers")], + env, + args, + )?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] alloc_system"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/alloc_system.rs", + &"--crate-type", + &"lib", + &"--target", + &args.config_info.target_triple, + ]); + if !args.no_default_features { + command.push(&"--cfg feature=\"master\""); + } + run_command_with_env(&command, None, Some(env))?; + + // FIXME: doesn't work on m68k. + if args.config_info.host_triple != args.config_info.target_triple { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] alloc_example"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/alloc_example.rs", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_env(&command, None, Some(env))?; + run_command_in_vm( + &[&Path::new(&args.config_info.cargo_target_dir).join("alloc_example")], + env, + args, + )?; + } + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] dst_field_align"); + // FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed. + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/dst-field-align.rs", + &"--crate-name", + &"dst_field_align", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_env(&command, None, Some(env))?; + run_command_in_vm( + &[&Path::new(&args.config_info.cargo_target_dir).join("dst_field_align")], + env, + args, + )?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] std_example"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/std_example.rs", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + if !args.no_default_features { + command.push(&"--cfg feature=\"master\""); + } + run_command_with_env(&command, None, Some(env))?; + run_command_in_vm( + &[ + &Path::new(&args.config_info.cargo_target_dir).join("std_example"), + &"--target", + &args.config_info.target_triple, + ], + env, + args, + )?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] subslice-patterns-const-eval"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/subslice-patterns-const-eval.rs", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_env(&command, None, Some(env))?; + run_command_in_vm( + &[&Path::new(&args.config_info.cargo_target_dir).join("subslice-patterns-const-eval")], + env, + args, + )?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] track-caller-attribute"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/track-caller-attribute.rs", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_env(&command, None, Some(env))?; + run_command_in_vm( + &[&Path::new(&args.config_info.cargo_target_dir).join("track-caller-attribute")], + env, + args, + )?; + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[AOT] mod_bench"); + let mut command: Vec<&dyn AsRef> = Vec::new(); + for arg in args.config_info.rustc_command.iter() { + command.push(arg); + } + command.extend_from_slice(&[ + &"example/mod_bench.rs", + &"--crate-type", + &"bin", + &"--target", + &args.config_info.target_triple, + ]); + run_command_with_env(&command, None, Some(env))?; + // FIXME: the compiled binary is not run. Is it normal? + + Ok(()) +} + +fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { + let toolchain = get_toolchain()?; + + let rust_dir = Some(Path::new("rust")); + // If the repository was already cloned, command will fail, so doesn't matter. + let _ = run_command_with_output_and_env( + &[&"git", &"clone", &"https://github.com/rust-lang/rust.git"], + None, + Some(env), + ); + run_command_with_output_and_env(&[&"git", &"fetch"], rust_dir, Some(env))?; + let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { + Some(commit_hash) => commit_hash, + None => return Err("Couldn't retrieve rustc commit hash".to_string()), + }; + run_command_with_output_and_env(&[&"git", &"checkout", &rustc_commit], rust_dir, Some(env))?; + env.insert("RUSTFLAGS".to_string(), String::new()); + let cargo = String::from_utf8( + run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout, + ) + .map_err(|error| format!("Failed to retrieve cargo path: {:?}", error)) + .and_then(|cargo| { + let cargo = cargo.trim().to_owned(); + if cargo.is_empty() { + Err(format!("`cargo` path is empty")) + } else { + Ok(cargo) + } + })?; + let llvm_filecheck = String::from_utf8( + run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ + which FileCheck-11 || \ + which FileCheck-12 || \ + which FileCheck-13 || \ + which FileCheck-14", + ], + rust_dir, + Some(env), + )? + .stdout, + ) + .map_err(|error| format!("Failed to retrieve LLVM FileCheck: {:?}", error))?; + std::fs::write( + "rust/config.toml", + &format!( + r#"change-id = 115898 + +[rust] +codegen-backends = [] +deny-warnings = false +verbose-tests = true + +[build] +cargo = "{cargo}" +local-rebuild = true +rustc = "{home}/.rustup/toolchains/{toolchain}-{host_triple}/bin/rustc" + +[target.x86_64-unknown-linux-gnu] +llvm-filecheck = "{llvm_filecheck}" + +[llvm] +download-ci-llvm = false +"#, + cargo = cargo.trim(), + home = env.get("HOME").unwrap(), + toolchain = toolchain, + host_triple = args.config_info.host_triple, + llvm_filecheck = llvm_filecheck, + ), + ) + .map_err(|error| format!("Failed to write into `rust/config.toml`: {:?}", error))?; + + let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { + Some(commit_hash) => commit_hash, + None => return Err("Couldn't retrieve rustc commit hash".to_string()), + }; + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("commit: {:?}", rustc_commit); + let command: &[&dyn AsRef] = &[&"git", &"checkout", &rustc_commit, &"tests"]; + run_command_with_output_and_env(command, rust_dir, Some(env))?; + Ok(()) +} + +fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { + let mut env = env.clone(); + setup_rustc(&mut env, args)?; + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] rustc asm test suite"); + + env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); + + run_command_with_env( + &[ + &"./x.py", + &"test", + &"--run", + &"always", + &"--stage", + &"0", + &"tests/assembly/asm", + &"--rustc-args", + &format!( + r#"-Zpanic-abort-tests -Csymbol-mangling-version=v0 \ + -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ + --sysroot "{pwd}/build_sysroot/sysroot" -Cpanic=abort"#, + pwd = std::env::current_dir() + .map_err(|error| format!("`current_dir` failed: {:?}", error))? + .display(), + channel = args.channel.as_str(), + dylib_ext = args.config_info.dylib_ext, + ) + .as_str(), + ], + Some(Path::new("rust")), + Some(&env), + )?; + Ok(()) +} + +fn run_cargo_command( + command: &[&dyn AsRef], + cwd: Option<&Path>, + env: &Env, + args: &TestArg, +) -> Result<(), String> { + run_cargo_command_with_callback(command, cwd, env, args, |cargo_command, cwd, env| { + run_command_with_output_and_env(&cargo_command, cwd, Some(env))?; + Ok(()) + }) +} + +fn run_cargo_command_with_callback( + command: &[&dyn AsRef], + cwd: Option<&Path>, + env: &Env, + args: &TestArg, + callback: F, +) -> Result<(), String> +where + F: Fn(&[&dyn AsRef], Option<&Path>, &Env) -> Result<(), String>, +{ + let toolchain = get_toolchain()?; + let rustc_version = String::from_utf8( + run_command_with_env(&[&args.config_info.rustc_command[0], &"-V"], cwd, Some(env))?.stdout, + ) + .map_err(|error| format!("Failed to retrieve rustc version: {:?}", error))?; + let rustc_toolchain_version = String::from_utf8( + run_command_with_env( + &[ + &args.config_info.rustc_command[0], + &format!("+{}", toolchain), + &"-V", + ], + cwd, + Some(env), + )? + .stdout, + ) + .map_err(|error| format!("Failed to retrieve rustc +toolchain version: {:?}", error))?; + + if rustc_version != rustc_toolchain_version { + eprintln!( + "rustc_codegen_gcc is built for `{}` but the default rustc version is `{}`.", + rustc_toolchain_version, rustc_version, + ); + eprintln!("Using `{}`.", rustc_toolchain_version); + } + let mut cargo_command: Vec<&dyn AsRef> = vec![&"cargo", &toolchain]; + cargo_command.extend_from_slice(&command); + callback(&cargo_command, cwd, env) +} + +// FIXME(antoyo): linker gives multiple definitions error on Linux +// echo "[BUILD] sysroot in release mode" +// ./build_sysroot/build_sysroot.sh --release + +fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] libcore"); + let path = Path::new("build_sysroot/sysroot_src/library/core/tests"); + let _ = remove_dir_all(path.join("target")); + run_cargo_command(&[&"test"], Some(path), env, args)?; + Ok(()) +} + +// echo "[BENCH COMPILE] mod_bench" +// +// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline" +// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort" +// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort" +// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort" +// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort" +// +// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow +// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3" +// echo "[BENCH RUN] mod_bench" +// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_* + +fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { + if args.no_default_features { + return Ok(()); + } + let path = Path::new("rand"); + run_cargo_command(&[&"clean"], Some(path), env, args)?; + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] rust-random/rand"); + run_cargo_command(&[&"test", &"--workspace"], Some(path), env, args)?; + Ok(()) +} + +fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> { + if args.no_default_features { + return Ok(()); + } + let path = Path::new("regex"); + run_cargo_command(&[&"clean"], Some(path), env, args)?; + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] rust-lang/regex example shootout-regex-dna"); + let mut env = env.clone(); + // newer aho_corasick versions throw a deprecation warning + env.insert("CG_RUSTFLAGS".to_string(), "--cap-lints warn".to_string()); + // Make sure `[codegen mono items] start` doesn't poison the diff + run_cargo_command( + &[&"build", &"--example", &"shootout-regex-dna"], + Some(path), + &env, + args, + )?; + + run_cargo_command_with_callback( + &[&"run", &"--example", &"shootout-regex-dna"], + Some(path), + &env, + args, + |cargo_command, cwd, env| { + // FIXME: rewrite this with `child.stdin.write_all()` because + // `examples/regexdna-input.txt` is very small. + let mut command: Vec<&dyn AsRef> = vec![&"bash", &"-c"]; + let cargo_args = cargo_command + .iter() + .map(|s| s.as_ref().to_str().unwrap()) + .collect::>(); + let bash_command = format!( + "cat examples/regexdna-input.txt | {} | grep -v 'Spawned thread' > res.txt", + cargo_args.join(" "), + ); + command.push(&bash_command); + run_command_with_output_and_env(&command, cwd, Some(env))?; + run_command_with_output_and_env( + &[&"diff", &"-u", &"res.txt", &"examples/regexdna-output.txt"], + cwd, + Some(env), + )?; + Ok(()) + }, + )?; + + Ok(()) +} + +fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { + if args.no_default_features { + return Ok(()); + } + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] rust-lang/regex tests"); + let mut env = env.clone(); + env.insert("CG_RUSTFLAGS".to_string(), "--cap-lints warn".to_string()); + run_cargo_command( + &[ + &"test", + &"--tests", + &"--", + &"--exclude-should-panic", + &"--test-threads", + &"1", + &"-Zunstable-options", + &"-q", + ], + Some(Path::new("regex")), + &env, + args, + )?; + Ok(()) +} + +fn extended_sysroot_tests(env: &Env, args: &TestArg) -> Result<(), String> { + // pushd simple-raytracer + // echo "[BENCH COMPILE] ebobby/simple-raytracer" + // hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \ + // "RUSTC=rustc RUSTFLAGS='' cargo build" \ + // "../cargo.sh build" + + // echo "[BENCH RUN] ebobby/simple-raytracer" + // cp ./target/debug/main ./raytracer_cg_gcc + // hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_gcc + // popd + extended_rand_tests(env, args)?; + extended_regex_example_tests(env, args)?; + extended_regex_tests(env, args)?; + + Ok(()) +} + +fn should_remove_ui_test(content: &str) -> bool { + for line in content + .lines() + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + { + if [ + "// error-pattern:", + "// build-fail", + "// run-fail", + "-Cllvm-args", + "//~", + "// ~", + ] + .iter() + .any(|check| line.contains(check)) + { + return true; + } + } + false +} + +fn should_not_remove_test(file: &str) -> bool { + // contains //~ERROR, but shouldn't be removed + [ + "issues/auxiliary/issue-3136-a.rs", + "type-alias-impl-trait/auxiliary/cross_crate_ice.rs", + "type-alias-impl-trait/auxiliary/cross_crate_ice2.rs", + "macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs", + "imports/ambiguous-1.rs", + "imports/ambiguous-4-extern.rs", + "entry-point/auxiliary/bad_main_functions.rs", + ] + .iter() + .any(|to_ignore| file.ends_with(to_ignore)) +} + +fn should_remove_test(path: &Path, path_str: &str) -> bool { + // Tests generating errors. + path.file_name() + .and_then(|name| name.to_str()) + .map(|name| name.contains("thread")) + .unwrap_or(false) + || [ + "consts/issue-miri-1910.rs", + // Tests generating errors. + "consts/issue-94675.rs", + // this test is oom-killed in the CI. + "mir/mir_heavy/issue-miri-1910.rs", + ] + .iter() + .any(|to_ignore| path_str.ends_with(to_ignore)) +} + +fn test_rustc_inner(env: &Env, args: &TestArg, callback: F) -> Result<(), String> +where + F: Fn() -> Result, +{ + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] rust-lang/rust"); + walk_dir( + "rust/tests/ui", + |dir| { + let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or(""); + if [ + "abi", + "extern", + "unsized-locals", + "proc-macro", + "threads-sendsync", + "borrowck", + "test-attrs", + ] + .iter() + .any(|name| *name == dir_name) + { + std::fs::remove_dir_all(dir).map_err(|error| { + format!("Failed to remove folder `{}`: {:?}", dir.display(), error) + })?; + } + Ok(()) + }, + |_| Ok(()), + )?; + + fn dir_handling(dir: &Path) -> Result<(), String> { + walk_dir(dir, dir_handling, file_handling) + } + fn file_handling(file: &Path) -> Result<(), String> { + let path_str = file.display().to_string().replace("\\", "/"); + if should_not_remove_test(&path_str) { + return Ok(()); + } else if should_remove_test(file, &path_str) { + return std::fs::remove_file(file) + .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error)); + } + let file_content = std::fs::read_to_string(file) + .map_err(|error| format!("Failed to read `{}`: {:?}", file.display(), error))?; + if should_remove_ui_test(&file_content) { + std::fs::remove_file(file) + .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error))?; + } + Ok(()) + } + + walk_dir("rust/tests/ui", dir_handling, file_handling)?; + let file = "rust/tests/ui/consts/const_cmp_type_id.rs"; + std::fs::remove_file(file) + .map_err(|error| format!("Failed to remove `{}`: {:?}", file, error))?; + let file = "rust/tests/ui/consts/issue-73976-monomorphic.rs"; + std::fs::remove_file(file) + .map_err(|error| format!("Failed to remove `{}`: {:?}", file, error))?; + + let mut env = env.clone(); + setup_rustc(&mut env, args)?; + if !callback()? { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("Keeping all UI tests"); + } + + let nb_parts = args.nb_parts.unwrap_or(0); + if nb_parts > 0 { + let current_part = args.current_part.unwrap_or(0); + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!( + "Splitting ui_test into {} parts (and running part {})", + nb_parts, current_part + ); + let out = String::from_utf8( + run_command( + &[ + &"find", + &"tests/ui", + &"-type", + &"f", + &"-name", + &"*.rs", + &"-not", + &"-path", + &"*/auxiliary/*", + ], + Some(Path::new("rust")), + )? + .stdout, + ) + .map_err(|error| format!("Failed to retrieve output of find command: {:?}", error))?; + let mut files = out + .split('\n') + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + .collect::>(); + // To ensure it'll be always the same sub files, we sort the content. + files.sort(); + // We increment the number of tests by one because if this is an odd number, we would skip + // one test. + let count = files.len() / nb_parts + 1; + let start = nb_parts * count; + let end = start + count; + for (pos, path) in files.iter().enumerate() { + if pos >= start && pos <= end { + continue; + } + std::fs::remove_file(path) + .map_err(|error| format!("Failed to remove `{}`: {:?}", path, error))?; + } + } + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] rustc test suite"); + env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); + let rustc_args = env + .get("RUSTFLAGS") + .expect("RUSTFLAGS should not be empty at this stage"); + run_command_with_output_and_env( + &[ + &"./x.py", + &"test", + &"--run", + &"always", + &"--stage", + &"0", + &"tests/ui", + &"--rustc-args", + &rustc_args, + ], + Some(Path::new("rust")), + Some(&env), + )?; + Ok(()) +} + +fn test_rustc(env: &Env, args: &TestArg) -> Result<(), String> { + test_rustc_inner(env, args, || Ok(false)) +} + +fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { + test_rustc_inner(env, args, || { + // Removing all tests. + run_command( + &[ + &"find", + &"tests/ui", + &"-type", + &"f", + &"-name", + &"*.rs", + &"-not", + &"-path", + &"*/auxiliary/*", + &"-delete", + ], + Some(Path::new("rust")), + )?; + // Putting back only the failing ones. + run_command( + &[ + &"xargs", + &"-a", + &"../failing-ui-tests.txt", + &"-d'\n'", + &"git", + &"checkout", + &"--", + ], + Some(Path::new("rust")), + )?; + Ok(true) + }) +} + +fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { + test_rustc_inner(env, args, || { + // Removing the failing tests. + run_command( + &[ + &"xargs", + &"-a", + &"../failing-ui-tests.txt", + &"-d'\n'", + &"rm", + ], + Some(Path::new("rust")), + )?; + Ok(true) + }) +} + +fn clean_ui_tests(_env: &Env, _args: &TestArg) -> Result<(), String> { + run_command( + &[ + &"find", + &"rust/build/x86_64-unknown-linux-gnu/test/ui/", + &"-name", + &"stamp", + &"-delete", + ], + None, + )?; + Ok(()) +} + +fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { + clean(env, args)?; + mini_tests(env, args)?; + build_sysroot(env, args)?; + std_tests(env, args)?; + // asm_tests(env, args)?; + test_libcore(env, args)?; + extended_sysroot_tests(env, args)?; + test_rustc(env, args)?; + Ok(()) } pub fn run() -> Result<(), String> { - let mut args: Vec<&dyn AsRef> = vec![&"bash", &"test.sh"]; - let extra_args = std::env::args().skip(2).collect::>(); - get_args(&mut args, &extra_args); - let current_dir = std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; - run_command_with_output(args.as_slice(), Some(¤t_dir)) + let mut args = match TestArg::new()? { + Some(args) => args, + None => return Ok(()), + }; + let mut env: HashMap = std::env::vars().collect(); + + env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); + env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); + + build_if_no_backend(&env, &args)?; + if args.build_only { + println!("Since it's build only, exiting..."); + return Ok(()); + } + + let test_flags = split_args(env.get("TEST_FLAGS").unwrap_or(&String::new())); + args.config_info + .setup(&mut env, &test_flags, Some(&args.gcc_path))?; + + if args.runners.is_empty() { + run_all(&env, &args)?; + } else { + let runners = get_runners(); + for runner in args.runners.iter() { + runners.get(runner.as_str()).unwrap().1(&env, &args)?; + } + } + + Ok(()) } diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 536f33a80293c..ba1e040cb20f9 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -143,17 +143,56 @@ pub fn get_os_name() -> Result { } } -pub fn get_rustc_host_triple() -> Result { - let output = run_command(&[&"rustc", &"-vV"], None)?; +#[derive(Default)] +pub struct RustcVersionInfo { + pub version: String, + pub host: Option, + pub commit_hash: Option, + pub commit_date: Option, +} + +pub fn rustc_version_info(rustc: Option<&str>) -> Result { + let output = run_command(&[&rustc.unwrap_or("rustc"), &"-vV"], None)?; let content = std::str::from_utf8(&output.stdout).unwrap_or(""); + let mut info = RustcVersionInfo::default(); + for line in content.split('\n').map(|line| line.trim()) { - if !line.starts_with("host:") { - continue; + match line.split_once(':') { + Some(("host", data)) => info.host = Some(data.trim().to_string()), + Some(("release", data)) => info.version = data.trim().to_string(), + Some(("commit-hash", data)) => info.commit_hash = Some(data.trim().to_string()), + Some(("commit-date", data)) => info.commit_date = Some(data.trim().to_string()), + _ => {} } - return Ok(line.split(':').nth(1).unwrap().trim().to_string()); } - Err("Cannot find host triple".to_string()) + if info.version.is_empty() { + Err("failed to retrieve rustc version".to_string()) + } else { + Ok(info) + } +} + +pub fn get_toolchain() -> Result { + let content = match fs::read_to_string("rust-toolchain") { + Ok(content) => content, + Err(_) => return Err("No `rust-toolchain` file found".to_string()), + }; + match content + .split('\n') + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + .filter_map(|line| { + if !line.starts_with("channel") { + return None; + } + line.split('"').skip(1).next() + }) + .next() + { + Some(toolchain) => Ok(toolchain.to_string()), + None => Err("Couldn't find `channel` in `rust-toolchain` file".to_string()), + } } pub fn get_gcc_path() -> Result { @@ -238,3 +277,56 @@ where } Ok(()) } + +pub fn split_args(args: &str) -> Vec { + let mut out = Vec::new(); + let mut start = 0; + let mut iter = args.char_indices().peekable(); + + while iter.peek().is_some() { + while let Some((pos, c)) = iter.next() { + if c == ' ' { + if pos != 0 { + out.push(args[start..pos].to_string()); + } + let mut found_start = false; + while let Some((pos, c)) = iter.peek() { + if *c != ' ' { + start = *pos; + found_start = true; + break; + } else { + iter.next(); + } + } + if !found_start { + return out; + } + } else if c == '"' || c == '\'' { + let end = c; + let mut found_end = false; + while let Some((_, c)) = iter.next() { + if c == end { + found_end = true; + break; + } else if c == '\\' { + // We skip the escaped character. + iter.next(); + } + } + if !found_end { + out.push(args[start..].to_string()); + return out; + } + } else if c == '\\' { + // We skip the escaped character. + iter.next(); + } + } + } + let s = args[start..].trim(); + if !s.is_empty() { + out.push(s.to_string()); + } + out +} From 84ca4f59c21425b02ba2042297187953d9aa283e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 Nov 2023 22:51:51 +0100 Subject: [PATCH 019/613] Remove `test.sh`, `config.sh` and all calls and documentation pointing to it --- .github/workflows/ci.yml | 2 +- .github/workflows/failures.yml | 2 +- .github/workflows/gcc12.yml | 2 +- .github/workflows/m68k.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/stdarch.yml | 2 +- Readme.md | 4 +- config.sh | 85 ------ test.sh | 479 --------------------------------- 9 files changed, 8 insertions(+), 572 deletions(-) delete mode 100644 config.sh delete mode 100755 test.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 308bc55ead71e..8e361bf617b1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,7 +124,7 @@ jobs: - name: Run tests run: | # TODO: remove --features master when it is back to the default. - ./test.sh --features master --release --clean --build-sysroot ${{ matrix.commands }} + ./y.sh test --features master --release --clean --build-sysroot ${{ matrix.commands }} duplicates: runs-on: ubuntu-latest diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index ae8de79b773db..b411b9a17846e 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -128,5 +128,5 @@ jobs: - name: Run tests id: tests run: | - ${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log + ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index a0d363cf1fbda..1a17b936c743e 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -112,4 +112,4 @@ jobs: - name: Run tests run: | - ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features + ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 4d9d7e23dc2b5..ac141e0624793 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -139,4 +139,4 @@ jobs: - name: Run tests run: | # TODO: remove --features master when it is back to the default. - ./test.sh --release --features master --clean --build-sysroot ${{ matrix.commands }} + ./y.sh test --release --features master --clean --build-sysroot ${{ matrix.commands }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 43b90fcec9337..9798bc338f3d5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -105,4 +105,4 @@ jobs: - name: Run tests run: | # TODO: remove --features master when it is back to the default. - EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master + EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 42109ba3e0245..d290f1d056288 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -120,7 +120,7 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | # TODO: remove `--features master` when it is back to the default. - ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master + ./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} diff --git a/Readme.md b/Readme.md index 9db1dec103232..68effb2bf78f9 100644 --- a/Readme.md +++ b/Readme.md @@ -65,7 +65,7 @@ $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --re To run the tests: ```bash -$ ./test.sh --release --features master +$ ./y.sh test --release --features master ``` ## Usage @@ -82,7 +82,7 @@ export CG_GCCJIT_DIR=[the full path to rustc_codegen_gcc] $ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run ``` -If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. +If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. ### LTO diff --git a/config.sh b/config.sh deleted file mode 100644 index 7ae2175d41de7..0000000000000 --- a/config.sh +++ /dev/null @@ -1,85 +0,0 @@ -set -e - -export CARGO_INCREMENTAL=0 - -if [ -f ./gcc_path ]; then - export GCC_PATH=$(cat gcc_path) -elif (( $use_system_gcc == 1 )); then - echo 'Using system GCC' -else - echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' - exit 1 -fi - -if [[ -z "$RUSTC" ]]; then - export RUSTC="rustc" -fi - -unamestr=`uname` -if [[ "$unamestr" == 'Linux' ]]; then - dylib_ext='so' -elif [[ "$unamestr" == 'Darwin' ]]; then - dylib_ext='dylib' -else - echo "Unsupported os" - exit 1 -fi - -HOST_TRIPLE=$($RUSTC -vV | grep host | cut -d: -f2 | tr -d " ") -# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed. -TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}" - -linker='' -RUN_WRAPPER='' -if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - RUN_WRAPPER=run_in_vm - if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then - linker='-Clinker=m68k-unknown-linux-gnu-gcc' - elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then - # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - linker='-Clinker=aarch64-linux-gnu-gcc' - else - echo "Unknown non-native platform" - fi -fi - -# Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. -# TODO(antoyo): remove when we can handle ThinLTO. -disable_lto_flags='' -if [[ ! -v FAT_LTO ]]; then - disable_lto_flags='-Clto=off' -fi - -if [[ -z "$BUILTIN_BACKEND" ]]; then - export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS" -else - export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=gcc $TEST_FLAGS -Cpanic=abort" - - if [[ ! -z "$RUSTC_SYSROOT" ]]; then - export RUSTFLAGS="$RUSTFLAGS --sysroot $RUSTC_SYSROOT" - fi -fi - -# FIXME(antoyo): remove once the atomic shim is gone -if [[ unamestr == 'Darwin' ]]; then - export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" -fi - -if [[ -z "$cargo_target_dir" ]]; then - RUST_CMD="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out" - cargo_target_dir="target/out" -else - RUST_CMD="$RUSTC $RUSTFLAGS -L crate=$cargo_target_dir --out-dir $cargo_target_dir" -fi -export RUSTC_LOG=warn # display metadata load errors - -export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib" -if [[ ! -z "$:$GCC_PATH" ]]; then - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GCC_PATH" -fi - -export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH -# NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc. -# To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH. -# Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc -export PATH="/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin:$PATH" diff --git a/test.sh b/test.sh deleted file mode 100755 index e896237a1ea4a..0000000000000 --- a/test.sh +++ /dev/null @@ -1,479 +0,0 @@ -#!/usr/bin/env bash - -# TODO(antoyo): rewrite to cargo-make (or just) or something like that to only rebuild the sysroot when needed? - -set -e -#set -x - -flags= -gcc_master_branch=1 -channel="debug" -funcs=() -build_only=0 -nb_parts=0 -current_part=0 -use_system_gcc=0 -use_backend=0 -cargo_target_dir="" - -export CHANNEL='debug' - -while [[ $# -gt 0 ]]; do - case $1 in - --release) - codegen_channel=release - channel="release" - export CHANNEL='release' - shift - ;; - --release-sysroot) - sysroot_channel="--release" - shift - ;; - --no-default-features) - gcc_master_branch=0 - flags="$flags --no-default-features" - shift - ;; - --features) - shift - flags="$flags --features $1" - shift - ;; - "--test-rustc") - funcs+=(test_rustc) - shift - ;; - "--test-successful-rustc") - funcs+=(test_successful_rustc) - shift - ;; - "--test-failing-rustc") - funcs+=(test_failing_rustc) - shift - ;; - - "--test-libcore") - funcs+=(test_libcore) - shift - ;; - - "--clean-ui-tests") - funcs+=(clean_ui_tests) - shift - ;; - "--clean") - funcs+=(clean) - shift - ;; - - "--std-tests") - funcs+=(std_tests) - shift - ;; - - "--asm-tests") - funcs+=(asm_tests) - shift - ;; - - "--extended-tests") - funcs+=(extended_sysroot_tests) - shift - ;; - "--extended-rand-tests") - funcs+=(extended_rand_tests) - shift - ;; - "--extended-regex-example-tests") - funcs+=(extended_regex_example_tests) - shift - ;; - "--extended-regex-tests") - funcs+=(extended_regex_tests) - shift - ;; - - "--mini-tests") - funcs+=(mini_tests) - shift - ;; - - "--build-sysroot") - funcs+=(build_sysroot) - shift - ;; - "--build") - build_only=1 - shift - ;; - "--use-system-gcc") - use_system_gcc=1 - shift - ;; - "--use-backend") - use_backend=1 - shift - export BUILTIN_BACKEND=$1 - shift - ;; - "--out-dir") - shift - export CARGO_TARGET_DIR=$1 - cargo_target_dir=$1 - shift - ;; - "--nb-parts") - shift - nb_parts=$1 - shift - ;; - "--current-part") - shift - current_part=$1 - shift - ;; - *) - echo "Unknown option $1" - exit 1 - ;; - esac -done - -if [ -f ./gcc_path ]; then - export GCC_PATH=$(cat gcc_path) -elif (( $use_system_gcc == 1 )); then - echo 'Using system GCC' -else - echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details' - exit 1 -fi - -export LD_LIBRARY_PATH="$GCC_PATH" -export LIBRARY_PATH="$GCC_PATH" - -if [[ $use_backend == 0 ]]; then - if [[ $channel == "release" ]]; then - CARGO_INCREMENTAL=1 cargo rustc --release $flags - else - echo $LD_LIBRARY_PATH - cargo rustc $flags - fi -fi - -if (( $build_only == 1 )); then - echo "Since it's 'build-only', exiting..." - exit -fi - -source config.sh - -function clean() { - rm -r $cargo_target_dir || true - mkdir -p $cargo_target_dir/gccjit -} - -function mini_tests() { - echo "[BUILD] mini_core" - crate_types="lib,dylib" - - if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - crate_types="lib" - fi - - $RUST_CMD example/mini_core.rs --crate-name mini_core --crate-type $crate_types --target $TARGET_TRIPLE - - echo "[BUILD] example" - $RUST_CMD example/example.rs --crate-type lib --target $TARGET_TRIPLE - - echo "[AOT] mini_core_hello_world" - $RUST_CMD example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE - $RUN_WRAPPER $cargo_target_dir/mini_core_hello_world abc bcd -} - -function build_sysroot() { - echo "[BUILD] sysroot" - time ./build_sysroot/build_sysroot.sh $sysroot_channel -} - -# TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible. -function run_in_vm() { - vm_parent_dir=${CG_GCC_VM_DIR:-$(pwd)} - vm_dir=vm - exe=$1 - exe_filename=$(basename $exe) - vm_home_dir=$vm_parent_dir/$vm_dir/home - vm_exe_path=$vm_home_dir/$exe_filename - inside_vm_exe_path=/home/$exe_filename - sudo cp $exe $vm_exe_path - - shift - pushd $vm_parent_dir - sudo chroot $vm_dir qemu-m68k-static $inside_vm_exe_path $@ - popd -} - -function std_tests() { - echo "[AOT] arbitrary_self_types_pointers_and_wrappers" - $RUST_CMD example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE - $RUN_WRAPPER $cargo_target_dir/arbitrary_self_types_pointers_and_wrappers - - echo "[AOT] alloc_system" - $RUST_CMD example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" - - # FIXME: doesn't work on m68k. - if [[ "$HOST_TRIPLE" == "$TARGET_TRIPLE" ]]; then - echo "[AOT] alloc_example" - $RUST_CMD example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE - $RUN_WRAPPER $cargo_target_dir/alloc_example - fi - - echo "[AOT] dst_field_align" - # FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed. - $RUST_CMD example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE - $RUN_WRAPPER $cargo_target_dir/dst_field_align || (echo $?; false) - - echo "[AOT] std_example" - std_flags="--cfg feature=\"master\"" - if (( $gcc_master_branch == 0 )); then - std_flags="" - fi - $RUST_CMD example/std_example.rs --crate-type bin --target $TARGET_TRIPLE $std_flags - $RUN_WRAPPER $cargo_target_dir/std_example --target $TARGET_TRIPLE - - echo "[AOT] subslice-patterns-const-eval" - $RUST_CMD example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE - $RUN_WRAPPER $cargo_target_dir/subslice-patterns-const-eval - - echo "[AOT] track-caller-attribute" - $RUST_CMD example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE - $RUN_WRAPPER $cargo_target_dir/track-caller-attribute - - echo "[BUILD] mod_bench" - $RUST_CMD example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE -} - -function setup_rustc() { - rust_toolchain=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/') - - git clone https://github.com/rust-lang/rust.git || true - cd rust - git fetch - git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(') - export RUSTFLAGS= - - rm config.toml || true - - cat > config.toml < res.txt - diff -u res.txt examples/regexdna-output.txt - popd -} - -function extended_regex_tests() { - if (( $gcc_master_branch == 0 )); then - return - fi - - pushd regex - echo "[TEST] rust-lang/regex tests" - export CG_RUSTFLAGS="--cap-lints warn" # newer aho_corasick versions throw a deprecation warning - ../cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q - popd -} - -function extended_sysroot_tests() { - #pushd simple-raytracer - #echo "[BENCH COMPILE] ebobby/simple-raytracer" - #hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \ - #"RUSTC=rustc RUSTFLAGS='' cargo build" \ - #"../cargo.sh build" - - #echo "[BENCH RUN] ebobby/simple-raytracer" - #cp ./target/debug/main ./raytracer_cg_gcc - #hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_gcc - #popd - - extended_rand_tests - extended_regex_example_tests - extended_regex_tests -} - -function test_rustc() { - echo - echo "[TEST] rust-lang/rust" - - setup_rustc - - for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do - rm $test - done - rm tests/ui/consts/const_cmp_type_id.rs - rm tests/ui/consts/issue-73976-monomorphic.rs - - git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed - - rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,borrowck/,test*,consts/issue-miri-1910.rs} || true - rm tests/ui/mir/mir_heavy_promoted.rs # this test is oom-killed in the CI. - # Tests generating errors. - rm tests/ui/consts/issue-94675.rs - for test in $(rg --files-with-matches "thread" tests/ui); do - rm $test - done - git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs - git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs - git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs - git checkout tests/ui/imports/ambiguous-1.rs - git checkout tests/ui/imports/ambiguous-4-extern.rs - git checkout tests/ui/entry-point/auxiliary/bad_main_functions.rs - - RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot" - - if [ $# -eq 0 ]; then - # No argument supplied to the function. Doing nothing. - echo "No argument provided. Keeping all UI tests" - elif [ $1 = "0" ]; then - # Removing the failing tests. - xargs -a ../failing-ui-tests.txt -d'\n' rm - else - # Removing all tests. - find tests/ui -type f -name '*.rs' -not -path '*/auxiliary/*' -delete - # Putting back only the failing ones. - xargs -a ../failing-ui-tests.txt -d'\n' git checkout -- - fi - - if [ $nb_parts -gt 0 ]; then - echo "Splitting ui_test into $nb_parts parts (and running part $current_part)" - find tests/ui -type f -name '*.rs' -not -path "*/auxiliary/*" > ui_tests - # To ensure it'll be always the same sub files, we sort the content. - sort ui_tests -o ui_tests - count=$((`wc -l < ui_tests` / $nb_parts)) - # We increment the number of tests by one because if this is an odd number, we would skip - # one test. - count=$((count + 1)) - split -d -l $count -a 1 ui_tests ui_tests.split - # Removing all tests. - find tests/ui -type f -name '*.rs' -not -path "*/auxiliary/*" -delete - # Putting back only the ones we want to test. - xargs -a "ui_tests.split$current_part" -d'\n' git checkout -- - fi - - echo "[TEST] rustc test suite" - COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS" # --target $TARGET_TRIPLE -} - -function test_failing_rustc() { - test_rustc "1" -} - -function test_successful_rustc() { - test_rustc "0" -} - -function clean_ui_tests() { - find rust/build/x86_64-unknown-linux-gnu/test/ui/ -name stamp -delete -} - -function all() { - clean - mini_tests - build_sysroot - std_tests - #asm_tests - test_libcore - extended_sysroot_tests - test_rustc -} - -if [ ${#funcs[@]} -eq 0 ]; then - echo "No command passed, running '--all'..." - all -else - for t in ${funcs[@]}; do - $t - done -fi From d3e14a49c9710a93ebd315b1b54a596496531de7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 Nov 2023 16:29:32 +0100 Subject: [PATCH 020/613] Display stdout and stderr if a command failed to run --- build_system/src/build.rs | 13 ++++++++--- build_system/src/main.rs | 2 +- build_system/src/utils.rs | 47 ++++++++++++++++++++++++++------------- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 6390458d4fd03..43fa442bf5b24 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -189,9 +189,16 @@ fn build_sysroot_inner( // Copy the source files to the sysroot (Rust for Linux needs this). let sysroot_src_path = "sysroot/lib/rustlib/src/rust"; - fs::create_dir_all(&sysroot_src_path) - .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_src_path, error))?; - run_command(&[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], None)?; + fs::create_dir_all(&sysroot_src_path).map_err(|error| { + format!( + "Failed to create directory `{}`: {:?}", + sysroot_src_path, error + ) + })?; + run_command( + &[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], + None, + )?; Ok(()) } diff --git a/build_system/src/main.rs b/build_system/src/main.rs index bff82b6e3e57d..e0091ff697733 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -61,7 +61,7 @@ fn main() { Command::Build => build::run(), Command::Test => test::run(), } { - eprintln!("Command failed to run: {e:?}"); + eprintln!("Command failed to run: {e}"); process::exit(1); } } diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index ba1e040cb20f9..6dfc6a6506aa4 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -29,22 +29,37 @@ fn check_exit_status( input: &[&dyn AsRef], cwd: Option<&Path>, exit_status: ExitStatus, + output: Option<&Output>, ) -> Result<(), String> { if exit_status.success() { - Ok(()) - } else { - Err(format!( - "Command `{}`{} exited with status {:?}", - input - .iter() - .map(|s| s.as_ref().to_str().unwrap()) - .collect::>() - .join(" "), - cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display())) - .unwrap_or_default(), - exit_status.code(), - )) + return Ok(()); + } + let mut error = format!( + "Command `{}`{} exited with status {:?}", + input + .iter() + .map(|s| s.as_ref().to_str().unwrap()) + .collect::>() + .join(" "), + cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display())) + .unwrap_or_default(), + exit_status.code() + ); + if let Some(output) = output { + unsafe { + let stdout = std::str::from_utf8_unchecked(&output.stdout); + if !stdout.is_empty() { + error.push_str("\n==== STDOUT ====\n"); + error.push_str(stdout); + } + let stderr = std::str::from_utf8_unchecked(&output.stderr); + if !stderr.is_empty() { + error.push_str("\n==== STDERR ====\n"); + error.push_str(stderr); + } + } } + Err(error) } fn command_error(input: &[&dyn AsRef], cwd: &Option<&Path>, error: D) -> String { @@ -73,7 +88,7 @@ pub fn run_command_with_env( let output = get_command_inner(input, cwd, env) .output() .map_err(|e| command_error(input, &cwd, e))?; - check_exit_status(input, cwd, output.status)?; + check_exit_status(input, cwd, output.status, Some(&output))?; Ok(output) } @@ -86,7 +101,7 @@ pub fn run_command_with_output( .map_err(|e| command_error(input, &cwd, e))? .wait() .map_err(|e| command_error(input, &cwd, e))?; - check_exit_status(input, cwd, exit_status)?; + check_exit_status(input, cwd, exit_status, None)?; Ok(()) } @@ -100,7 +115,7 @@ pub fn run_command_with_output_and_env( .map_err(|e| command_error(input, &cwd, e))? .wait() .map_err(|e| command_error(input, &cwd, e))?; - check_exit_status(input, cwd, exit_status)?; + check_exit_status(input, cwd, exit_status, None)?; Ok(()) } From 8cc024c84dc76cb081bbaf8ae2eef4647ed8d78b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 Nov 2023 18:38:30 +0100 Subject: [PATCH 021/613] Fix invalid path in `build_sysroot_inner` --- build_system/src/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 43fa442bf5b24..8f5c113fe319a 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -196,7 +196,7 @@ fn build_sysroot_inner( ) })?; run_command( - &[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], + &[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], None, )?; From 694a80d3724cdf7138df550d64fcaceb5d1404b0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 Nov 2023 21:38:16 +0100 Subject: [PATCH 022/613] Add missing `--build-sysroot` option --- build_system/src/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index fb2b24da9a233..2619fbc2f646a 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -33,6 +33,7 @@ fn get_runners() -> Runners { runners.insert("--test-libcore", ("Run libcore tests", &test_libcore)); runners.insert("--clean-ui-tests", ("Clean ui tests", &clean_ui_tests)); runners.insert("--clean", ("Empty cargo target directory", &clean)); + runners.insert("--build-sysroot", ("Build sysroot", &build_sysroot)); runners.insert("--std-tests", ("Run std tests", &std_tests)); runners.insert("--asm-tests", ("Run asm tests", &asm_tests)); runners.insert( From c27fe3e0366313933daf6f9a6b3df578bde2682b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Nov 2023 15:17:48 +0100 Subject: [PATCH 023/613] Correctly handle channel in config --- build_system/src/config.rs | 4 +++- build_system/src/test.rs | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 763cac8edb66b..8bab64f121ac0 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -110,7 +110,9 @@ impl ConfigInfo { let current_dir = std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; - let channel = if let Some(channel) = env.get("CHANNEL") { + let channel = if self.sysroot_release_channel { + "release" + } else if let Some(channel) = env.get("CHANNEL") { channel.as_str() } else { "debug" diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 2619fbc2f646a..06a5c3157bb2f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -126,7 +126,6 @@ struct TestArg { build_only: bool, gcc_path: String, channel: Channel, - sysroot_channel: Channel, use_backend: bool, runners: BTreeSet, flags: Vec, @@ -148,8 +147,11 @@ impl TestArg { while let Some(arg) = args.next() { match arg.as_str() { - "--release" => test_arg.channel = Channel::Release, - "--release-sysroot" => test_arg.sysroot_channel = Channel::Release, + "--release" => { + test_arg.channel = Channel::Release; + test_arg.config_info.sysroot_release_channel = true; + } + "--release-sysroot" => test_arg.config_info.sysroot_release_channel = true, "--no-default-features" => { // To prevent adding it more than once. if !test_arg.no_default_features { From 9d104a0cbf0abbf5d2f5176298373510392e5a36 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Nov 2023 17:01:05 +0100 Subject: [PATCH 024/613] Clone rust repository before modifying it --- build_system/src/test.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 06a5c3157bb2f..7785957541f5b 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -895,6 +895,9 @@ where { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rust-lang/rust"); + let mut env = env.clone(); + setup_rustc(&mut env, args)?; + walk_dir( "rust/tests/ui", |dir| { @@ -948,8 +951,6 @@ where std::fs::remove_file(file) .map_err(|error| format!("Failed to remove `{}`: {:?}", file, error))?; - let mut env = env.clone(); - setup_rustc(&mut env, args)?; if !callback()? { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("Keeping all UI tests"); From 87c284c9bc05e290cb0ee577717a94de9e853c89 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Nov 2023 17:20:14 +0100 Subject: [PATCH 025/613] Only read rust test files --- build_system/src/test.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 7785957541f5b..bbe2322f93d3e 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -928,7 +928,9 @@ where } fn file_handling(file: &Path) -> Result<(), String> { let path_str = file.display().to_string().replace("\\", "/"); - if should_not_remove_test(&path_str) { + if !path_str.ends_with(".rs") { + return Ok(()) + } else if should_not_remove_test(&path_str) { return Ok(()); } else if should_remove_test(file, &path_str) { return std::fs::remove_file(file) From 23c97b545dd7d8dbee80e491269f95308707c750 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Nov 2023 17:35:49 +0100 Subject: [PATCH 026/613] Replace `xargs` command with pure Rust --- build_system/src/build.rs | 7 ++++- build_system/src/test.rs | 59 ++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 8f5c113fe319a..3087a5d79e01b 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -196,7 +196,12 @@ fn build_sysroot_inner( ) })?; run_command( - &[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], + &[ + &"cp", + &"-r", + &start_dir.join("sysroot_src/library/"), + &sysroot_src_path, + ], None, )?; diff --git a/build_system/src/test.rs b/build_system/src/test.rs index bbe2322f93d3e..12927c5d13cab 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -929,7 +929,7 @@ where fn file_handling(file: &Path) -> Result<(), String> { let path_str = file.display().to_string().replace("\\", "/"); if !path_str.ends_with(".rs") { - return Ok(()) + return Ok(()); } else if should_not_remove_test(&path_str) { return Ok(()); } else if should_remove_test(file, &path_str) { @@ -1052,18 +1052,24 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { Some(Path::new("rust")), )?; // Putting back only the failing ones. - run_command( - &[ - &"xargs", - &"-a", - &"../failing-ui-tests.txt", - &"-d'\n'", - &"git", - &"checkout", - &"--", - ], - Some(Path::new("rust")), - )?; + let path = "failing-ui-tests.txt"; + if let Ok(files) = std::fs::read_to_string(path) { + for file in files + .split('\n') + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + { + run_command( + &[&"git", &"checkout", &"--", &file], + Some(Path::new("rust")), + )?; + } + } else { + println!( + "Failed to read `{}`, not putting back failing ui tests", + path + ); + } Ok(true) }) } @@ -1071,16 +1077,23 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { test_rustc_inner(env, args, || { // Removing the failing tests. - run_command( - &[ - &"xargs", - &"-a", - &"../failing-ui-tests.txt", - &"-d'\n'", - &"rm", - ], - Some(Path::new("rust")), - )?; + let path = "failing-ui-tests.txt"; + if let Ok(files) = std::fs::read_to_string(path) { + for file in files + .split('\n') + .map(|line| line.trim()) + .filter(|line| !line.is_empty()) + { + let path = Path::new("rust").join(file); + std::fs::remove_file(&path) + .map_err(|error| format!("failed to remove `{}`: {:?}", path.display(), error))?; + } + } else { + println!( + "Failed to read `{}`, not putting back failing ui tests", + path + ); + } Ok(true) }) } From 673661db8b35fbbdc71b91af9b122a7eaf7f7bf3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Nov 2023 17:54:58 +0100 Subject: [PATCH 027/613] Remove newline for llvm FileCheck binary path --- build_system/src/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 12927c5d13cab..e175b62625cb8 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -597,7 +597,7 @@ download-ci-llvm = false home = env.get("HOME").unwrap(), toolchain = toolchain, host_triple = args.config_info.host_triple, - llvm_filecheck = llvm_filecheck, + llvm_filecheck = llvm_filecheck.trim(), ), ) .map_err(|error| format!("Failed to write into `rust/config.toml`: {:?}", error))?; From d793f80bd4ceb85c032e18c1d0badac9a8664bba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Nov 2023 16:09:11 +0100 Subject: [PATCH 028/613] Correctly pass `cfg` option --- build_system/src/test.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index e175b62625cb8..614042b36c20d 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -390,7 +390,7 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); if !args.no_default_features { - command.push(&"--cfg feature=\"master\""); + command.extend_from_slice(&[&"--cfg", &"feature=\"master\""]); } run_command_with_env(&command, None, Some(env))?; @@ -454,7 +454,7 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); if !args.no_default_features { - command.push(&"--cfg feature=\"master\""); + command.extend_from_slice(&[&"--cfg", &"feature=\"master\""]); } run_command_with_env(&command, None, Some(env))?; run_command_in_vm( @@ -1085,8 +1085,9 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { .filter(|line| !line.is_empty()) { let path = Path::new("rust").join(file); - std::fs::remove_file(&path) - .map_err(|error| format!("failed to remove `{}`: {:?}", path.display(), error))?; + std::fs::remove_file(&path).map_err(|error| { + format!("failed to remove `{}`: {:?}", path.display(), error) + })?; } } else { println!( From 4bed89f79bfd40fdfe615334c38e2427319db34f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Nov 2023 16:25:52 +0100 Subject: [PATCH 029/613] Correctly pass toolchain to cargo command --- build_system/src/test.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 614042b36c20d..114aa6dc72071 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -672,17 +672,14 @@ where F: Fn(&[&dyn AsRef], Option<&Path>, &Env) -> Result<(), String>, { let toolchain = get_toolchain()?; + let toolchain_arg = format!("+{}", toolchain); let rustc_version = String::from_utf8( run_command_with_env(&[&args.config_info.rustc_command[0], &"-V"], cwd, Some(env))?.stdout, ) .map_err(|error| format!("Failed to retrieve rustc version: {:?}", error))?; let rustc_toolchain_version = String::from_utf8( run_command_with_env( - &[ - &args.config_info.rustc_command[0], - &format!("+{}", toolchain), - &"-V", - ], + &[&args.config_info.rustc_command[0], &toolchain_arg, &"-V"], cwd, Some(env), )? @@ -697,7 +694,7 @@ where ); eprintln!("Using `{}`.", rustc_toolchain_version); } - let mut cargo_command: Vec<&dyn AsRef> = vec![&"cargo", &toolchain]; + let mut cargo_command: Vec<&dyn AsRef> = vec![&"cargo", &toolchain_arg]; cargo_command.extend_from_slice(&command); callback(&cargo_command, cwd, env) } From 3c6bae7fa88d700a34b57f43e55749c510c57b72 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Nov 2023 16:41:16 +0100 Subject: [PATCH 030/613] Use the correct folder when deleting rust UI tests --- build_system/src/test.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 114aa6dc72071..16f01a1ba2def 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -942,13 +942,15 @@ where Ok(()) } - walk_dir("rust/tests/ui", dir_handling, file_handling)?; - let file = "rust/tests/ui/consts/const_cmp_type_id.rs"; - std::fs::remove_file(file) - .map_err(|error| format!("Failed to remove `{}`: {:?}", file, error))?; - let file = "rust/tests/ui/consts/issue-73976-monomorphic.rs"; - std::fs::remove_file(file) - .map_err(|error| format!("Failed to remove `{}`: {:?}", file, error))?; + let rust_path = Path::new("rust"); + + walk_dir(rust_path.join("tests/ui"), dir_handling, file_handling)?; + let file = rust_path.join("tests/ui/consts/const_cmp_type_id.rs"); + std::fs::remove_file(&file) + .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error))?; + let file = rust_path.join("tests/ui/consts/issue-73976-monomorphic.rs"); + std::fs::remove_file(&file) + .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error))?; if !callback()? { // FIXME: create a function "display_if_not_quiet" or something along the line. @@ -976,7 +978,7 @@ where &"-path", &"*/auxiliary/*", ], - Some(Path::new("rust")), + Some(rust_path), )? .stdout, ) @@ -997,8 +999,10 @@ where if pos >= start && pos <= end { continue; } - std::fs::remove_file(path) - .map_err(|error| format!("Failed to remove `{}`: {:?}", path, error))?; + let test_path = rust_path.join(path); + std::fs::remove_file(&test_path).map_err(|error| { + format!("Failed to remove `{}`: {:?}", test_path.display(), error) + })?; } } @@ -1020,7 +1024,7 @@ where &"--rustc-args", &rustc_args, ], - Some(Path::new("rust")), + Some(rust_path), Some(&env), )?; Ok(()) From 7013eccc052228044faa0103ca596ed75ea2a70e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Nov 2023 17:05:33 +0100 Subject: [PATCH 031/613] Add missing code comment --- build_system/src/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 16f01a1ba2def..7ab4767e405d1 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -794,6 +794,7 @@ fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rust-lang/regex tests"); let mut env = env.clone(); + // newer aho_corasick versions throw a deprecation warning env.insert("CG_RUSTFLAGS".to_string(), "--cap-lints warn".to_string()); run_cargo_command( &[ From ad1d5417e705c8d915b718b8fc29e58c49b8defa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Nov 2023 17:11:07 +0100 Subject: [PATCH 032/613] Set RUSTDOCFLAGS environment variable in `run_cargo_command_with_callback` function --- build_system/src/test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 7ab4767e405d1..02e6309bd338d 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -694,9 +694,12 @@ where ); eprintln!("Using `{}`.", rustc_toolchain_version); } + let mut env = env.clone(); + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert("RUSTDOCFLAGS".to_string(), rustflags); let mut cargo_command: Vec<&dyn AsRef> = vec![&"cargo", &toolchain_arg]; cargo_command.extend_from_slice(&command); - callback(&cargo_command, cwd, env) + callback(&cargo_command, cwd, &env) } // FIXME(antoyo): linker gives multiple definitions error on Linux From 7d71b87691c22d54a1119a491647db63d28b55d3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Nov 2023 18:10:01 +0100 Subject: [PATCH 033/613] Correctly set `--cap-lints` when running regex tests --- build_system/src/config.rs | 2 ++ build_system/src/test.rs | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 8bab64f121ac0..b31a728c68075 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -149,9 +149,11 @@ impl ConfigInfo { .extend_from_slice(&["--sysroot".to_string(), sysroot_path.display().to_string()]); }; + // This environment variable is useful in case we want to change options of rustc commands. if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { rustflags.extend_from_slice(&split_args(&cg_rustflags)); } + if let Some(linker) = linker { rustflags.push(linker.to_string()); } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 02e6309bd338d..4e8c176db7379 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -750,7 +750,8 @@ fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> println!("[TEST] rust-lang/regex example shootout-regex-dna"); let mut env = env.clone(); // newer aho_corasick versions throw a deprecation warning - env.insert("CG_RUSTFLAGS".to_string(), "--cap-lints warn".to_string()); + let rustflags = format!("{} --cap-lints warn", env.get("RUSTFLAGS").cloned().unwrap_or_default()); + env.insert("RUSTFLAGS".to_string(), rustflags); // Make sure `[codegen mono items] start` doesn't poison the diff run_cargo_command( &[&"build", &"--example", &"shootout-regex-dna"], @@ -798,7 +799,8 @@ fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { println!("[TEST] rust-lang/regex tests"); let mut env = env.clone(); // newer aho_corasick versions throw a deprecation warning - env.insert("CG_RUSTFLAGS".to_string(), "--cap-lints warn".to_string()); + let rustflags = format!("{} --cap-lints warn", env.get("RUSTFLAGS").cloned().unwrap_or_default()); + env.insert("RUSTFLAGS".to_string(), rustflags); run_cargo_command( &[ &"test", From 970b2c770010c044abe5e3a8433fffc4ab3b8d52 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Nov 2023 21:34:29 +0100 Subject: [PATCH 034/613] Fix `build_sysroot` by adding missing `RUSTFLAGS` environment variable --- build_system/src/build.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 3087a5d79e01b..da29e87c33cbe 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -141,8 +141,8 @@ fn build_sysroot_inner( rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } rustflags.push_str(" -Z force-unstable-if-unmarked"); + let mut env = env.clone(); let channel = if sysroot_release_channel { - let mut env = env.clone(); env.insert( "RUSTFLAGS".to_string(), format!("{} -Zmir-opt-level=3", rustflags), @@ -160,10 +160,15 @@ fn build_sysroot_inner( )?; "release" } else { + env.insert( + "RUSTFLAGS".to_string(), + rustflags, + ); + run_command_with_output_and_env( &[&"cargo", &"build", &"--target", &config.target], Some(start_dir), - Some(env), + Some(&env), )?; "debug" }; From ff043162432a33fb7d2c675f05aef2803b39d387 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Nov 2023 22:05:08 +0100 Subject: [PATCH 035/613] Remove `--target` option --- build_system/src/build.rs | 25 +++---------------------- build_system/src/config.rs | 12 ------------ build_system/src/test.rs | 10 ++++++++-- 3 files changed, 11 insertions(+), 36 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index da29e87c33cbe..189c393019fd4 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -43,22 +43,6 @@ impl BuildArg { Self::usage(); return Ok(None); } - "--target-triple" => { - if args.next().is_some() { - // Handled in config.rs. - } else { - return Err( - "Expected a value after `--target-triple`, found nothing".to_string() - ); - } - } - "--target" => { - if args.next().is_some() { - // Handled in config.rs. - } else { - return Err("Expected a value after `--target`, found nothing".to_string()); - } - } arg => { if !build_arg.config_info.parse_argument(arg, &mut args)? { return Err(format!("Unknown argument `{}`", arg)); @@ -152,7 +136,7 @@ fn build_sysroot_inner( &"cargo", &"build", &"--target", - &config.target, + &config.target_triple, &"--release", ], Some(start_dir), @@ -160,13 +144,10 @@ fn build_sysroot_inner( )?; "release" } else { - env.insert( - "RUSTFLAGS".to_string(), - rustflags, - ); + env.insert("RUSTFLAGS".to_string(), rustflags); run_command_with_output_and_env( - &[&"cargo", &"build", &"--target", &config.target], + &[&"cargo", &"build", &"--target", &config.target_triple], Some(start_dir), Some(&env), )?; diff --git a/build_system/src/config.rs b/build_system/src/config.rs index b31a728c68075..267f454644236 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -4,7 +4,6 @@ use std::env as std_env; #[derive(Default)] pub struct ConfigInfo { - pub target: String, pub target_triple: String, pub host_triple: String, pub rustc_command: Vec, @@ -31,10 +30,6 @@ impl ConfigInfo { ) } }, - "--target" => match args.next() { - Some(arg) if !arg.is_empty() => self.target = arg.to_string(), - _ => return Err("Expected a value after `--target`, found nothing".to_string()), - }, "--out-dir" => match args.next() { Some(arg) if !arg.is_empty() => { // env.insert("CARGO_TARGET_DIR".to_string(), arg.to_string()); @@ -83,12 +78,6 @@ impl ConfigInfo { }; self.host_triple = rustc_version_info(Some(&rustc))?.host.unwrap_or_default(); - if !self.target_triple.is_empty() && self.target.is_empty() { - self.target = self.target_triple.clone(); - } - if self.target.is_empty() { - self.target = self.host_triple.clone(); - } if self.target_triple.is_empty() { self.target_triple = self.host_triple.clone(); } @@ -223,7 +212,6 @@ impl ConfigInfo { pub fn show_usage() { println!( "\ - --target [arg] : Set the target to [arg] --target-triple [arg] : Set the target triple to [arg] --out-dir : Location where the files will be generated --release-sysroot : Build sysroot in release mode diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 4e8c176db7379..1e012798cba1e 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -750,7 +750,10 @@ fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> println!("[TEST] rust-lang/regex example shootout-regex-dna"); let mut env = env.clone(); // newer aho_corasick versions throw a deprecation warning - let rustflags = format!("{} --cap-lints warn", env.get("RUSTFLAGS").cloned().unwrap_or_default()); + let rustflags = format!( + "{} --cap-lints warn", + env.get("RUSTFLAGS").cloned().unwrap_or_default() + ); env.insert("RUSTFLAGS".to_string(), rustflags); // Make sure `[codegen mono items] start` doesn't poison the diff run_cargo_command( @@ -799,7 +802,10 @@ fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { println!("[TEST] rust-lang/regex tests"); let mut env = env.clone(); // newer aho_corasick versions throw a deprecation warning - let rustflags = format!("{} --cap-lints warn", env.get("RUSTFLAGS").cloned().unwrap_or_default()); + let rustflags = format!( + "{} --cap-lints warn", + env.get("RUSTFLAGS").cloned().unwrap_or_default() + ); env.insert("RUSTFLAGS".to_string(), rustflags); run_cargo_command( &[ From 53b2759bef791bad51bfcef022f2da432e6a4269 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Nov 2023 22:23:08 +0100 Subject: [PATCH 036/613] Show command which failed --- build_system/src/utils.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 6dfc6a6506aa4..88fce2fcbce18 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -45,6 +45,8 @@ fn check_exit_status( .unwrap_or_default(), exit_status.code() ); + let input = input.iter().map(|i| i.as_ref()).collect::>(); + eprintln!("Command `{:?}` failed", input); if let Some(output) = output { unsafe { let stdout = std::str::from_utf8_unchecked(&output.stdout); From 2ec8d46dd1b6adc116a5efba46b7aad4a5315f86 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Nov 2023 23:54:18 +0100 Subject: [PATCH 037/613] Correctly handle `OVERWRITE_TARGET_TRIPLE` env variable --- build_system/src/config.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 267f454644236..d602cec9f9f58 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -78,6 +78,11 @@ impl ConfigInfo { }; self.host_triple = rustc_version_info(Some(&rustc))?.host.unwrap_or_default(); + if self.target_triple.is_empty() { + if let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE") { + self.target_triple = overwrite.clone(); + } + } if self.target_triple.is_empty() { self.target_triple = self.host_triple.clone(); } From 996635bad689a90ba90a8dbf887611f6fa287bab Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Nov 2023 00:04:08 +0100 Subject: [PATCH 038/613] Fix chroot command --- build_system/src/test.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1e012798cba1e..db3e4d9894d8c 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -345,8 +345,13 @@ fn run_command_in_vm( let sudo_command: &[&dyn AsRef] = &[&"sudo", &"cp", &exe, &vm_exe_path]; run_command_with_env(sudo_command, None, Some(env))?; - let mut vm_command: Vec<&dyn AsRef> = - vec![&"sudo", &"chroot", &"qemu-m68k-static", &inside_vm_exe_path]; + let mut vm_command: Vec<&dyn AsRef> = vec![ + &"sudo", + &"chroot", + &vm_dir, + &"qemu-m68k-static", + &inside_vm_exe_path, + ]; vm_command.extend_from_slice(command); run_command_with_env(&vm_command, Some(&vm_parent_dir), Some(env))?; Ok(()) From ebb7aa0b8575a27e2768c42f1472d3523925357c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 Dec 2023 23:57:16 +0100 Subject: [PATCH 039/613] Apply suggestions --- build_system/src/build.rs | 40 +------ build_system/src/config.rs | 25 ++-- build_system/src/prepare.rs | 7 +- build_system/src/test.rs | 227 ++++++++++++++++-------------------- build_system/src/utils.rs | 47 +++++--- 5 files changed, 156 insertions(+), 190 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 189c393019fd4..618e74be2c0c9 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -67,14 +67,8 @@ impl BuildArg { } } -fn build_sysroot_inner( - env: &HashMap, - sysroot_panic_abort: bool, - sysroot_release_channel: bool, - config: &ConfigInfo, - start_dir: Option<&Path>, -) -> Result<(), String> { - let start_dir = start_dir.unwrap_or_else(|| Path::new(".")); +pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Result<(), String> { + let start_dir = Path::new("build_sysroot"); // Cleanup for previous run // Clean target dir except for build scripts and incremental cache let _ = walk_dir( @@ -121,12 +115,11 @@ fn build_sysroot_inner( // Builds libs let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); - if sysroot_panic_abort { + if config.sysroot_panic_abort { rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } - rustflags.push_str(" -Z force-unstable-if-unmarked"); let mut env = env.clone(); - let channel = if sysroot_release_channel { + let channel = if config.sysroot_release_channel { env.insert( "RUSTFLAGS".to_string(), format!("{} -Zmir-opt-level=3", rustflags), @@ -194,21 +187,6 @@ fn build_sysroot_inner( Ok(()) } -pub fn build_sysroot( - env: &HashMap, - sysroot_panic_abort: bool, - sysroot_release_channel: bool, - config: &ConfigInfo, -) -> Result<(), String> { - build_sysroot_inner( - env, - sysroot_panic_abort, - sysroot_release_channel, - config, - Some(Path::new("build_sysroot")), - ) -} - fn build_codegen(args: &mut BuildArg) -> Result<(), String> { let mut env = HashMap::new(); @@ -229,8 +207,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info - .setup(&mut env, &[], Some(&args.gcc_path))?; + args.config_info.setup(&mut env, Some(&args.gcc_path))?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); @@ -243,12 +220,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { })?; println!("[BUILD] sysroot"); - build_sysroot( - &env, - args.config_info.sysroot_panic_abort, - args.config_info.sysroot_release_channel, - &args.config_info, - )?; + build_sysroot(&env, &args.config_info)?; Ok(()) } diff --git a/build_system/src/config.rs b/build_system/src/config.rs index d602cec9f9f58..8396681b292a4 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -1,8 +1,9 @@ use crate::utils::{get_gcc_path, get_os_name, rustc_version_info, split_args}; use std::collections::HashMap; use std::env as std_env; +use std::ffi::OsStr; -#[derive(Default)] +#[derive(Default, Debug)] pub struct ConfigInfo { pub target_triple: String, pub host_triple: String, @@ -32,7 +33,6 @@ impl ConfigInfo { }, "--out-dir" => match args.next() { Some(arg) if !arg.is_empty() => { - // env.insert("CARGO_TARGET_DIR".to_string(), arg.to_string()); self.cargo_target_dir = arg.to_string(); } _ => return Err("Expected a value after `--out-dir`, found nothing".to_string()), @@ -44,10 +44,17 @@ impl ConfigInfo { Ok(true) } + pub fn rustc_command_vec(&self) -> Vec<&dyn AsRef> { + let mut command: Vec<&dyn AsRef> = Vec::with_capacity(self.rustc_command.len()); + for arg in self.rustc_command.iter() { + command.push(arg); + } + command + } + pub fn setup( &mut self, env: &mut HashMap, - test_flags: &[String], gcc_path: Option<&str>, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -90,15 +97,10 @@ impl ConfigInfo { let mut linker = None; if self.host_triple != self.target_triple { - if self.target_triple == "m68k-unknown-linux-gnu" { - linker = Some("-Clinker=m68k-unknown-linux-gnu-gcc".to_string()); - } else if self.target_triple == "aarch64-unknown-linux-gnu" { - // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - linker = Some("-Clinker=aarch64-linux-gnu-gcc".to_string()); - } else { + if self.target_triple.is_empty() { return Err("Unknown non-native platform".to_string()); } - + linker = Some(format!("-Clinker={}-gcc", self.target_triple)); self.run_in_vm = true; } @@ -145,7 +147,7 @@ impl ConfigInfo { // This environment variable is useful in case we want to change options of rustc commands. if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { - rustflags.extend_from_slice(&split_args(&cg_rustflags)); + rustflags.extend_from_slice(&split_args(&cg_rustflags)?); } if let Some(linker) = linker { @@ -162,7 +164,6 @@ impl ConfigInfo { if !env.contains_key(&"FAT_LTO".to_string()) { rustflags.push("-Clto=off".to_string()); } - rustflags.extend_from_slice(test_flags); // FIXME(antoyo): remove once the atomic shim is gone if os_name == "Darwin" { rustflags.extend_from_slice(&[ diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index da9f8953ec3cb..ce9b440be053a 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -1,5 +1,7 @@ use crate::rustc_info::get_rustc_path; -use crate::utils::{cargo_install, git_clone, run_command, run_command_with_output, walk_dir}; +use crate::utils::{ + cargo_install, git_clone, remove_file, run_command, run_command_with_output, walk_dir, +}; use std::fs; use std::path::Path; @@ -137,8 +139,7 @@ fn build_raytracer(repo_dir: &Path) -> Result<(), String> { run_command(&[&"cargo", &"build"], Some(repo_dir))?; let mv_target = repo_dir.join("raytracer_cg_llvm"); if mv_target.is_file() { - std::fs::remove_file(&mv_target) - .map_err(|e| format!("Failed to remove file `{}`: {e:?}", mv_target.display()))?; + remove_file(&mv_target)?; } run_command( &[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], diff --git a/build_system/src/test.rs b/build_system/src/test.rs index db3e4d9894d8c..af2367e668ebb 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -3,11 +3,13 @@ use crate::config::ConfigInfo; use crate::utils::{ get_gcc_path, get_toolchain, run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, + remove_file, }; use std::collections::{BTreeSet, HashMap}; use std::ffi::OsStr; -use std::fs::remove_dir_all; +use std::fs::{File, remove_dir_all}; +use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -85,7 +87,6 @@ fn show_usage() { `test` command help: --release : Build codegen in release mode - --release-sysroot : Build sysroot in release mode --sysroot-panic-abort : Build the sysroot without unwinding support. --no-default-features : Add `--no-default-features` flag --features [arg] : Add a new feature [arg] @@ -104,7 +105,7 @@ fn show_usage() { println!(" --help : Show this help"); } -#[derive(Default, PartialEq, Eq, Clone, Copy)] +#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] enum Channel { #[default] Debug, @@ -120,7 +121,7 @@ impl Channel { } } -#[derive(Default)] +#[derive(Default, Debug)] struct TestArg { no_default_features: bool, build_only: bool, @@ -151,7 +152,6 @@ impl TestArg { test_arg.channel = Channel::Release; test_arg.config_info.sysroot_release_channel = true; } - "--release-sysroot" => test_arg.config_info.sysroot_release_channel = true, "--no-default-features" => { // To prevent adding it more than once. if !test_arg.no_default_features { @@ -210,8 +210,19 @@ impl TestArg { get_gcc_path()? }; } + match (test_arg.current_part, test_arg.nb_parts) { + (Some(_), Some(_)) | (None, None) => {} + _ => { + return Err("If either `--current-part` or `--nb-parts` is specified, the other one \ + needs to be specified as well!".to_string()); + } + } Ok(Some(test_arg)) } + + pub fn is_using_gcc_master_branch(&self) -> bool { + !self.no_default_features + } } fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> { @@ -251,10 +262,7 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { "lib,dylib" } .to_string(); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/mini_core.rs", &"--crate-name", @@ -268,10 +276,7 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[BUILD] example"); - command.clear(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/example.rs", &"--crate-type", @@ -283,10 +288,7 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] mini_core_hello_world"); - command.clear(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/mini_core_hello_world.rs", &"--crate-name", @@ -304,24 +306,19 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"abc", &"bcd", ]; - run_command_in_vm(&command, env, args)?; + maybe_run_command_in_vm(&command, env, args)?; Ok(()) } fn build_sysroot(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[BUILD] sysroot"); - build::build_sysroot( - env, - args.config_info.sysroot_panic_abort, - args.config_info.sysroot_release_channel, - &args.config_info, - )?; + build::build_sysroot(env, &args.config_info)?; Ok(()) } // TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible. -fn run_command_in_vm( +fn maybe_run_command_in_vm( command: &[&dyn AsRef], env: &Env, args: &TestArg, @@ -358,12 +355,10 @@ fn run_command_in_vm( } fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { + let cargo_target_dir = Path::new(&args.config_info.cargo_target_dir); // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] arbitrary_self_types_pointers_and_wrappers"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/arbitrary_self_types_pointers_and_wrappers.rs", &"--crate-name", @@ -374,19 +369,15 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); run_command_with_env(&command, None, Some(env))?; - run_command_in_vm( - &[&Path::new(&args.config_info.cargo_target_dir) - .join("arbitrary_self_types_pointers_and_wrappers")], + maybe_run_command_in_vm( + &[&cargo_target_dir.join("arbitrary_self_types_pointers_and_wrappers")], env, args, )?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] alloc_system"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/alloc_system.rs", &"--crate-type", @@ -394,19 +385,16 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"--target", &args.config_info.target_triple, ]); - if !args.no_default_features { + if args.is_using_gcc_master_branch() { command.extend_from_slice(&[&"--cfg", &"feature=\"master\""]); } run_command_with_env(&command, None, Some(env))?; // FIXME: doesn't work on m68k. - if args.config_info.host_triple != args.config_info.target_triple { + if args.config_info.host_triple == args.config_info.target_triple { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] alloc_example"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/alloc_example.rs", &"--crate-type", @@ -415,8 +403,8 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); run_command_with_env(&command, None, Some(env))?; - run_command_in_vm( - &[&Path::new(&args.config_info.cargo_target_dir).join("alloc_example")], + maybe_run_command_in_vm( + &[&cargo_target_dir.join("alloc_example")], env, args, )?; @@ -425,10 +413,7 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] dst_field_align"); // FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed. - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/dst-field-align.rs", &"--crate-name", @@ -439,18 +424,15 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); run_command_with_env(&command, None, Some(env))?; - run_command_in_vm( - &[&Path::new(&args.config_info.cargo_target_dir).join("dst_field_align")], + maybe_run_command_in_vm( + &[&cargo_target_dir.join("dst_field_align")], env, args, )?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] std_example"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/std_example.rs", &"--crate-type", @@ -458,13 +440,13 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"--target", &args.config_info.target_triple, ]); - if !args.no_default_features { + if args.is_using_gcc_master_branch() { command.extend_from_slice(&[&"--cfg", &"feature=\"master\""]); } run_command_with_env(&command, None, Some(env))?; - run_command_in_vm( + maybe_run_command_in_vm( &[ - &Path::new(&args.config_info.cargo_target_dir).join("std_example"), + &cargo_target_dir.join("std_example"), &"--target", &args.config_info.target_triple, ], @@ -472,12 +454,14 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { args, )?; + let test_flags = if let Some(test_flags) = env.get("TEST_FLAGS") { + split_args(test_flags)? + } else { + Vec::new() + }; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] subslice-patterns-const-eval"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/subslice-patterns-const-eval.rs", &"--crate-type", @@ -485,19 +469,19 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"--target", &args.config_info.target_triple, ]); + for test_flag in &test_flags { + command.push(test_flag); + } run_command_with_env(&command, None, Some(env))?; - run_command_in_vm( - &[&Path::new(&args.config_info.cargo_target_dir).join("subslice-patterns-const-eval")], + maybe_run_command_in_vm( + &[&cargo_target_dir.join("subslice-patterns-const-eval")], env, args, )?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] track-caller-attribute"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/track-caller-attribute.rs", &"--crate-type", @@ -505,19 +489,19 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"--target", &args.config_info.target_triple, ]); + for test_flag in &test_flags { + command.push(test_flag); + } run_command_with_env(&command, None, Some(env))?; - run_command_in_vm( - &[&Path::new(&args.config_info.cargo_target_dir).join("track-caller-attribute")], + maybe_run_command_in_vm( + &[&cargo_target_dir.join("track-caller-attribute")], env, args, )?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] mod_bench"); - let mut command: Vec<&dyn AsRef> = Vec::new(); - for arg in args.config_info.rustc_command.iter() { - command.push(arg); - } + let mut command = args.config_info.rustc_command_vec(); command.extend_from_slice(&[ &"example/mod_bench.rs", &"--crate-type", @@ -547,6 +531,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { None => return Err("Couldn't retrieve rustc commit hash".to_string()), }; run_command_with_output_and_env(&[&"git", &"checkout", &rustc_commit], rust_dir, Some(env))?; + // FIXME: Is it really needed to empty `RUSTFLAGS` here? env.insert("RUSTFLAGS".to_string(), String::new()); let cargo = String::from_utf8( run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout, @@ -661,7 +646,7 @@ fn run_cargo_command( args: &TestArg, ) -> Result<(), String> { run_cargo_command_with_callback(command, cwd, env, args, |cargo_command, cwd, env| { - run_command_with_output_and_env(&cargo_command, cwd, Some(env))?; + run_command_with_output_and_env(cargo_command, cwd, Some(env))?; Ok(()) }) } @@ -734,7 +719,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { // hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_* fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { - if args.no_default_features { + if !args.is_using_gcc_master_branch() { return Ok(()); } let path = Path::new("rand"); @@ -746,7 +731,7 @@ fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { } fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> { - if args.no_default_features { + if !args.is_using_gcc_master_branch() { return Ok(()); } let path = Path::new("regex"); @@ -800,7 +785,7 @@ fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> } fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { - if args.no_default_features { + if !args.is_using_gcc_master_branch() { return Ok(()); } // FIXME: create a function "display_if_not_quiet" or something along the line. @@ -817,6 +802,7 @@ fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"test", &"--tests", &"--", + // FIXME: try removing `--exclude-should-panic` argument &"--exclude-should-panic", &"--test-threads", &"1", @@ -848,24 +834,22 @@ fn extended_sysroot_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -fn should_remove_ui_test(content: &str) -> bool { - for line in content - .lines() - .map(|line| line.trim()) - .filter(|line| !line.is_empty()) - { - if [ - "// error-pattern:", - "// build-fail", - "// run-fail", - "-Cllvm-args", - "//~", - "// ~", - ] - .iter() - .any(|check| line.contains(check)) - { - return true; +fn should_remove_ui_test(file: File) -> bool { + for line in BufReader::new(file).lines() { + if let Ok(line) = line { + if [ + "// error-pattern:", + "// build-fail", + "// run-fail", + "-Cllvm-args", + "//~", + "// ~", + ] + .iter() + .any(|check| line.contains(check)) + { + return true; + } } } false @@ -903,7 +887,7 @@ fn should_remove_test(path: &Path, path_str: &str) -> bool { .any(|to_ignore| path_str.ends_with(to_ignore)) } -fn test_rustc_inner(env: &Env, args: &TestArg, callback: F) -> Result<(), String> +fn test_rustc_inner(env: &Env, args: &TestArg, prepare_files_callback: F) -> Result<(), String> where F: Fn() -> Result, { @@ -937,24 +921,24 @@ where |_| Ok(()), )?; + // These two functions are used to remove files that are known to not be working currently + // with the GCC backend to reduce noise. fn dir_handling(dir: &Path) -> Result<(), String> { walk_dir(dir, dir_handling, file_handling) } - fn file_handling(file: &Path) -> Result<(), String> { - let path_str = file.display().to_string().replace("\\", "/"); + fn file_handling(file_path: &Path) -> Result<(), String> { + let path_str = file_path.display().to_string().replace("\\", "/"); if !path_str.ends_with(".rs") { return Ok(()); } else if should_not_remove_test(&path_str) { return Ok(()); - } else if should_remove_test(file, &path_str) { - return std::fs::remove_file(file) - .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error)); + } else if should_remove_test(file_path, &path_str) { + return remove_file(&file_path); } - let file_content = std::fs::read_to_string(file) - .map_err(|error| format!("Failed to read `{}`: {:?}", file.display(), error))?; - if should_remove_ui_test(&file_content) { - std::fs::remove_file(file) - .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error))?; + let file = File::open(file_path) + .map_err(|error| format!("Failed to read `{}`: {:?}", file_path.display(), error))?; + if should_remove_ui_test(file) { + remove_file(&file_path)?; } Ok(()) } @@ -963,20 +947,18 @@ where walk_dir(rust_path.join("tests/ui"), dir_handling, file_handling)?; let file = rust_path.join("tests/ui/consts/const_cmp_type_id.rs"); - std::fs::remove_file(&file) - .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error))?; + remove_file(&file)?; let file = rust_path.join("tests/ui/consts/issue-73976-monomorphic.rs"); - std::fs::remove_file(&file) - .map_err(|error| format!("Failed to remove `{}`: {:?}", file.display(), error))?; + remove_file(&file)?; - if !callback()? { + if !prepare_files_callback()? { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("Keeping all UI tests"); } let nb_parts = args.nb_parts.unwrap_or(0); if nb_parts > 0 { - let current_part = args.current_part.unwrap_or(0); + let current_part = args.current_part.unwrap(); // FIXME: create a function "display_if_not_quiet" or something along the line. println!( "Splitting ui_test into {} parts (and running part {})", @@ -1017,18 +999,19 @@ where continue; } let test_path = rust_path.join(path); - std::fs::remove_file(&test_path).map_err(|error| { - format!("Failed to remove `{}`: {:?}", test_path.display(), error) - })?; + remove_file(&test_path)?; } } // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rustc test suite"); env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); - let rustc_args = env - .get("RUSTFLAGS") - .expect("RUSTFLAGS should not be empty at this stage"); + let rustc_args = format!( + "{} {}", + env.get("RUSTFLAGS") + .expect("RUSTFLAGS should not be empty at this stage"), + env.get("TEST_FLAGS").unwrap_or(&String::new()), + ); run_command_with_output_and_env( &[ &"./x.py", @@ -1103,9 +1086,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { .filter(|line| !line.is_empty()) { let path = Path::new("rust").join(file); - std::fs::remove_file(&path).map_err(|error| { - format!("failed to remove `{}`: {:?}", path.display(), error) - })?; + remove_file(&path)?; } } else { println!( @@ -1159,9 +1140,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - let test_flags = split_args(env.get("TEST_FLAGS").unwrap_or(&String::new())); - args.config_info - .setup(&mut env, &test_flags, Some(&args.gcc_path))?; + args.config_info.setup(&mut env, Some(&args.gcc_path))?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 88fce2fcbce18..59863fcfd90a1 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; @@ -48,16 +49,20 @@ fn check_exit_status( let input = input.iter().map(|i| i.as_ref()).collect::>(); eprintln!("Command `{:?}` failed", input); if let Some(output) = output { - unsafe { - let stdout = std::str::from_utf8_unchecked(&output.stdout); - if !stdout.is_empty() { - error.push_str("\n==== STDOUT ====\n"); - error.push_str(stdout); + let stdout = String::from_utf8_lossy(&output.stdout); + if !stdout.is_empty() { + error.push_str("\n==== STDOUT ====\n"); + match stdout { + Cow::Owned(s) => error.push_str(&s), + Cow::Borrowed(s) => error.push_str(s), } - let stderr = std::str::from_utf8_unchecked(&output.stderr); - if !stderr.is_empty() { - error.push_str("\n==== STDERR ====\n"); - error.push_str(stderr); + } + let stderr = String::from_utf8_lossy(&output.stderr); + if !stderr.is_empty() { + error.push_str("\n==== STDERR ====\n"); + match stderr { + Cow::Owned(s) => error.push_str(&s), + Cow::Borrowed(s) => error.push_str(s), } } } @@ -295,17 +300,16 @@ where Ok(()) } -pub fn split_args(args: &str) -> Vec { +pub fn split_args(args: &str) -> Result, String> { let mut out = Vec::new(); let mut start = 0; + let args = args.trim(); let mut iter = args.char_indices().peekable(); while iter.peek().is_some() { while let Some((pos, c)) = iter.next() { if c == ' ' { - if pos != 0 { - out.push(args[start..pos].to_string()); - } + out.push(args[start..pos].to_string()); let mut found_start = false; while let Some((pos, c)) = iter.peek() { if *c != ' ' { @@ -317,7 +321,7 @@ pub fn split_args(args: &str) -> Vec { } } if !found_start { - return out; + return Ok(out); } } else if c == '"' || c == '\'' { let end = c; @@ -332,8 +336,7 @@ pub fn split_args(args: &str) -> Vec { } } if !found_end { - out.push(args[start..].to_string()); - return out; + return Err(format!("Didn't find `{}` at the end of `{}`", end, &args[start..])); } } else if c == '\\' { // We skip the escaped character. @@ -345,5 +348,15 @@ pub fn split_args(args: &str) -> Vec { if !s.is_empty() { out.push(s.to_string()); } - out + Ok(out) +} + +pub fn remove_file>(file_path: &P) -> Result<(), String> { + std::fs::remove_file(file_path).map_err(|error| { + format!( + "Failed to remove `{}`: {:?}", + file_path.as_ref().display(), + error + ) + }) } From 2baa073fb1dc1a3556d174b58e5bc94b28682119 Mon Sep 17 00:00:00 2001 From: quininer Date: Mon, 13 Nov 2023 20:48:23 +0800 Subject: [PATCH 040/613] Add emulated TLS support Currently LLVM uses emutls by default for some targets (such as android, openbsd), but rust does not use it, because `has_thread_local` is false. This commit has some changes to allow users to enable emutls: 1. add `-Zhas-thread-local` flag to specify that std uses `#[thread_local]` instead of pthread key. 2. when using emutls, decorate symbol names to find thread local symbol correctly. 3. change `-Zforce-emulated-tls` to `-Ztls-model=emulated` to explicitly specify whether to generate emutls. --- src/context.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/context.rs b/src/context.rs index a043660ea632b..893cad0516182 100644 --- a/src/context.rs +++ b/src/context.rs @@ -569,5 +569,6 @@ fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel { TlsModel::LocalDynamic => gccjit::TlsModel::LocalDynamic, TlsModel::InitialExec => gccjit::TlsModel::InitialExec, TlsModel::LocalExec => gccjit::TlsModel::LocalExec, + TlsModel::Emulated => gccjit::TlsModel::GlobalDynamic, } } From 19e11760ab8c2694875f4fdbeb4063706ceae009 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 7 Dec 2023 14:59:37 +0100 Subject: [PATCH 041/613] Update rustc_codegen_gcc libc --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c18633692783..ddfce5d59bde8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "linux-raw-sys" From 3cfff05ac7c880e24c4e89f4e9518e8715d2ef29 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 7 Dec 2023 15:25:46 +0100 Subject: [PATCH 042/613] Allow internal_features in rustc_codegen_gcc examples --- example/std_example.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/example/std_example.rs b/example/std_example.rs index 0f6325c8980e7..ad69409eb6590 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -1,3 +1,4 @@ +#![allow(internal_features)] #![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)] #[cfg(feature="master")] From cb32ffd8da5831c7052362fa58d27b36558b3b78 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 25 Nov 2023 18:41:53 +0100 Subject: [PATCH 043/613] ctfe interpreter: extend provenance so that it can track whether a pointer is immutable --- src/common.rs | 3 ++- src/consts.rs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common.rs b/src/common.rs index 93fe27e547aef..b7ddc410315c3 100644 --- a/src/common.rs +++ b/src/common.rs @@ -199,7 +199,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } } Scalar::Ptr(ptr, _size) => { - let (alloc_id, offset) = ptr.into_parts(); + let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative + let alloc_id = prov.alloc_id(); let base_addr = match self.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { diff --git a/src/consts.rs b/src/consts.rs index d8a1fd315c0a5..f06416b9bb5fe 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -285,7 +285,8 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; - for &(offset, alloc_id) in alloc.provenance().ptrs().iter() { + for &(offset, prov) in alloc.provenance().ptrs().iter() { + let alloc_id = prov.alloc_id(); let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; @@ -313,7 +314,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl llvals.push(cx.scalar_to_backend( InterpScalar::from_pointer( - interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), + interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx, ), abi::Scalar::Initialized { value: Primitive::Pointer(address_space), valid_range: WrappingRange::full(dl.pointer_size) }, From 92de9d4210a7e81fd8db558c54367026a68bec62 Mon Sep 17 00:00:00 2001 From: r0cky Date: Mon, 11 Dec 2023 23:12:49 +0800 Subject: [PATCH 044/613] Remove dead codes --- src/common.rs | 11 ----------- src/context.rs | 6 ------ 2 files changed, 17 deletions(-) diff --git a/src/common.rs b/src/common.rs index b7ddc410315c3..c6edd52d1e416 100644 --- a/src/common.rs +++ b/src/common.rs @@ -377,9 +377,6 @@ pub trait TypeReflection<'gcc, 'tcx> { fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; - fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; - fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool; - fn is_vector(&self) -> bool; } @@ -464,14 +461,6 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> { self.unqualified() == cx.u128_type.unqualified() } - fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.unqualified() == cx.context.new_type::() - } - - fn is_f64(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool { - self.unqualified() == cx.context.new_type::() - } - fn is_vector(&self) -> bool { let mut typ = self.clone(); loop { diff --git a/src/context.rs b/src/context.rs index 893cad0516182..ab9c703db37da 100644 --- a/src/context.rs +++ b/src/context.rs @@ -22,12 +22,6 @@ use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; use crate::callee::get_fn; use crate::common::SignType; -#[derive(Clone)] -pub struct FuncSig<'gcc> { - pub params: Vec>, - pub return_type: Type<'gcc>, -} - pub struct CodegenCx<'gcc, 'tcx> { pub check_overflow: bool, pub codegen_unit: &'tcx CodegenUnit<'tcx>, From 547f3cef6022980187da2744b3c6ed93368328bd Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Mon, 11 Dec 2023 11:41:33 -0600 Subject: [PATCH 045/613] fixing error std::fs::read_to_string example documentation --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 4310e10830380..ed630ef3dc7f1 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -283,11 +283,11 @@ pub fn read>(path: P) -> io::Result> { /// /// ```no_run /// use std::fs; -/// use std::net::SocketAddr; /// use std::error::Error; /// /// fn main() -> Result<(), Box> { -/// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; +/// let address: String = fs::read_to_string("address.txt")?; +/// println!("{}", address); /// Ok(()) /// } /// ``` From a72e20d77378420af6c02daebb9c6b1f3fe9757a Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 11 Dec 2023 18:48:49 +0100 Subject: [PATCH 046/613] Fix rustc codegen gcc tests --- example/mini_core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 3432852034325..db94bc1c86af9 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -4,7 +4,7 @@ thread_local )] #![no_core] -#![allow(dead_code, internal_features)] +#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)] #[no_mangle] unsafe extern "C" fn _Unwind_Resume() { From 6e9ca489f703f055d98bf7a513b2491dbec63983 Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Mon, 11 Dec 2023 12:00:23 -0600 Subject: [PATCH 047/613] Updating fs::read example to remove SocketAddress --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index ed630ef3dc7f1..acc0f37a688a8 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -242,10 +242,10 @@ pub struct DirBuilder { /// /// ```no_run /// use std::fs; -/// use std::net::SocketAddr; /// /// fn main() -> Result<(), Box> { -/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// let address: String = String::from_utf8_lossy(&fs::read("address.txt")?).to_string(); +/// println!("{}", address); /// Ok(()) /// } /// ``` From 867ea124884cabf81462e152fcfa2cdccd3ed1aa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 5 Dec 2023 21:09:13 +0100 Subject: [PATCH 048/613] Fix non-running rustc ui tests --- build_system/src/build.rs | 2 +- build_system/src/config.rs | 17 ++-- build_system/src/test.rs | 186 ++++++++++++++++++------------------- build_system/src/utils.rs | 6 +- 4 files changed, 108 insertions(+), 103 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 618e74be2c0c9..370d8436e3de1 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -128,9 +128,9 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu &[ &"cargo", &"build", + &"--release", &"--target", &config.target_triple, - &"--release", ], Some(start_dir), Some(&env), diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 8396681b292a4..091186b90660c 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -13,6 +13,8 @@ pub struct ConfigInfo { pub dylib_ext: String, pub sysroot_release_channel: bool, pub sysroot_panic_abort: bool, + pub cg_backend_path: String, + pub sysroot_path: String, } impl ConfigInfo { @@ -118,13 +120,12 @@ impl ConfigInfo { .get("BUILTIN_BACKEND") .map(|backend| !backend.is_empty()) .unwrap_or(false); - let cg_backend_path; let mut rustflags = Vec::new(); if has_builtin_backend { // It means we're building inside the rustc testsuite, so some options need to be handled // a bit differently. - cg_backend_path = "gcc".to_string(); + self.cg_backend_path = "gcc".to_string(); match env.get("RUSTC_SYSROOT") { Some(rustc_sysroot) if !rustc_sysroot.is_empty() => { @@ -134,15 +135,17 @@ impl ConfigInfo { } rustflags.push("-Cpanic=abort".to_string()); } else { - cg_backend_path = current_dir + self.cg_backend_path = current_dir .join("target") .join(channel) .join(&format!("librustc_codegen_gcc.{}", self.dylib_ext)) .display() .to_string(); - let sysroot_path = current_dir.join("build_sysroot/sysroot"); - rustflags - .extend_from_slice(&["--sysroot".to_string(), sysroot_path.display().to_string()]); + self.sysroot_path = current_dir + .join("build_sysroot/sysroot") + .display() + .to_string(); + rustflags.extend_from_slice(&["--sysroot".to_string(), self.sysroot_path.clone()]); }; // This environment variable is useful in case we want to change options of rustc commands. @@ -156,7 +159,7 @@ impl ConfigInfo { rustflags.extend_from_slice(&[ "-Csymbol-mangling-version=v0".to_string(), "-Cdebuginfo=2".to_string(), - format!("-Zcodegen-backend={}", cg_backend_path), + format!("-Zcodegen-backend={}", self.cg_backend_path), ]); // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO. diff --git a/build_system/src/test.rs b/build_system/src/test.rs index af2367e668ebb..efd8ebdd52d91 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,14 +1,13 @@ use crate::build; use crate::config::ConfigInfo; use crate::utils::{ - get_gcc_path, get_toolchain, run_command, run_command_with_env, + get_gcc_path, get_toolchain, remove_file, run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, - remove_file, }; use std::collections::{BTreeSet, HashMap}; use std::ffi::OsStr; -use std::fs::{File, remove_dir_all}; +use std::fs::{remove_dir_all, File}; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -213,8 +212,11 @@ impl TestArg { match (test_arg.current_part, test_arg.nb_parts) { (Some(_), Some(_)) | (None, None) => {} _ => { - return Err("If either `--current-part` or `--nb-parts` is specified, the other one \ - needs to be specified as well!".to_string()); + return Err( + "If either `--current-part` or `--nb-parts` is specified, the other one \ + needs to be specified as well!" + .to_string(), + ); } } Ok(Some(test_arg)) @@ -230,20 +232,19 @@ fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> { return Ok(()); } let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; - if args.channel == Channel::Release { - let mut env = env.clone(); - env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); + let mut tmp_env; + let env = if args.channel == Channel::Release { + tmp_env = env.clone(); + tmp_env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); command.push(&"--release"); - for flag in args.flags.iter() { - command.push(flag); - } - run_command_with_output_and_env(&command, None, Some(&env)) + &tmp_env } else { - for flag in args.flags.iter() { - command.push(flag); - } - run_command_with_output_and_env(&command, None, Some(&env)) + &env + }; + for flag in args.flags.iter() { + command.push(flag); } + run_command_with_output_and_env(&command, None, Some(env)) } fn clean(_env: &Env, args: &TestArg) -> Result<(), String> { @@ -403,11 +404,7 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); run_command_with_env(&command, None, Some(env))?; - maybe_run_command_in_vm( - &[&cargo_target_dir.join("alloc_example")], - env, - args, - )?; + maybe_run_command_in_vm(&[&cargo_target_dir.join("alloc_example")], env, args)?; } // FIXME: create a function "display_if_not_quiet" or something along the line. @@ -424,11 +421,7 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); run_command_with_env(&command, None, Some(env))?; - maybe_run_command_in_vm( - &[&cargo_target_dir.join("dst_field_align")], - env, - args, - )?; + maybe_run_command_in_vm(&[&cargo_target_dir.join("dst_field_align")], env, args)?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] std_example"); @@ -525,6 +518,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { None, Some(env), ); + run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?; run_command_with_output_and_env(&[&"git", &"fetch"], rust_dir, Some(env))?; let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { Some(commit_hash) => commit_hash, @@ -532,7 +526,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { }; run_command_with_output_and_env(&[&"git", &"checkout", &rustc_commit], rust_dir, Some(env))?; // FIXME: Is it really needed to empty `RUSTFLAGS` here? - env.insert("RUSTFLAGS".to_string(), String::new()); + // env.insert("RUSTFLAGS".to_string(), String::new()); let cargo = String::from_utf8( run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout, ) @@ -591,15 +585,6 @@ download-ci-llvm = false ), ) .map_err(|error| format!("Failed to write into `rust/config.toml`: {:?}", error))?; - - let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { - Some(commit_hash) => commit_hash, - None => return Err("Couldn't retrieve rustc commit hash".to_string()), - }; - // FIXME: create a function "display_if_not_quiet" or something along the line. - println!("commit: {:?}", rustc_commit); - let command: &[&dyn AsRef] = &[&"git", &"checkout", &rustc_commit, &"tests"]; - run_command_with_output_and_env(command, rust_dir, Some(env))?; Ok(()) } @@ -834,27 +819,6 @@ fn extended_sysroot_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -fn should_remove_ui_test(file: File) -> bool { - for line in BufReader::new(file).lines() { - if let Ok(line) = line { - if [ - "// error-pattern:", - "// build-fail", - "// run-fail", - "-Cllvm-args", - "//~", - "// ~", - ] - .iter() - .any(|check| line.contains(check)) - { - return true; - } - } - } - false -} - fn should_not_remove_test(file: &str) -> bool { // contains //~ERROR, but shouldn't be removed [ @@ -870,21 +834,40 @@ fn should_not_remove_test(file: &str) -> bool { .any(|to_ignore| file.ends_with(to_ignore)) } -fn should_remove_test(path: &Path, path_str: &str) -> bool { +fn should_remove_test(file_path: &Path) -> Result { // Tests generating errors. - path.file_name() - .and_then(|name| name.to_str()) - .map(|name| name.contains("thread")) - .unwrap_or(false) - || [ - "consts/issue-miri-1910.rs", - // Tests generating errors. - "consts/issue-94675.rs", - // this test is oom-killed in the CI. - "mir/mir_heavy/issue-miri-1910.rs", + let file = File::open(file_path) + .map_err(|error| format!("Failed to read `{}`: {:?}", file_path.display(), error))?; + for line in BufReader::new(file).lines().filter_map(|line| line.ok()) { + let line = line.trim(); + if line.is_empty() { + continue; + } + if [ + "// error-pattern:", + "// build-fail", + "// run-fail", + "-Cllvm-args", + "//~", + "thread", ] .iter() - .any(|to_ignore| path_str.ends_with(to_ignore)) + .any(|check| line.contains(check)) + { + return Ok(true); + } + if line.contains("//[") && line.contains("]~") { + return Ok(true); + } + } + if file_path + .display() + .to_string() + .contains("ambiguous-4-extern.rs") + { + eprintln!("nothing found for {file_path:?}"); + } + Ok(false) } fn test_rustc_inner(env: &Env, args: &TestArg, prepare_files_callback: F) -> Result<(), String> @@ -896,6 +879,8 @@ where let mut env = env.clone(); setup_rustc(&mut env, args)?; + let rust_path = Path::new("rust"); + walk_dir( "rust/tests/ui", |dir| { @@ -924,32 +909,41 @@ where // These two functions are used to remove files that are known to not be working currently // with the GCC backend to reduce noise. fn dir_handling(dir: &Path) -> Result<(), String> { + if dir + .file_name() + .map(|name| name == "auxiliary") + .unwrap_or(true) + { + return Ok(()); + } walk_dir(dir, dir_handling, file_handling) } fn file_handling(file_path: &Path) -> Result<(), String> { - let path_str = file_path.display().to_string().replace("\\", "/"); - if !path_str.ends_with(".rs") { + if !file_path + .extension() + .map(|extension| extension == "rs") + .unwrap_or(false) + { return Ok(()); - } else if should_not_remove_test(&path_str) { + } + let path_str = file_path.display().to_string().replace("\\", "/"); + if should_not_remove_test(&path_str) { return Ok(()); - } else if should_remove_test(file_path, &path_str) { + } else if should_remove_test(file_path)? { return remove_file(&file_path); } - let file = File::open(file_path) - .map_err(|error| format!("Failed to read `{}`: {:?}", file_path.display(), error))?; - if should_remove_ui_test(file) { - remove_file(&file_path)?; - } Ok(()) } - let rust_path = Path::new("rust"); + remove_file(&rust_path.join("tests/ui/consts/const_cmp_type_id.rs"))?; + remove_file(&rust_path.join("tests/ui/consts/issue-73976-monomorphic.rs"))?; + // this test is oom-killed in the CI. + remove_file(&rust_path.join("tests/ui/consts/issue-miri-1910.rs"))?; + // Tests generating errors. + remove_file(&rust_path.join("tests/ui/consts/issue-94675.rs"))?; + remove_file(&rust_path.join("tests/ui/mir/mir_heavy_promoted.rs"))?; walk_dir(rust_path.join("tests/ui"), dir_handling, file_handling)?; - let file = rust_path.join("tests/ui/consts/const_cmp_type_id.rs"); - remove_file(&file)?; - let file = rust_path.join("tests/ui/consts/issue-73976-monomorphic.rs"); - remove_file(&file)?; if !prepare_files_callback()? { // FIXME: create a function "display_if_not_quiet" or something along the line. @@ -992,14 +986,16 @@ where // We increment the number of tests by one because if this is an odd number, we would skip // one test. let count = files.len() / nb_parts + 1; - let start = nb_parts * count; - let end = start + count; - for (pos, path) in files.iter().enumerate() { - if pos >= start && pos <= end { - continue; - } - let test_path = rust_path.join(path); - remove_file(&test_path)?; + let start = current_part * count; + let end = current_part * count + count; + // We remove the files we don't want to test. + for path in files + .iter() + .enumerate() + .filter(|(pos, _)| *pos < start || *pos >= end) + .map(|(_, path)| path) + { + remove_file(&rust_path.join(path))?; } } @@ -1007,11 +1003,13 @@ where println!("[TEST] rustc test suite"); env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); let rustc_args = format!( - "{} {}", - env.get("RUSTFLAGS") - .expect("RUSTFLAGS should not be empty at this stage"), + "{} -Csymbol-mangling-version=v0 -Zcodegen-backend={} --sysroot {}", env.get("TEST_FLAGS").unwrap_or(&String::new()), + args.config_info.cg_backend_path, + args.config_info.sysroot_path, ); + + env.get_mut("RUSTFLAGS").unwrap().clear(); run_command_with_output_and_env( &[ &"./x.py", diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 59863fcfd90a1..9d785e7f57cf4 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -336,7 +336,11 @@ pub fn split_args(args: &str) -> Result, String> { } } if !found_end { - return Err(format!("Didn't find `{}` at the end of `{}`", end, &args[start..])); + return Err(format!( + "Didn't find `{}` at the end of `{}`", + end, + &args[start..] + )); } } else if c == '\\' { // We skip the escaped character. From e1f039f5628f665dead2c9a13b4c32ffe92336ac Mon Sep 17 00:00:00 2001 From: Lukasz Anforowicz Date: Wed, 13 Dec 2023 21:14:18 +0000 Subject: [PATCH 049/613] Add unstable `-Zdefault-hidden-visibility` cmdline flag for `rustc`. The new flag has been described in the Major Change Proposal at https://github.com/rust-lang/compiler-team/issues/656 --- src/allocator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/allocator.rs b/src/allocator.rs index c8c098e2973f0..7c7044830f3d4 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -90,7 +90,7 @@ fn create_wrapper_function( .collect(); let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, from_name, false); - if tcx.sess.target.options.default_hidden_visibility { + if tcx.sess.default_hidden_visibility() { #[cfg(feature="master")] func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } From b1affb9321442f378ee06fbaf0ebdc3317e5c9fe Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 12 Dec 2023 21:47:20 +0100 Subject: [PATCH 050/613] Move rustc_codegen_ssa target features to rustc_target --- src/gcc_util.rs | 8 +++----- src/lib.rs | 5 +++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 1248fdcd2599c..2aa84f26797c3 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -2,12 +2,10 @@ use gccjit::Context; use smallvec::{smallvec, SmallVec}; -use rustc_codegen_ssa::target_features::{ - supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES, -}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; +use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use crate::errors::{PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix}; @@ -44,7 +42,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> // Given a map from target_features to whether they are enabled or disabled, // ensure only valid combinations are allowed. pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> { - for tied in tied_target_features(sess) { + for tied in sess.target.tied_target_features() { // Tied features must be set to the same value, or not set at all let mut tied_iter = tied.iter(); let enabled = features.get(tied_iter.next().unwrap()); diff --git a/src/lib.rs b/src/lib.rs index d54057615d2d8..0ececc5dda0a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,7 +97,6 @@ use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; -use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods}; @@ -397,7 +396,9 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo) -> Vec { - supported_target_features(sess) + sess + .target + .supported_target_features() .iter() .filter_map( |&(feature, gate)| { From db9b932314023318f49b0b5941d09f034a12b31e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Dec 2023 21:35:05 +0100 Subject: [PATCH 051/613] Fix sysroot build --- build_system/src/build.rs | 8 +++----- build_system/src/config.rs | 24 +++++++++++++++++++++++- build_system/src/test.rs | 27 +++------------------------ 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 370d8436e3de1..9fb47195aeed7 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -1,4 +1,4 @@ -use crate::config::ConfigInfo; +use crate::config::{Channel, ConfigInfo}; use crate::utils::{get_gcc_path, run_command, run_command_with_output_and_env, walk_dir}; use std::collections::HashMap; use std::ffi::OsStr; @@ -7,7 +7,6 @@ use std::path::Path; #[derive(Default)] struct BuildArg { - codegen_release_channel: bool, flags: Vec, gcc_path: String, config_info: ConfigInfo, @@ -25,7 +24,6 @@ impl BuildArg { while let Some(arg) = args.next() { match arg.as_str() { - "--release" => build_arg.codegen_release_channel = true, "--no-default-features" => { build_arg.flags.push("--no-default-features".to_string()); } @@ -58,7 +56,6 @@ impl BuildArg { r#" `build` command help: - --release : Build codegen in release mode --no-default-features : Add `--no-default-features` flag --features [arg] : Add a new feature [arg]"# ); @@ -118,6 +115,7 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu if config.sysroot_panic_abort { rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } + rustflags.push_str(" -Z force-unstable-if-unmarked"); let mut env = env.clone(); let channel = if config.sysroot_release_channel { env.insert( @@ -194,7 +192,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; - if args.codegen_release_channel { + if args.config_info.channel == Channel::Release { command.push(&"--release"); env.insert("CHANNEL".to_string(), "release".to_string()); env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 091186b90660c..09375791aa314 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -3,6 +3,22 @@ use std::collections::HashMap; use std::env as std_env; use std::ffi::OsStr; +#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] +pub enum Channel { + #[default] + Debug, + Release, +} + +impl Channel { + pub fn as_str(self) -> &'static str { + match self { + Self::Debug => "debug", + Self::Release => "release", + } + } +} + #[derive(Default, Debug)] pub struct ConfigInfo { pub target_triple: String, @@ -12,6 +28,7 @@ pub struct ConfigInfo { pub cargo_target_dir: String, pub dylib_ext: String, pub sysroot_release_channel: bool, + pub channel: Channel, pub sysroot_panic_abort: bool, pub cg_backend_path: String, pub sysroot_path: String, @@ -40,6 +57,7 @@ impl ConfigInfo { _ => return Err("Expected a value after `--out-dir`, found nothing".to_string()), }, "--release-sysroot" => self.sysroot_release_channel = true, + "--release" => self.channel = Channel::Release, "--sysroot-panic-abort" => self.sysroot_panic_abort = true, _ => return Ok(false), } @@ -108,7 +126,7 @@ impl ConfigInfo { let current_dir = std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?; - let channel = if self.sysroot_release_channel { + let channel = if self.channel == Channel::Release { "release" } else if let Some(channel) = env.get("CHANNEL") { channel.as_str() @@ -152,6 +170,9 @@ impl ConfigInfo { if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { rustflags.extend_from_slice(&split_args(&cg_rustflags)?); } + if let Some(test_flags) = env.get("TEST_FLAGS") { + rustflags.extend_from_slice(&split_args(&test_flags)?); + } if let Some(linker) = linker { rustflags.push(linker.to_string()); @@ -223,6 +244,7 @@ impl ConfigInfo { "\ --target-triple [arg] : Set the target triple to [arg] --out-dir : Location where the files will be generated + --release : Build in release mode --release-sysroot : Build sysroot in release mode --sysroot-panic-abort : Build the sysroot without unwinding support." ); diff --git a/build_system/src/test.rs b/build_system/src/test.rs index efd8ebdd52d91..1e9652d282200 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,5 +1,5 @@ use crate::build; -use crate::config::ConfigInfo; +use crate::config::{Channel, ConfigInfo}; use crate::utils::{ get_gcc_path, get_toolchain, remove_file, run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, @@ -104,28 +104,11 @@ fn show_usage() { println!(" --help : Show this help"); } -#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] -enum Channel { - #[default] - Debug, - Release, -} - -impl Channel { - pub fn as_str(self) -> &'static str { - match self { - Self::Debug => "debug", - Self::Release => "release", - } - } -} - #[derive(Default, Debug)] struct TestArg { no_default_features: bool, build_only: bool, gcc_path: String, - channel: Channel, use_backend: bool, runners: BTreeSet, flags: Vec, @@ -147,10 +130,6 @@ impl TestArg { while let Some(arg) = args.next() { match arg.as_str() { - "--release" => { - test_arg.channel = Channel::Release; - test_arg.config_info.sysroot_release_channel = true; - } "--no-default-features" => { // To prevent adding it more than once. if !test_arg.no_default_features { @@ -233,7 +212,7 @@ fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> { } let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; let mut tmp_env; - let env = if args.channel == Channel::Release { + let env = if args.config_info.channel == Channel::Release { tmp_env = env.clone(); tmp_env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); command.push(&"--release"); @@ -613,7 +592,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { pwd = std::env::current_dir() .map_err(|error| format!("`current_dir` failed: {:?}", error))? .display(), - channel = args.channel.as_str(), + channel = args.config_info.channel.as_str(), dylib_ext = args.config_info.dylib_ext, ) .as_str(), From 95dfe5ec9040bcba53a8dd61d3593d182defab71 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Dec 2023 17:39:58 +0100 Subject: [PATCH 052/613] Simplify `split_args` code, add a unit test for it and run it into CI --- .github/workflows/ci.yml | 9 ++++ build_system/src/utils.rs | 95 ++++++++++++++++++++++++--------------- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e361bf617b1f..b04ea1550ba2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -131,3 +131,12 @@ jobs: steps: - uses: actions/checkout@v3 - run: python tools/check_intrinsics_duplicates.py + + build_system: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Test build system + run: | + cd build_system + cargo test diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 9d785e7f57cf4..ebfa41c761cee 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -306,46 +306,44 @@ pub fn split_args(args: &str) -> Result, String> { let args = args.trim(); let mut iter = args.char_indices().peekable(); - while iter.peek().is_some() { - while let Some((pos, c)) = iter.next() { - if c == ' ' { - out.push(args[start..pos].to_string()); - let mut found_start = false; - while let Some((pos, c)) = iter.peek() { - if *c != ' ' { - start = *pos; - found_start = true; - break; - } else { - iter.next(); - } + while let Some((pos, c)) = iter.next() { + if c == ' ' { + out.push(args[start..pos].to_string()); + let mut found_start = false; + while let Some((pos, c)) = iter.peek() { + if *c != ' ' { + start = *pos; + found_start = true; + break; + } else { + iter.next(); } - if !found_start { - return Ok(out); - } - } else if c == '"' || c == '\'' { - let end = c; - let mut found_end = false; - while let Some((_, c)) = iter.next() { - if c == end { - found_end = true; - break; - } else if c == '\\' { - // We skip the escaped character. - iter.next(); - } - } - if !found_end { - return Err(format!( - "Didn't find `{}` at the end of `{}`", - end, - &args[start..] - )); + } + if !found_start { + return Ok(out); + } + } else if c == '"' || c == '\'' { + let end = c; + let mut found_end = false; + while let Some((_, c)) = iter.next() { + if c == end { + found_end = true; + break; + } else if c == '\\' { + // We skip the escaped character. + iter.next(); } - } else if c == '\\' { - // We skip the escaped character. - iter.next(); } + if !found_end { + return Err(format!( + "Didn't find `{}` at the end of `{}`", + end, + &args[start..] + )); + } + } else if c == '\\' { + // We skip the escaped character. + iter.next(); } } let s = args[start..].trim(); @@ -364,3 +362,26 @@ pub fn remove_file>(file_path: &P) -> Result<(), String> { ) }) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_split_args() { + // Missing `"` at the end. + assert!(split_args("\"tada").is_err()); + // Missing `'` at the end. + assert!(split_args("\'tada").is_err()); + + assert_eq!( + split_args("a \"b\" c"), + Ok(vec!["a".to_string(), "\"b\"".to_string(), "c".to_string()]) + ); + // Trailing whitespace characters. + assert_eq!( + split_args(" a \"b\" c "), + Ok(vec!["a".to_string(), "\"b\"".to_string(), "c".to_string()]) + ); + } +} From 9882d7c511fcfed404c547a64cbc42b6cf3fc17c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Dec 2023 17:55:53 +0100 Subject: [PATCH 053/613] Apply suggestions --- build_system/src/build.rs | 4 ++-- build_system/src/config.rs | 12 ++++++++++++ build_system/src/test.rs | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 9fb47195aeed7..d264aac7effbd 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -128,7 +128,7 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu &"build", &"--release", &"--target", - &config.target_triple, + &config.target, ], Some(start_dir), Some(&env), @@ -138,7 +138,7 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu env.insert("RUSTFLAGS".to_string(), rustflags); run_command_with_output_and_env( - &[&"cargo", &"build", &"--target", &config.target_triple], + &[&"cargo", &"build", &"--target", &config.target], Some(start_dir), Some(&env), )?; diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 09375791aa314..d948572bda567 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -21,6 +21,7 @@ impl Channel { #[derive(Default, Debug)] pub struct ConfigInfo { + pub target: String, pub target_triple: String, pub host_triple: String, pub rustc_command: Vec, @@ -42,6 +43,13 @@ impl ConfigInfo { args: &mut impl Iterator, ) -> Result { match arg { + "--target" => { + if let Some(arg) = args.next() { + self.target = arg; + } else { + return Err("Expected a value after `--target`, found nothing".to_string()); + } + } "--target-triple" => match args.next() { Some(arg) if !arg.is_empty() => self.target_triple = arg.to_string(), _ => { @@ -113,6 +121,9 @@ impl ConfigInfo { if self.target_triple.is_empty() { self.target_triple = self.host_triple.clone(); } + if self.target.is_empty() && !self.target_triple.is_empty() { + self.target = self.target_triple.clone(); + } let mut linker = None; @@ -243,6 +254,7 @@ impl ConfigInfo { println!( "\ --target-triple [arg] : Set the target triple to [arg] + --target [arg] : Set the target to [arg] --out-dir : Location where the files will be generated --release : Build in release mode --release-sysroot : Build sysroot in release mode diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1e9652d282200..a926ee4c79ebd 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -482,7 +482,7 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { &args.config_info.target_triple, ]); run_command_with_env(&command, None, Some(env))?; - // FIXME: the compiled binary is not run. Is it normal? + // FIXME: the compiled binary is not run. Ok(()) } From 590e0d9573bcde7637b9c0a00c96a6e18d887b70 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 17 Dec 2023 21:48:57 +1100 Subject: [PATCH 054/613] Rename `Handler` as `DiagCtxt`. --- src/back/lto.rs | 6 +++--- src/back/write.rs | 6 +++--- src/errors.rs | 5 +++-- src/lib.rs | 8 ++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 529454b119e86..289b93fab876a 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -30,7 +30,7 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; -use rustc_errors::{FatalError, Handler}; +use rustc_errors::{FatalError, DiagCtxt}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; @@ -61,7 +61,7 @@ struct LtoData { tmp_path: TempDir, } -fn prepare_lto(cgcx: &CodegenContext, diag_handler: &Handler) -> Result { +fn prepare_lto(cgcx: &CodegenContext, diag_handler: &DiagCtxt) -> Result { let export_threshold = match cgcx.lto { // We're just doing LTO for our one crate Lto::ThinLocal => SymbolExportLevel::Rust, @@ -192,7 +192,7 @@ pub(crate) fn run_fat( ) } -fn fat_lto(cgcx: &CodegenContext, _diag_handler: &Handler, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, +fn fat_lto(cgcx: &CodegenContext, _diag_handler: &DiagCtxt, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[*const libc::c_char], ) -> Result, FatalError> { let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); diff --git a/src/back/write.rs b/src/back/write.rs index 04772d7707abd..c2438d7ca36fd 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -4,7 +4,7 @@ use gccjit::OutputKind; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_codegen_ssa::back::link::ensure_removed; use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; -use rustc_errors::Handler; +use rustc_errors::DiagCtxt; use rustc_fs_util::link_or_copy; use rustc_session::config::OutputType; use rustc_span::fatal_error::FatalError; @@ -13,7 +13,7 @@ use rustc_target::spec::SplitDebuginfo; use crate::{GccCodegenBackend, GccContext}; use crate::errors::CopyBitcode; -pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, module: ModuleCodegen, config: &ModuleConfig) -> Result { +pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &DiagCtxt, module: ModuleCodegen, config: &ModuleConfig) -> Result { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); { let context = &module.module_llvm.context; @@ -148,7 +148,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_hand )) } -pub(crate) fn link(_cgcx: &CodegenContext, _diag_handler: &Handler, mut _modules: Vec>) -> Result, FatalError> { +pub(crate) fn link(_cgcx: &CodegenContext, _diag_handler: &DiagCtxt, mut _modules: Vec>) -> Result, FatalError> { unimplemented!(); } diff --git a/src/errors.rs b/src/errors.rs index 5fc4b12d7e699..0261d5cd59044 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,5 +1,6 @@ use rustc_errors::{ - DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, + IntoDiagnosticArg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -111,7 +112,7 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub(crate) struct MissingFeatures; impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, handler: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + fn into_diagnostic(self, handler: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { let mut diag = handler.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); if let Some(span) = self.span { diag.set_span(span); diff --git a/src/lib.rs b/src/lib.rs index 0ececc5dda0a9..cbe03f4051ed3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModul use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods}; -use rustc_errors::{ErrorGuaranteed, Handler}; +use rustc_errors::{ErrorGuaranteed, DiagCtxt}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::util::Providers; @@ -330,7 +330,7 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!() } - unsafe fn optimize(_cgcx: &CodegenContext, _diag_handler: &Handler, module: &ModuleCodegen, config: &ModuleConfig) -> Result<(), FatalError> { + unsafe fn optimize(_cgcx: &CodegenContext, _diag_handler: &DiagCtxt, module: &ModuleCodegen, config: &ModuleConfig) -> Result<(), FatalError> { module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); Ok(()) } @@ -344,7 +344,7 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!(); } - unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &Handler, module: ModuleCodegen, config: &ModuleConfig) -> Result { + unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &DiagCtxt, module: ModuleCodegen, config: &ModuleConfig) -> Result { back::write::codegen(cgcx, diag_handler, module, config) } @@ -356,7 +356,7 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!(); } - fn run_link(cgcx: &CodegenContext, diag_handler: &Handler, modules: Vec>) -> Result, FatalError> { + fn run_link(cgcx: &CodegenContext, diag_handler: &DiagCtxt, modules: Vec>) -> Result, FatalError> { back::write::link(cgcx, diag_handler, modules) } } From a5c63ae13b8e5f37bb5e58ce44fd6d3a6fb503e1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 08:43:59 +1100 Subject: [PATCH 055/613] Rename `CodegenContext::create_diag_handler` as `CodegenContext::create_dcx`. --- src/back/lto.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 289b93fab876a..ee8da7c6cb736 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -183,7 +183,7 @@ pub(crate) fn run_fat( modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> Result, FatalError> { - let diag_handler = cgcx.create_diag_handler(); + let diag_handler = cgcx.create_dcx(); let lto_data = prepare_lto(cgcx, &diag_handler)?; /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ From 5ea71c1150a7ef7a35be240c0e0d40525a94afe0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 10:15:45 +1100 Subject: [PATCH 056/613] Rename many `DiagCtxt` arguments. --- src/back/lto.rs | 20 ++++++++++---------- src/back/write.rs | 8 ++++---- src/errors.rs | 4 ++-- src/lib.rs | 10 +++++----- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index ee8da7c6cb736..c21b768682399 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -61,7 +61,7 @@ struct LtoData { tmp_path: TempDir, } -fn prepare_lto(cgcx: &CodegenContext, diag_handler: &DiagCtxt) -> Result { +fn prepare_lto(cgcx: &CodegenContext, dcx: &DiagCtxt) -> Result { let export_threshold = match cgcx.lto { // We're just doing LTO for our one crate Lto::ThinLocal => SymbolExportLevel::Rust, @@ -106,18 +106,18 @@ fn prepare_lto(cgcx: &CodegenContext, diag_handler: &DiagCtxt // Make sure we actually can run LTO for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { - diag_handler.emit_err(LtoDisallowed); + dcx.emit_err(LtoDisallowed); return Err(FatalError); } else if *crate_type == CrateType::Dylib { if !cgcx.opts.unstable_opts.dylib_lto { - diag_handler.emit_err(LtoDylib); + dcx.emit_err(LtoDylib); return Err(FatalError); } } } if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { - diag_handler.emit_err(DynamicLinkingWithLTO); + dcx.emit_err(DynamicLinkingWithLTO); return Err(FatalError); } @@ -154,7 +154,7 @@ fn prepare_lto(cgcx: &CodegenContext, diag_handler: &DiagCtxt upstream_modules.push((module, CString::new(name).unwrap())); } Err(e) => { - diag_handler.emit_err(e); + dcx.emit_err(e); return Err(FatalError); } } @@ -183,16 +183,16 @@ pub(crate) fn run_fat( modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> Result, FatalError> { - let diag_handler = cgcx.create_dcx(); - let lto_data = prepare_lto(cgcx, &diag_handler)?; + let dcx = cgcx.create_dcx(); + let lto_data = prepare_lto(cgcx, &dcx)?; /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ - fat_lto(cgcx, &diag_handler, modules, cached_modules, lto_data.upstream_modules, lto_data.tmp_path, + fat_lto(cgcx, &dcx, modules, cached_modules, lto_data.upstream_modules, lto_data.tmp_path, //&symbols_below_threshold, ) } -fn fat_lto(cgcx: &CodegenContext, _diag_handler: &DiagCtxt, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, +fn fat_lto(cgcx: &CodegenContext, _dcx: &DiagCtxt, modules: Vec>, cached_modules: Vec<(SerializedModule, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[*const libc::c_char], ) -> Result, FatalError> { let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); @@ -257,7 +257,7 @@ fn fat_lto(cgcx: &CodegenContext, _diag_handler: &DiagCtxt, m let (buffer, name) = serialized_modules.remove(0); info!("no in-memory regular modules to choose from, parsing {:?}", name); ModuleCodegen { - module_llvm: GccContext::parse(cgcx, &name, buffer.data(), diag_handler)?, + module_llvm: GccContext::parse(cgcx, &name, buffer.data(), dcx)?, name: name.into_string().unwrap(), kind: ModuleKind::Regular, }*/ diff --git a/src/back/write.rs b/src/back/write.rs index c2438d7ca36fd..2f8a54f529cc5 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -13,7 +13,7 @@ use rustc_target::spec::SplitDebuginfo; use crate::{GccCodegenBackend, GccContext}; use crate::errors::CopyBitcode; -pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &DiagCtxt, module: ModuleCodegen, config: &ModuleConfig) -> Result { +pub(crate) unsafe fn codegen(cgcx: &CodegenContext, dcx: &DiagCtxt, module: ModuleCodegen, config: &ModuleConfig) -> Result { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); { let context = &module.module_llvm.context; @@ -127,12 +127,12 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_hand EmitObj::Bitcode => { debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); if let Err(err) = link_or_copy(&bc_out, &obj_out) { - diag_handler.emit_err(CopyBitcode { err }); + dcx.emit_err(CopyBitcode { err }); } if !config.emit_bc { debug!("removing_bitcode {:?}", bc_out); - ensure_removed(diag_handler, &bc_out); + ensure_removed(dcx, &bc_out); } } @@ -148,7 +148,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_hand )) } -pub(crate) fn link(_cgcx: &CodegenContext, _diag_handler: &DiagCtxt, mut _modules: Vec>) -> Result, FatalError> { +pub(crate) fn link(_cgcx: &CodegenContext, _dcx: &DiagCtxt, mut _modules: Vec>) -> Result, FatalError> { unimplemented!(); } diff --git a/src/errors.rs b/src/errors.rs index 0261d5cd59044..766d90cf72407 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -112,8 +112,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { pub(crate) struct MissingFeatures; impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, handler: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = handler.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); + fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = dcx.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); if let Some(span) = self.span { diag.set_span(span); }; diff --git a/src/lib.rs b/src/lib.rs index cbe03f4051ed3..1f3f909d8b4f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -330,7 +330,7 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!() } - unsafe fn optimize(_cgcx: &CodegenContext, _diag_handler: &DiagCtxt, module: &ModuleCodegen, config: &ModuleConfig) -> Result<(), FatalError> { + unsafe fn optimize(_cgcx: &CodegenContext, _dcx: &DiagCtxt, module: &ModuleCodegen, config: &ModuleConfig) -> Result<(), FatalError> { module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); Ok(()) } @@ -344,8 +344,8 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!(); } - unsafe fn codegen(cgcx: &CodegenContext, diag_handler: &DiagCtxt, module: ModuleCodegen, config: &ModuleConfig) -> Result { - back::write::codegen(cgcx, diag_handler, module, config) + unsafe fn codegen(cgcx: &CodegenContext, dcx: &DiagCtxt, module: ModuleCodegen, config: &ModuleConfig) -> Result { + back::write::codegen(cgcx, dcx, module, config) } fn prepare_thin(_module: ModuleCodegen) -> (String, Self::ThinBuffer) { @@ -356,8 +356,8 @@ impl WriteBackendMethods for GccCodegenBackend { unimplemented!(); } - fn run_link(cgcx: &CodegenContext, diag_handler: &DiagCtxt, modules: Vec>) -> Result, FatalError> { - back::write::link(cgcx, diag_handler, modules) + fn run_link(cgcx: &CodegenContext, dcx: &DiagCtxt, modules: Vec>) -> Result, FatalError> { + back::write::link(cgcx, dcx, modules) } } From 472ea06999ce6ecfb78554a74b14dec9dae97f38 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 14:12:39 +1100 Subject: [PATCH 057/613] Add `level` arg to `into_diagnostic`. And make all hand-written `IntoDiagnostic` impls generic, by using `DiagnosticBuilder::new(dcx, level, ...)` instead of e.g. `dcx.struct_err(...)`. This means the `create_*` functions are the source of the error level. This change will let us remove `struct_diagnostic`. Note: `#[rustc_lint_diagnostics]` is added to `DiagnosticBuilder::new`, it's necessary to pass diagnostics tests now that it's used in `into_diagnostic` functions. --- src/errors.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 766d90cf72407..1b1ed0b411c71 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -111,9 +111,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_gcc_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); +impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_gcc_target_feature_disable_or_enable + ); if let Some(span) = self.span { diag.set_span(span); }; From a8b0e30a8b5c9b97b83bdabd700c0f6e92e0f96d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 18 Dec 2023 23:25:23 +0100 Subject: [PATCH 058/613] Error earlier if the rustc host cannot be found --- build_system/src/config.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index d948572bda567..b61c65f7b0220 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -111,7 +111,10 @@ impl ConfigInfo { Some(r) if !r.is_empty() => r.to_string(), _ => "rustc".to_string(), }; - self.host_triple = rustc_version_info(Some(&rustc))?.host.unwrap_or_default(); + self.host_triple = match rustc_version_info(Some(&rustc))?.host { + Some(host) => host, + None => return Err("no host found".to_string()), + }; if self.target_triple.is_empty() { if let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE") { @@ -216,6 +219,8 @@ impl ConfigInfo { )); let ld_library_path = format!( "{target}:{sysroot}:{gcc_path}", + // FIXME: It's possible to pick another out directory. Would be nice to have a command + // line option to change it. target = current_dir.join("target/out").display(), sysroot = sysroot.display(), ); From f516c9681133788c6ff20932e443226ffef98d5c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Dec 2023 01:07:01 +0100 Subject: [PATCH 059/613] Add comment about why `-Cpanic=abort` option is needed --- build_system/src/config.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index b61c65f7b0220..1824bdd292ffa 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -165,6 +165,8 @@ impl ConfigInfo { } _ => {} } + // This should not be needed, but is necessary for the CI in the rust repository. + // FIXME: Remove when the rust CI switches to the master version of libgccjit. rustflags.push("-Cpanic=abort".to_string()); } else { self.cg_backend_path = current_dir From bb4fd2c638fa31c0121255e8548488381ab39041 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Dec 2023 01:16:29 +0100 Subject: [PATCH 060/613] Simplify code by removing unneeded pattern matching --- build_system/src/utils.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index ebfa41c761cee..9c3a86ad68a2a 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -1,4 +1,3 @@ -use std::borrow::Cow; use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; @@ -52,18 +51,12 @@ fn check_exit_status( let stdout = String::from_utf8_lossy(&output.stdout); if !stdout.is_empty() { error.push_str("\n==== STDOUT ====\n"); - match stdout { - Cow::Owned(s) => error.push_str(&s), - Cow::Borrowed(s) => error.push_str(s), - } + error.push_str(&*stdout); } let stderr = String::from_utf8_lossy(&output.stderr); if !stderr.is_empty() { error.push_str("\n==== STDERR ====\n"); - match stderr { - Cow::Owned(s) => error.push_str(&s), - Cow::Borrowed(s) => error.push_str(s), - } + error.push_str(&*stderr); } } Err(error) From 984e045848ff28294d86471478286307942680da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Dec 2023 16:54:02 +0100 Subject: [PATCH 061/613] Show output of `--mini-tests` and `--std-tests` commands --- build_system/src/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index a926ee4c79ebd..13828e461913b 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -304,7 +304,7 @@ fn maybe_run_command_in_vm( args: &TestArg, ) -> Result<(), String> { if !args.config_info.run_in_vm { - run_command_with_env(command, None, Some(env))?; + run_command_with_output_and_env(command, None, Some(env))?; return Ok(()); } let vm_parent_dir = match env.get("CG_GCC_VM_DIR") { @@ -330,7 +330,7 @@ fn maybe_run_command_in_vm( &inside_vm_exe_path, ]; vm_command.extend_from_slice(command); - run_command_with_env(&vm_command, Some(&vm_parent_dir), Some(env))?; + run_command_with_output_and_env(&vm_command, Some(&vm_parent_dir), Some(env))?; Ok(()) } From a46066ca230a421ef40bf1136ec030cc10afab84 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Dec 2023 16:55:22 +0100 Subject: [PATCH 062/613] Remove ignored commands from gcc12 CI --- .github/workflows/gcc12.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 1a17b936c743e..a27ef913c21d6 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -28,9 +28,6 @@ jobs: # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", "--test-libcore", - "--extended-rand-tests", - "--extended-regex-example-tests", - "--extended-regex-tests", "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", ] From 6e53832eda190141516e0faeb4651eecfe3710be Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Dec 2023 21:15:28 +0100 Subject: [PATCH 063/613] Simplify `Runner` type alias --- build_system/src/test.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 13828e461913b..f368e5b420e6f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -13,7 +13,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; type Env = HashMap; -type Runner = &'static dyn Fn(&Env, &TestArg) -> Result<(), String>; +type Runner = fn(&Env, &TestArg) -> Result<(), String>; type Runners = HashMap<&'static str, (&'static str, Runner)>; fn get_runners() -> Runners { @@ -21,42 +21,42 @@ fn get_runners() -> Runners { runners.insert( "--test-rustc", - ("Run all rustc tests", &test_rustc as Runner), + ("Run all rustc tests", test_rustc as Runner), ); runners.insert( "--test-successful-rustc", - ("Run successful rustc tests", &test_successful_rustc), + ("Run successful rustc tests", test_successful_rustc), ); runners.insert( "--test-failing-rustc", - ("Run failing rustc tests", &test_failing_rustc), + ("Run failing rustc tests", test_failing_rustc), ); - runners.insert("--test-libcore", ("Run libcore tests", &test_libcore)); - runners.insert("--clean-ui-tests", ("Clean ui tests", &clean_ui_tests)); - runners.insert("--clean", ("Empty cargo target directory", &clean)); - runners.insert("--build-sysroot", ("Build sysroot", &build_sysroot)); - runners.insert("--std-tests", ("Run std tests", &std_tests)); - runners.insert("--asm-tests", ("Run asm tests", &asm_tests)); + runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); + runners.insert("--clean-ui-tests", ("Clean ui tests", clean_ui_tests)); + runners.insert("--clean", ("Empty cargo target directory", clean)); + runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); + runners.insert("--std-tests", ("Run std tests", std_tests)); + runners.insert("--asm-tests", ("Run asm tests", asm_tests)); runners.insert( "--extended-tests", - ("Run extended sysroot tests", &extended_sysroot_tests), + ("Run extended sysroot tests", extended_sysroot_tests), ); runners.insert( "--extended-rand-tests", - ("Run extended rand tests", &extended_rand_tests), + ("Run extended rand tests", extended_rand_tests), ); runners.insert( "--extended-regex-example-tests", ( "Run extended regex example tests", - &extended_regex_example_tests, + extended_regex_example_tests, ), ); runners.insert( "--extended-regex-tests", - ("Run extended regex tests", &extended_regex_tests), + ("Run extended regex tests", extended_regex_tests), ); - runners.insert("--mini-tests", ("Run mini tests", &mini_tests)); + runners.insert("--mini-tests", ("Run mini tests", mini_tests)); runners } From 8e870c75d991b06a19a6ae8af45cef39a70ffae9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Dec 2023 21:22:32 +0100 Subject: [PATCH 064/613] Remove unused `TestArgs::use_backend` and display messages in case a test is not run --- build_system/src/test.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index f368e5b420e6f..f66b16c31496e 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -97,6 +97,7 @@ fn show_usage() { ); ConfigInfo::show_usage(); for (option, (doc, _)) in get_runners() { + // FIXME: Instead of using the hard-coded `23` value, better to compute it instead. let needed_spaces = 23_usize.saturating_sub(option.len()); let spaces: String = std::iter::repeat(' ').take(needed_spaces).collect(); println!(" {}{}: {}", option, spaces, doc); @@ -109,7 +110,6 @@ struct TestArg { no_default_features: bool, build_only: bool, gcc_path: String, - use_backend: bool, runners: BTreeSet, flags: Vec, backend: Option, @@ -207,7 +207,7 @@ impl TestArg { } fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> { - if args.use_backend { + if args.backend.is_some() { return Ok(()); } let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; @@ -504,8 +504,6 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { None => return Err("Couldn't retrieve rustc commit hash".to_string()), }; run_command_with_output_and_env(&[&"git", &"checkout", &rustc_commit], rust_dir, Some(env))?; - // FIXME: Is it really needed to empty `RUSTFLAGS` here? - // env.insert("RUSTFLAGS".to_string(), String::new()); let cargo = String::from_utf8( run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout, ) @@ -684,6 +682,7 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { + println!("Not using GCC master branch. Skipping `extended_rand_tests`."); return Ok(()); } let path = Path::new("rand"); @@ -696,6 +695,7 @@ fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { + println!("Not using GCC master branch. Skipping `extended_regex_example_tests`."); return Ok(()); } let path = Path::new("regex"); @@ -750,6 +750,7 @@ fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { + println!("Not using GCC master branch. Skipping `extended_regex_tests`."); return Ok(()); } // FIXME: create a function "display_if_not_quiet" or something along the line. From 05ef68961b0375cca8ddf7e842d6dbba9d46db11 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Dec 2023 14:47:42 +0100 Subject: [PATCH 065/613] Remove unused `build_sysroot.sh` file --- build_sysroot/build_sysroot.sh | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100755 build_sysroot/build_sysroot.sh diff --git a/build_sysroot/build_sysroot.sh b/build_sysroot/build_sysroot.sh deleted file mode 100755 index ebc7dc375b125..0000000000000 --- a/build_sysroot/build_sysroot.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash - -# Requires the CHANNEL env var to be set to `debug` or `release.` - -set -e -cd $(dirname "$0") - -pushd ../ -source ./config.sh -popd - -# Cleanup for previous run -# v Clean target dir except for build scripts and incremental cache -rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true -rm Cargo.lock test_target/Cargo.lock 2>/dev/null || true -rm -r sysroot/ 2>/dev/null || true - -# Build libs -export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked" -if [[ "$1" == "--release" ]]; then - sysroot_channel='release' - RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release -else - sysroot_channel='debug' - cargo build --target $TARGET_TRIPLE -fi - -# Copy files to sysroot -mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ -cp -r target/$TARGET_TRIPLE/$sysroot_channel/deps/* sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ -# Copy the source files to the sysroot (Rust for Linux needs this). -source_dir=sysroot/lib/rustlib/src/rust -mkdir -p $source_dir -cp -r sysroot_src/library/ $source_dir From e26e074261c841508cf4114645291c92ab552be2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Dec 2023 14:58:43 +0100 Subject: [PATCH 066/613] Rustify `clean_all.sh` --- .github/workflows/ci.yml | 2 +- .github/workflows/gcc12.yml | 2 +- .github/workflows/m68k.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/stdarch.yml | 2 +- build_system/src/clean.rs | 73 +++++++++++++++++++++++++++++++++++ build_system/src/main.rs | 5 +++ build_system/src/utils.rs | 2 +- clean_all.sh | 6 --- rustup.sh | 2 +- 10 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 build_system/src/clean.rs delete mode 100755 clean_all.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b04ea1550ba2b..d14f30338b01a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,7 +103,7 @@ jobs: ./y.sh build --features master # TODO: remove --features master when it is back to the default. cargo test --features master - ./clean_all.sh + ./y.sh clean all - name: Prepare dependencies run: | diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index a27ef913c21d6..eef26f01789f1 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -86,7 +86,7 @@ jobs: ./y.sh prepare --only-libcore --libgccjit12-patches ./y.sh build --no-default-features --sysroot-panic-abort cargo test --no-default-features - ./clean_all.sh + ./y.sh clean all - name: Prepare dependencies run: | diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index ac141e0624793..a7489b10744f4 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -118,7 +118,7 @@ jobs: ./y.sh build --target-triple m68k-unknown-linux-gnu --features master # TODO: remove --features master when it is back to the default. CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test --features master - ./clean_all.sh + ./y.sh clean all - name: Prepare dependencies run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9798bc338f3d5..6dc950f88a23b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -82,7 +82,7 @@ jobs: EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot --features master # TODO: remove --features master when it is back to the default. cargo test --features master - ./clean_all.sh + ./y.sh clean all - name: Prepare dependencies run: | diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index d290f1d056288..dc670c5701c8d 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -100,7 +100,7 @@ jobs: - name: Clean if: ${{ !matrix.cargo_runner }} run: | - ./clean_all.sh + ./y.sh clean all - name: Prepare dependencies run: | diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs new file mode 100644 index 0000000000000..56cc19d255f96 --- /dev/null +++ b/build_system/src/clean.rs @@ -0,0 +1,73 @@ +use crate::utils::remove_file; + +use std::fs::remove_dir_all; + +#[derive(Default)] +struct CleanArg { + all: bool, +} + +impl CleanArg { + fn new() -> Result, String> { + let mut args = CleanArg::default(); + + // We skip the binary and the "clean" option. + for arg in std::env::args().skip(2) { + match arg.as_str() { + "all" => args.all = true, + "--help" => { + Self::usage(); + return Ok(None); + } + a => return Err(format!("Unknown argument `{}`", a)), + } + } + Ok(Some(args)) + } + + fn usage() { + println!( + r#" + `clean` command help: + + all : Clean all data + --help : Show this help + "# + ) + } +} + +fn clean_all() -> Result<(), String> { + let dirs_to_remove = [ + "target", + "build_sysroot/sysroot", + "build_sysroot/sysroot_src", + "build_sysroot/target", + "regex", + "simple-raytracer", + ]; + for dir in dirs_to_remove { + let _ = remove_dir_all(dir); + } + + let files_to_remove = ["build_sysroot/Cargo.lock", "perf.data", "perf.data.old"]; + + for file in files_to_remove { + let _ = remove_file(file); + } + + println!("Successfully ran `clean all`"); + Ok(()) +} + +pub fn run() -> Result<(), String> { + let args = match CleanArg::new()? { + Some(a) => a, + None => return Ok(()), + }; + + if args.all { + clean_all()?; + } + Ok(()) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs index e0091ff697733..1ed44b22a9538 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -2,6 +2,7 @@ use std::env; use std::process; mod build; +mod clean; mod config; mod prepare; mod rustc_info; @@ -22,6 +23,7 @@ fn usage() { "\ Available commands for build_system: + clean : Run clean command prepare : Run prepare command build : Run build command test : Run test command @@ -30,6 +32,7 @@ Available commands for build_system: } pub enum Command { + Clean, Prepare, Build, Test, @@ -41,6 +44,7 @@ fn main() { } let command = match env::args().nth(1).as_deref() { + Some("clean") => Command::Clean, Some("prepare") => Command::Prepare, Some("build") => Command::Build, Some("test") => Command::Test, @@ -57,6 +61,7 @@ fn main() { }; if let Err(e) = match command { + Command::Clean => clean::run(), Command::Prepare => prepare::run(), Command::Build => build::run(), Command::Test => test::run(), diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 9c3a86ad68a2a..276f4f2d989b2 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -346,7 +346,7 @@ pub fn split_args(args: &str) -> Result, String> { Ok(out) } -pub fn remove_file>(file_path: &P) -> Result<(), String> { +pub fn remove_file + ?Sized>(file_path: &P) -> Result<(), String> { std::fs::remove_file(file_path).map_err(|error| { format!( "Failed to remove `{}`: {:?}", diff --git a/clean_all.sh b/clean_all.sh deleted file mode 100755 index 782bd3e5058c4..0000000000000 --- a/clean_all.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -e -set -v - -rm -rf target/ build_sysroot/{sysroot/,sysroot_src/,target/,Cargo.lock} perf.data{,.old} -rm -rf regex/ simple-raytracer/ diff --git a/rustup.sh b/rustup.sh index a4f938e4b5b76..3cdc07ca5207a 100755 --- a/rustup.sh +++ b/rustup.sh @@ -15,7 +15,7 @@ case $1 in rustup toolchain uninstall $nightly done - ./clean_all.sh + ./y.sh clean all ./y.sh prepare ;; "commit") From 9a8245fed83d55a5bdcd72cf126107a11cc676e1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Dec 2023 16:19:03 +0100 Subject: [PATCH 067/613] Remove unused `rustup.sh` script --- rustup.sh | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100755 rustup.sh diff --git a/rustup.sh b/rustup.sh deleted file mode 100755 index 3cdc07ca5207a..0000000000000 --- a/rustup.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -set -e - -case $1 in - "prepare") - TOOLCHAIN=$(date +%Y-%m-%d) - - echo "=> Installing new nightly" - rustup toolchain install --profile minimal nightly-${TOOLCHAIN} # Sanity check to see if the nightly exists - echo nightly-${TOOLCHAIN} > rust-toolchain - - echo "=> Uninstalling all old nightlies" - for nightly in $(rustup toolchain list | grep nightly | grep -v $TOOLCHAIN | grep -v nightly-x86_64); do - rustup toolchain uninstall $nightly - done - - ./y.sh clean all - ./y.sh prepare - ;; - "commit") - git add rust-toolchain - git commit -m "Rustup to $(rustc -V)" - ;; - *) - echo "Unknown command '$1'" - echo "Usage: ./rustup.sh prepare|commit" - ;; -esac From 87a704a2278882d4d8717e83c62879dc540ad87d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Dec 2023 21:33:21 +0100 Subject: [PATCH 068/613] If the rustc commit cannot be retrieve, just checkout the repository --- build_system/src/test.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index f66b16c31496e..c98be8dcaccdb 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -503,7 +503,15 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { Some(commit_hash) => commit_hash, None => return Err("Couldn't retrieve rustc commit hash".to_string()), }; - run_command_with_output_and_env(&[&"git", &"checkout", &rustc_commit], rust_dir, Some(env))?; + if rustc_commit != "unknown" { + run_command_with_output_and_env( + &[&"git", &"checkout", &rustc_commit], + rust_dir, + Some(env), + )?; + } else { + run_command_with_output_and_env(&[&"git", &"checkout"], rust_dir, Some(env))?; + } let cargo = String::from_utf8( run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout, ) From 6631dd9dd27b63bf89d3ace5dbce02ea240c5a44 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 20 Dec 2023 21:44:12 +0100 Subject: [PATCH 069/613] Don't stop test if llvm FileCheck cannot be found --- build_system/src/test.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index c98be8dcaccdb..1a9bb4ea94eb8 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -524,23 +524,25 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { Ok(cargo) } })?; - let llvm_filecheck = String::from_utf8( - run_command_with_env( - &[ - &"bash", - &"-c", - &"which FileCheck-10 || \ + let llvm_filecheck = match run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ which FileCheck-11 || \ which FileCheck-12 || \ which FileCheck-13 || \ which FileCheck-14", - ], - rust_dir, - Some(env), - )? - .stdout, - ) - .map_err(|error| format!("Failed to retrieve LLVM FileCheck: {:?}", error))?; + ], + rust_dir, + Some(env), + ) { + Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(), + Err(_) => { + eprintln!("Failed to retrieve LLVM FileCheck, ignoring..."); + String::new() + } + }; std::fs::write( "rust/config.toml", &format!( From a53495ab45a1d7773561431eb2fb753aee102d44 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 21 Dec 2023 11:18:11 -0500 Subject: [PATCH 070/613] Add comment --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 8c7bae0c8866d..5f8d00bb455e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ * TODO(antoyo): support LTO (gcc's equivalent to Full LTO is -flto -flto-partition=one — https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html). * For Thin LTO, this might be helpful: * In gcc 4.6 -fwhopr was removed and became default with -flto. The non-whopr path can still be executed via -flto-partition=none. + * Or the new incremental LTO? * * Maybe some missing optizations enabled by rustc's LTO is in there: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html * Like -fipa-icf (should be already enabled) and maybe -fdevirtualize-at-ltrans. @@ -29,6 +30,7 @@ #![warn(unused_lifetimes)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +#![deny(clippy::pattern_type_mismatch)] extern crate rustc_apfloat; extern crate rustc_ast; From 2e52b08800d5213e6cc7d75559f62584e8e0eede Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 21 Dec 2023 23:46:41 +0100 Subject: [PATCH 071/613] Rustify `cargo.sh` --- .github/workflows/stdarch.yml | 4 +- Readme.md | 10 ++-- build_system/src/cargo.rs | 98 +++++++++++++++++++++++++++++++++++ build_system/src/main.rs | 5 ++ build_system/src/test.rs | 2 +- build_system/src/utils.rs | 27 ++++++++-- cargo.sh | 23 -------- 7 files changed, 135 insertions(+), 34 deletions(-) create mode 100644 build_system/src/cargo.rs delete mode 100755 cargo.sh diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index dc670c5701c8d..d8336fe991b63 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -126,11 +126,11 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ - CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test + CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../y.sh cargo test - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a + STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../y.sh cargo test -- --skip rtm --skip tbm --skip sse4a diff --git a/Readme.md b/Readme.md index 68effb2bf78f9..f31b5c17969e3 100644 --- a/Readme.md +++ b/Readme.md @@ -79,7 +79,7 @@ export CG_GCCJIT_DIR=[the full path to rustc_codegen_gcc] ### Cargo ```bash -$ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run +$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run ``` If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. @@ -230,13 +230,13 @@ Run do the command with `-v -save-temps` and then extract the `lto1` line from t ### How to send arguments to the GCC linker ``` -CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../cargo.sh build +CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../y.sh cargo build ``` ### How to see the personality functions in the asm dump ``` -CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../cargo.sh build +CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../y.sh cargo build ``` ### How to see the LLVM IR for a sysroot crate @@ -324,13 +324,13 @@ generate it in [gimple.md](./doc/gimple.md). * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. * Set the path to the cross-compiling libgccjit in `gcc_path`. * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`. - * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`. + * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`. If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler). Then, you can use it the following way: * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json` - * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`. + * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`. If you get the following error: diff --git a/build_system/src/cargo.rs b/build_system/src/cargo.rs new file mode 100644 index 0000000000000..06b543a6cad65 --- /dev/null +++ b/build_system/src/cargo.rs @@ -0,0 +1,98 @@ +use crate::config::ConfigInfo; +use crate::utils::{ + get_toolchain, run_command_with_output_and_env, rustc_toolchain_version_info, + rustc_version_info, +}; + +use std::collections::HashMap; +use std::ffi::OsStr; + +fn args() -> Result>, String> { + // We skip the binary and the "cargo" option. + if let Some("--help") = std::env::args().skip(2).next().as_deref() { + usage(); + return Ok(None); + } + let args = std::env::args().skip(2).collect::>(); + if args.is_empty() { + return Err( + "Expected at least one argument for `cargo` subcommand, found none".to_string(), + ); + } + Ok(Some(args)) +} + +fn usage() { + println!( + r#" +`cargo` command help: + + [args] : Arguments to be passed to the cargo command + --help : Show this help +"# + ) +} + +pub fn run() -> Result<(), String> { + let args = match args()? { + Some(a) => a, + None => return Ok(()), + }; + + // We first need to go to the original location to ensure that the config setup will go as + // expected. + let current_dir = std::env::current_dir() + .map_err(|error| format!("Failed to get current directory path: {:?}", error))?; + let current_exe = std::env::current_exe() + .map_err(|error| format!("Failed to get current exe path: {:?}", error))?; + let parent_dir = match current_exe.parent() { + Some(parent) => parent, + None => { + return Err(format!( + "Cannot get parent of current executable path `{}`", + current_exe.display() + )); + } + }; + std::env::set_current_dir(&parent_dir).map_err(|error| { + format!( + "Failed to go to `{}` folder: {:?}", + parent_dir.display(), + error + ) + })?; + + let mut env: HashMap = std::env::vars().collect(); + ConfigInfo::default().setup(&mut env, None)?; + let toolchain = get_toolchain()?; + + let toolchain_version = rustc_toolchain_version_info(&toolchain)?; + let default_version = rustc_version_info(None)?; + if toolchain_version != default_version { + println!( + "rustc_codegen_gcc is built for {} but the default rustc version is {}.", + toolchain_version.short, default_version.short, + ); + println!("Using {}.", toolchain_version.short); + } + + // We go back to the original folder since we now have set up everything we needed. + std::env::set_current_dir(¤t_dir).map_err(|error| { + format!( + "Failed to go back to `{}` folder: {:?}", + current_dir.display(), + error + ) + })?; + + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert("RUSTDOCFLAGS".to_string(), rustflags); + let toolchain = format!("+{}", toolchain); + let mut command: Vec<&dyn AsRef> = vec![&"cargo", &toolchain]; + for arg in &args { + command.push(arg); + } + run_command_with_output_and_env(&command, None, Some(&env))?; + + Ok(()) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 1ed44b22a9538..102c5486a75e4 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -2,6 +2,7 @@ use std::env; use std::process; mod build; +mod cargo; mod clean; mod config; mod prepare; @@ -23,6 +24,7 @@ fn usage() { "\ Available commands for build_system: + cargo : Run cargo command clean : Run clean command prepare : Run prepare command build : Run build command @@ -32,6 +34,7 @@ Available commands for build_system: } pub enum Command { + Cargo, Clean, Prepare, Build, @@ -44,6 +47,7 @@ fn main() { } let command = match env::args().nth(1).as_deref() { + Some("cargo") => Command::Cargo, Some("clean") => Command::Clean, Some("prepare") => Command::Prepare, Some("build") => Command::Build, @@ -61,6 +65,7 @@ fn main() { }; if let Err(e) = match command { + Command::Cargo => cargo::run(), Command::Clean => clean::run(), Command::Prepare => prepare::run(), Command::Build => build::run(), diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1a9bb4ea94eb8..1577cbf2b53ed 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -796,7 +796,7 @@ fn extended_sysroot_tests(env: &Env, args: &TestArg) -> Result<(), String> { // echo "[BENCH COMPILE] ebobby/simple-raytracer" // hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \ // "RUSTC=rustc RUSTFLAGS='' cargo build" \ - // "../cargo.sh build" + // "../y.sh cargo build" // echo "[BENCH RUN] ebobby/simple-raytracer" // cp ./target/debug/main ./raytracer_cg_gcc diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 276f4f2d989b2..fdd8bd8f4c4d7 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -158,21 +158,42 @@ pub fn get_os_name() -> Result { } } -#[derive(Default)] +#[derive(Default, PartialEq)] pub struct RustcVersionInfo { + pub short: String, pub version: String, pub host: Option, pub commit_hash: Option, pub commit_date: Option, } +pub fn rustc_toolchain_version_info(toolchain: &str) -> Result { + rustc_version_info_inner(None, Some(toolchain)) +} + pub fn rustc_version_info(rustc: Option<&str>) -> Result { - let output = run_command(&[&rustc.unwrap_or("rustc"), &"-vV"], None)?; + rustc_version_info_inner(rustc, None) +} + +fn rustc_version_info_inner( + rustc: Option<&str>, + toolchain: Option<&str>, +) -> Result { + let output = if let Some(toolchain) = toolchain { + run_command(&[&rustc.unwrap_or("rustc"), &toolchain, &"-vV"], None) + } else { + run_command(&[&rustc.unwrap_or("rustc"), &"-vV"], None) + }?; let content = std::str::from_utf8(&output.stdout).unwrap_or(""); let mut info = RustcVersionInfo::default(); + let mut lines = content.split('\n'); + info.short = match lines.next() { + Some(s) => s.to_string(), + None => return Err("failed to retrieve rustc version".to_string()), + }; - for line in content.split('\n').map(|line| line.trim()) { + for line in lines.map(|line| line.trim()) { match line.split_once(':') { Some(("host", data)) => info.host = Some(data.trim().to_string()), Some(("release", data)) => info.version = data.trim().to_string(), diff --git a/cargo.sh b/cargo.sh deleted file mode 100755 index b68a08ee88f80..0000000000000 --- a/cargo.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -if [ -z $CHANNEL ]; then -export CHANNEL='debug' -fi - -pushd $(dirname "$0") >/dev/null -source config.sh - -# read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/') - -popd >/dev/null - -if [[ $(${RUSTC} -V) != $(${RUSTC} +${TOOLCHAIN} -V) ]]; then - echo "rustc_codegen_gcc is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)." - echo "Using $(rustc +${TOOLCHAIN} -V)." -fi - -cmd=$1 -shift - -RUSTDOCFLAGS="$RUSTFLAGS" cargo +${TOOLCHAIN} $cmd $@ From ec940748175eca4e476ed29fa537319eb090356a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 22 Dec 2023 00:47:01 +0100 Subject: [PATCH 072/613] Correctly take into account potential position of cargo command in `y.sh` --- build_system/src/cargo.rs | 26 ++++++++++++++++++++------ y.sh | 6 +++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/build_system/src/cargo.rs b/build_system/src/cargo.rs index 06b543a6cad65..5f9de5e2eb658 100644 --- a/build_system/src/cargo.rs +++ b/build_system/src/cargo.rs @@ -6,6 +6,7 @@ use crate::utils::{ use std::collections::HashMap; use std::ffi::OsStr; +use std::path::PathBuf; fn args() -> Result>, String> { // We skip the binary and the "cargo" option. @@ -42,18 +43,31 @@ pub fn run() -> Result<(), String> { // We first need to go to the original location to ensure that the config setup will go as // expected. let current_dir = std::env::current_dir() + .and_then(|path| path.canonicalize()) .map_err(|error| format!("Failed to get current directory path: {:?}", error))?; let current_exe = std::env::current_exe() + .and_then(|path| path.canonicalize()) .map_err(|error| format!("Failed to get current exe path: {:?}", error))?; - let parent_dir = match current_exe.parent() { - Some(parent) => parent, - None => { + let mut parent_dir = current_exe + .components() + .map(|comp| comp.as_os_str()) + .collect::>(); + // We run this script from "build_system/target/release/y", so we need to remove these elements. + for to_remove in &["y", "release", "target", "build_system"] { + if parent_dir + .last() + .map(|part| part == to_remove) + .unwrap_or(false) + { + parent_dir.pop(); + } else { return Err(format!( - "Cannot get parent of current executable path `{}`", - current_exe.display() + "Build script not executed from `build_system/target/release/y` (in path {})", + current_exe.display(), )); } - }; + } + let parent_dir = PathBuf::from(parent_dir.join(&OsStr::new("/"))); std::env::set_current_dir(&parent_dir).map_err(|error| { format!( "Failed to go to `{}` folder: {:?}", diff --git a/y.sh b/y.sh index 188109743e3db..69d7917dd7779 100755 --- a/y.sh +++ b/y.sh @@ -2,7 +2,7 @@ set -e echo "[BUILD] build system" 1>&2 -cd build_system +pushd $(dirname "$0")/build_system > /dev/null cargo build --release -cd .. -./build_system/target/release/y $@ +popd > /dev/null +$(dirname "$0")/build_system/target/release/y $@ From 02ed79063171e4214d4139e651b477487c517108 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 22:21:37 +1100 Subject: [PATCH 073/613] Remove `Session` methods that duplicate `DiagCtxt` methods. Also add some `dcx` methods to types that wrap `TyCtxt`, for easier access. --- src/asm.rs | 2 +- src/attributes.rs | 2 +- src/consts.rs | 2 +- src/context.rs | 6 +++--- src/gcc_util.rs | 6 +++--- src/intrinsic/mod.rs | 2 +- src/intrinsic/simd.rs | 4 ++-- src/lib.rs | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index f3a9ca77a67b1..ddd67a994c942 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -109,7 +109,7 @@ enum ConstraintOrRegister { impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { if options.contains(InlineAsmOptions::MAY_UNWIND) { - self.sess() + self.sess().dcx() .create_err(UnwindingInlineAsm { span: span[0] }) .emit(); return; diff --git a/src/attributes.rs b/src/attributes.rs index 6159971cfaa8d..9f361d3688695 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -80,7 +80,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>( let span = cx.tcx .get_attr(instance.def_id(), sym::target_feature) .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); - cx.tcx.sess.create_err(TiedTargetFeatures { + cx.tcx.dcx().create_err(TiedTargetFeatures { features: features.join(", "), span, }) diff --git a/src/consts.rs b/src/consts.rs index f06416b9bb5fe..70d8db02247ce 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -24,7 +24,7 @@ fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc> match Align::from_bits(min) { Ok(min) => align = align.max(min), Err(err) => { - cx.sess().emit_err(InvalidMinimumAlignment { err: err.to_string() }); + cx.sess().dcx().emit_err(InvalidMinimumAlignment { err: err.to_string() }); } } } diff --git a/src/context.rs b/src/context.rs index ab9c703db37da..053f759329fb1 100644 --- a/src/context.rs +++ b/src/context.rs @@ -500,9 +500,9 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { #[inline] fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err { - self.sess().emit_fatal(respan(span, err.into_diagnostic())) + self.tcx.dcx().emit_fatal(respan(span, err.into_diagnostic())) } else { - self.tcx.sess.emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err }) + self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err }) } } } @@ -518,7 +518,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.sess().emit_fatal(respan(span, err)) + self.tcx.dcx().emit_fatal(respan(span, err)) } else { match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 2aa84f26797c3..df917d527ced8 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -52,7 +52,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec c, Some(_) => { if diagnostics { - sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s }); + sess.dcx().emit_warning(UnknownCTargetFeaturePrefix { feature: s }); } return None; } @@ -79,7 +79,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { _ => bug!(), }, None => { - tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); + tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); return; } } diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 85d3e7234a0e6..9fa978cd2ef7a 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -34,7 +34,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // macros for error handling: macro_rules! return_error { ($err:expr) => {{ - bx.sess().emit_err($err); + bx.tcx.dcx().emit_err($err); return Err(()); }}; } @@ -390,7 +390,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ) -> Result, ()> { macro_rules! return_error { ($err:expr) => {{ - bx.sess().emit_err($err); + bx.tcx.dcx().emit_err($err); return Err(()); }}; } diff --git a/src/lib.rs b/src/lib.rs index 1f3f909d8b4f0..f69f850c1d4a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -191,7 +191,7 @@ impl CodegenBackend for GccCodegenBackend { #[cfg(feature="master")] gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); if sess.lto() == Lto::Thin { - sess.emit_warning(LTONotSupported {}); + sess.dcx().emit_warning(LTONotSupported {}); } #[cfg(not(feature="master"))] From 69b5a9f2eb8b7d16091b76a2a5b84cd4889eefe2 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Thu, 30 Nov 2023 14:54:27 +0100 Subject: [PATCH 074/613] Change `rustc_codegen_ssa`'s `atomic_cmpxchg` interface to return a pair of values --- src/builder.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index b8a8c144dc90b..42e61b3ccb5ad 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1296,7 +1296,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } // Atomic Operations - fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> { + fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> (RValue<'gcc>, RValue<'gcc>) { let expected = self.current_func().new_local(None, cmp.get_type(), "expected"); self.llbb().add_assignment(None, expected, cmp); // NOTE: gcc doesn't support a failure memory model that is stronger than the success @@ -1310,20 +1310,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }; let success = self.compare_exchange(dst, expected, src, order, failure_order, weak); - let pair_type = self.cx.type_struct(&[src.get_type(), self.bool_type], false); - let result = self.current_func().new_local(None, pair_type, "atomic_cmpxchg_result"); - let align = Align::from_bits(64).expect("align"); // TODO(antoyo): use good align. + // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before + // expected so that we store expected after the call. + let success_var = self.current_func().new_local(None, self.bool_type, "success"); + self.llbb().add_assignment(None, success_var, success); - let value_type = result.to_rvalue().get_type(); - if let Some(struct_type) = value_type.is_struct() { - self.store(success, result.access_field(None, struct_type.get_field(1)).get_address(None), align); - // NOTE: since success contains the call to the intrinsic, it must be stored before - // expected so that we store expected after the call. - self.store(expected.to_rvalue(), result.access_field(None, struct_type.get_field(0)).get_address(None), align); - } - // TODO(antoyo): handle when value is not a struct. - - result.to_rvalue() + (expected.to_rvalue(), success_var.to_rvalue()) } fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> { From eca05c6cb06ca059bf13bd7f2b53066d217edaa2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Dec 2023 01:52:10 +0000 Subject: [PATCH 075/613] Remove movability from TyKind::Coroutine --- src/type_of.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type_of.rs b/src/type_of.rs index 479a814788a54..e5c0b2de4ca46 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -98,7 +98,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _, _), &Variants::Single { index }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); From c122376493e40dd494dac45614205c340141f005 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 29 Dec 2023 21:27:36 +0100 Subject: [PATCH 076/613] Don't show `cargo` command errors --- build_system/src/cargo.rs | 6 ++++-- build_system/src/utils.rs | 25 +++++++++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/build_system/src/cargo.rs b/build_system/src/cargo.rs index 5f9de5e2eb658..67b301d9aa646 100644 --- a/build_system/src/cargo.rs +++ b/build_system/src/cargo.rs @@ -1,6 +1,6 @@ use crate::config::ConfigInfo; use crate::utils::{ - get_toolchain, run_command_with_output_and_env, rustc_toolchain_version_info, + get_toolchain, run_command_with_output_and_env_no_err, rustc_toolchain_version_info, rustc_version_info, }; @@ -106,7 +106,9 @@ pub fn run() -> Result<(), String> { for arg in &args { command.push(arg); } - run_command_with_output_and_env(&command, None, Some(&env))?; + if run_command_with_output_and_env_no_err(&command, None, Some(&env)).is_err() { + std::process::exit(1); + } Ok(()) } diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index fdd8bd8f4c4d7..f0a07b597a0f4 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -30,6 +30,7 @@ fn check_exit_status( cwd: Option<&Path>, exit_status: ExitStatus, output: Option<&Output>, + show_err: bool, ) -> Result<(), String> { if exit_status.success() { return Ok(()); @@ -46,7 +47,9 @@ fn check_exit_status( exit_status.code() ); let input = input.iter().map(|i| i.as_ref()).collect::>(); - eprintln!("Command `{:?}` failed", input); + if show_err { + eprintln!("Command `{:?}` failed", input); + } if let Some(output) = output { let stdout = String::from_utf8_lossy(&output.stdout); if !stdout.is_empty() { @@ -88,7 +91,7 @@ pub fn run_command_with_env( let output = get_command_inner(input, cwd, env) .output() .map_err(|e| command_error(input, &cwd, e))?; - check_exit_status(input, cwd, output.status, Some(&output))?; + check_exit_status(input, cwd, output.status, Some(&output), true)?; Ok(output) } @@ -101,7 +104,7 @@ pub fn run_command_with_output( .map_err(|e| command_error(input, &cwd, e))? .wait() .map_err(|e| command_error(input, &cwd, e))?; - check_exit_status(input, cwd, exit_status, None)?; + check_exit_status(input, cwd, exit_status, None, true)?; Ok(()) } @@ -115,7 +118,21 @@ pub fn run_command_with_output_and_env( .map_err(|e| command_error(input, &cwd, e))? .wait() .map_err(|e| command_error(input, &cwd, e))?; - check_exit_status(input, cwd, exit_status, None)?; + check_exit_status(input, cwd, exit_status, None, true)?; + Ok(()) +} + +pub fn run_command_with_output_and_env_no_err( + input: &[&dyn AsRef], + cwd: Option<&Path>, + env: Option<&HashMap>, +) -> Result<(), String> { + let exit_status = get_command_inner(input, cwd, env) + .spawn() + .map_err(|e| command_error(input, &cwd, e))? + .wait() + .map_err(|e| command_error(input, &cwd, e))?; + check_exit_status(input, cwd, exit_status, None, false)?; Ok(()) } From a56eff2b4152a9846027f03c6bab35a653f958c4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 24 Dec 2023 09:08:41 +1100 Subject: [PATCH 077/613] Rename some `Diagnostic` setters. `Diagnostic` has 40 methods that return `&mut Self` and could be considered setters. Four of them have a `set_` prefix. This doesn't seem necessary for a type that implements the builder pattern. This commit removes the `set_` prefixes on those four methods. --- src/errors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 1b1ed0b411c71..e9283b1989453 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -119,12 +119,12 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl fluent::codegen_gcc_target_feature_disable_or_enable ); if let Some(span) = self.span { - diag.set_span(span); + diag.span(span); }; if let Some(missing_features) = self.missing_features { diag.subdiagnostic(missing_features); } - diag.set_arg("features", self.features.join(", ")); + diag.arg("features", self.features.join(", ")); diag } } From f93e985664ad56be1286b9cbe3a14cfe499be239 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 3 Jan 2024 18:00:37 +0900 Subject: [PATCH 078/613] Support reg_addr register class in s390x inline assembly --- src/asm.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/asm.rs b/src/asm.rs index ddd67a994c942..78e8e32b97299 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -634,6 +634,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Err => unreachable!(), } @@ -704,7 +705,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") }, - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::S390x( + S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr + ) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::Err => unreachable!(), } From b5681ca4aa818e10debd99020327af9c01c43ed2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 3 Jan 2024 15:27:19 +0100 Subject: [PATCH 079/613] Update intrinsics conversion --- src/intrinsic/archs.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 15d67385c3e98..c4ae1751fa05a 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -151,8 +151,10 @@ match name { "llvm.amdgcn.msad.u8" => "__builtin_amdgcn_msad_u8", "llvm.amdgcn.perm" => "__builtin_amdgcn_perm", "llvm.amdgcn.permlane16" => "__builtin_amdgcn_permlane16", + "llvm.amdgcn.permlane16.var" => "__builtin_amdgcn_permlane16_var", "llvm.amdgcn.permlane64" => "__builtin_amdgcn_permlane64", "llvm.amdgcn.permlanex16" => "__builtin_amdgcn_permlanex16", + "llvm.amdgcn.permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "llvm.amdgcn.qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "llvm.amdgcn.queue.ptr" => "__builtin_amdgcn_queue_ptr", "llvm.amdgcn.rcp.legacy" => "__builtin_amdgcn_rcp_legacy", @@ -160,11 +162,20 @@ match name { "llvm.amdgcn.readlane" => "__builtin_amdgcn_readlane", "llvm.amdgcn.rsq.legacy" => "__builtin_amdgcn_rsq_legacy", "llvm.amdgcn.s.barrier" => "__builtin_amdgcn_s_barrier", + "llvm.amdgcn.s.barrier.init" => "__builtin_amdgcn_s_barrier_init", + "llvm.amdgcn.s.barrier.join" => "__builtin_amdgcn_s_barrier_join", + "llvm.amdgcn.s.barrier.leave" => "__builtin_amdgcn_s_barrier_leave", + "llvm.amdgcn.s.barrier.signal" => "__builtin_amdgcn_s_barrier_signal", + "llvm.amdgcn.s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst", + "llvm.amdgcn.s.barrier.signal.isfirst.var" => "__builtin_amdgcn_s_barrier_signal_isfirst_var", + "llvm.amdgcn.s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var", + "llvm.amdgcn.s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait", "llvm.amdgcn.s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv", "llvm.amdgcn.s.dcache.inv.vol" => "__builtin_amdgcn_s_dcache_inv_vol", "llvm.amdgcn.s.dcache.wb" => "__builtin_amdgcn_s_dcache_wb", "llvm.amdgcn.s.dcache.wb.vol" => "__builtin_amdgcn_s_dcache_wb_vol", "llvm.amdgcn.s.decperflevel" => "__builtin_amdgcn_s_decperflevel", + "llvm.amdgcn.s.get.barrier.state" => "__builtin_amdgcn_s_get_barrier_state", "llvm.amdgcn.s.get.waveid.in.workgroup" => "__builtin_amdgcn_s_get_waveid_in_workgroup", "llvm.amdgcn.s.getpc" => "__builtin_amdgcn_s_getpc", "llvm.amdgcn.s.getreg" => "__builtin_amdgcn_s_getreg", @@ -176,8 +187,10 @@ match name { "llvm.amdgcn.s.setprio" => "__builtin_amdgcn_s_setprio", "llvm.amdgcn.s.setreg" => "__builtin_amdgcn_s_setreg", "llvm.amdgcn.s.sleep" => "__builtin_amdgcn_s_sleep", + "llvm.amdgcn.s.sleep.var" => "__builtin_amdgcn_s_sleep_var", "llvm.amdgcn.s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "llvm.amdgcn.s.waitcnt" => "__builtin_amdgcn_s_waitcnt", + "llvm.amdgcn.s.wakeup.barrier" => "__builtin_amdgcn_s_wakeup_barrier", "llvm.amdgcn.sad.hi.u8" => "__builtin_amdgcn_sad_hi_u8", "llvm.amdgcn.sad.u16" => "__builtin_amdgcn_sad_u16", "llvm.amdgcn.sad.u8" => "__builtin_amdgcn_sad_u8", @@ -314,6 +327,8 @@ match name { // bpf "llvm.bpf.btf.type.id" => "__builtin_bpf_btf_type_id", "llvm.bpf.compare" => "__builtin_bpf_compare", + "llvm.bpf.getelementptr.and.load" => "__builtin_bpf_getelementptr_and_load", + "llvm.bpf.getelementptr.and.store" => "__builtin_bpf_getelementptr_and_store", "llvm.bpf.load.byte" => "__builtin_bpf_load_byte", "llvm.bpf.load.half" => "__builtin_bpf_load_half", "llvm.bpf.load.word" => "__builtin_bpf_load_word", @@ -5776,14 +5791,6 @@ match name { "llvm.s390.verimf" => "__builtin_s390_verimf", "llvm.s390.verimg" => "__builtin_s390_verimg", "llvm.s390.verimh" => "__builtin_s390_verimh", - "llvm.s390.verllb" => "__builtin_s390_verllb", - "llvm.s390.verllf" => "__builtin_s390_verllf", - "llvm.s390.verllg" => "__builtin_s390_verllg", - "llvm.s390.verllh" => "__builtin_s390_verllh", - "llvm.s390.verllvb" => "__builtin_s390_verllvb", - "llvm.s390.verllvf" => "__builtin_s390_verllvf", - "llvm.s390.verllvg" => "__builtin_s390_verllvg", - "llvm.s390.verllvh" => "__builtin_s390_verllvh", "llvm.s390.vfaeb" => "__builtin_s390_vfaeb", "llvm.s390.vfaef" => "__builtin_s390_vfaef", "llvm.s390.vfaeh" => "__builtin_s390_vfaeh", @@ -5815,7 +5822,7 @@ match name { "llvm.s390.vistrh" => "__builtin_s390_vistrh", "llvm.s390.vlbb" => "__builtin_s390_vlbb", "llvm.s390.vll" => "__builtin_s390_vll", - "llvm.s390.vlrl" => "__builtin_s390_vlrl", + "llvm.s390.vlrl" => "__builtin_s390_vlrlr", "llvm.s390.vmaeb" => "__builtin_s390_vmaeb", "llvm.s390.vmaef" => "__builtin_s390_vmaef", "llvm.s390.vmaeh" => "__builtin_s390_vmaeh", @@ -5885,7 +5892,7 @@ match name { "llvm.s390.vstrczb" => "__builtin_s390_vstrczb", "llvm.s390.vstrczf" => "__builtin_s390_vstrczf", "llvm.s390.vstrczh" => "__builtin_s390_vstrczh", - "llvm.s390.vstrl" => "__builtin_s390_vstrl", + "llvm.s390.vstrl" => "__builtin_s390_vstrlr", "llvm.s390.vsumb" => "__builtin_s390_vsumb", "llvm.s390.vsumgf" => "__builtin_s390_vsumgf", "llvm.s390.vsumgh" => "__builtin_s390_vsumgh", From 47b06069b3e63df4d850479084d5543b24a92302 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 22 Dec 2023 15:12:01 +0300 Subject: [PATCH 080/613] Update test for `E0796` and `static_mut_ref` lint --- example/mini_core_hello_world.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 40a1ad22c0e13..9827e299f2a31 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -98,6 +98,9 @@ fn start( } static mut NUM: u8 = 6 * 7; + +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint +#[allow(static_mut_ref)] static NUM_REF: &'static u8 = unsafe { &NUM }; macro_rules! assert { From b10f5dd3b9f33093030bda58b470d727128fa3ea Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:52:52 +0800 Subject: [PATCH 081/613] Fix typo Readme.md --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index f31b5c17969e3..39ff41acf84ae 100644 --- a/Readme.md +++ b/Readme.md @@ -181,7 +181,7 @@ debug_tree(expr); (defined in print-tree.h) -To print a debug reprensentation of a gimple struct: +To print a debug representation of a gimple struct: ```c debug_gimple_stmt(gimple_struct) From 4e8627cf8982e16c000f5b36e0cf505337ce467f Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:53:00 +0800 Subject: [PATCH 082/613] Fix typo src/base.rs --- src/base.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base.rs b/src/base.rs index b0788718da4d1..773e234150d1b 100644 --- a/src/base.rs +++ b/src/base.rs @@ -164,7 +164,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock context.add_driver_option("-v"); } - // NOTE: The codegen generates unrechable blocks. + // NOTE: The codegen generates unreachable blocks. context.set_allow_unreachable_blocks(true); { From f8e079a1714c43d81b96bfa2af67833eeec6eae6 Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:53:11 +0800 Subject: [PATCH 083/613] Fix typo src/intrinsic/llvm.rs --- src/intrinsic/llvm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 35eb4a11005b9..0d2ce20c654cf 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -262,7 +262,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc }, // NOTE: the LLVM intrinsic receives 3 floats, but the GCC builtin requires 3 vectors. // FIXME: the intrinsics like _mm_mask_fmadd_sd should probably directly call the GCC - // instrinsic to avoid this. + // intrinsic to avoid this. "__builtin_ia32_vfmaddss3_round" => { let new_args = args.to_vec(); let arg1_type = gcc_func.get_param_type(0); From 558d051b1d956dc9db8fd7c437f2a624fd86e751 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jan 2024 11:28:14 +1100 Subject: [PATCH 084/613] Rename `{create,emit}_warning` as `{create,emit}_warn`. For consistency with `warn`/`struct_warn`, and also `{create,emit}_err`, all of which use an abbreviated form. --- src/gcc_util.rs | 4 ++-- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index df917d527ced8..4babe5bfb813f 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -52,7 +52,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec c, Some(_) => { if diagnostics { - sess.dcx().emit_warning(UnknownCTargetFeaturePrefix { feature: s }); + sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature: s }); } return None; } @@ -79,7 +79,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Date: Thu, 11 Jan 2024 17:41:37 -0500 Subject: [PATCH 085/613] Fix the destination path of the sysroot copy --- build_system/src/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index d264aac7effbd..3149560b458a8 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -165,11 +165,11 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu )?; // Copy the source files to the sysroot (Rust for Linux needs this). - let sysroot_src_path = "sysroot/lib/rustlib/src/rust"; + let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust"); fs::create_dir_all(&sysroot_src_path).map_err(|error| { format!( "Failed to create directory `{}`: {:?}", - sysroot_src_path, error + sysroot_src_path.display(), error ) })?; run_command( From 0fe5c7fee387d8440b99227ec17587863434b6b6 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 11 Jan 2024 20:42:00 -0500 Subject: [PATCH 086/613] Switch from actions-rs to preinstalled rustup actions-rs is deprecated. Switch to using the preinstalled rustup to install the toolchain, and https://github.com/Swatinem/rust-cache to configure cacheing. --- .github/workflows/ci.yml | 38 ++++++------------------------ .github/workflows/failures.yml | 38 ++++++------------------------ .github/workflows/gcc12.yml | 38 ++++++------------------------ .github/workflows/m68k.yml | 42 ++++++++-------------------------- .github/workflows/release.yml | 38 ++++++------------------------ .github/workflows/stdarch.yml | 39 ++++++------------------------- 6 files changed, 44 insertions(+), 189 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d14f30338b01a..d063f39293960 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,13 @@ jobs: steps: - uses: actions/checkout@v3 + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + - name: Install packages # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools @@ -63,30 +70,6 @@ jobs: echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: cargo-installed-crates2-ubuntu-latest - - - name: Cache cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} - #- name: Cache rust repository ## We only clone the rust repository for rustc tests #if: ${{ contains(matrix.commands, 'rustc') }} @@ -111,13 +94,6 @@ jobs: git config --global user.name "User" ./y.sh prepare - # Compile is a separate step, as the actions-rs/cargo action supports error annotations - - name: Compile - uses: actions-rs/cargo@v1.0.3 - with: - command: build - args: --release - - name: Add more failing tests because the sysroot is not compiled with LTO run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index b411b9a17846e..b768918a014ee 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -36,6 +36,13 @@ jobs: steps: - uses: actions/checkout@v3 + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + - name: Install packages run: sudo apt-get install ninja-build ripgrep @@ -71,30 +78,6 @@ jobs: echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: cargo-installed-crates2-ubuntu-latest - - - name: Cache cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} - #- name: Cache rust repository #uses: actions/cache@v3 #id: cache-rust-repository @@ -115,13 +98,6 @@ jobs: if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: ./y.sh prepare - # Compile is a separate step, as the actions-rs/cargo action supports error annotations - - name: Compile - uses: actions-rs/cargo@v1.0.3 - with: - command: build - args: --release - - name: Add more failing tests because the sysroot is not compiled with LTO run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index eef26f01789f1..a522423f36cc5 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -35,6 +35,13 @@ jobs: steps: - uses: actions/checkout@v3 + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + - name: Install packages # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev @@ -48,30 +55,6 @@ jobs: echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: cargo-installed-crates2-ubuntu-latest - - - name: Cache cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} - #- name: Cache rust repository ## We only clone the rust repository for rustc tests #if: ${{ contains(matrix.commands, 'rustc') }} @@ -94,13 +77,6 @@ jobs: git config --global user.name "User" ./y.sh prepare --libgccjit12-patches - # Compile is a separate step, as the actions-rs/cargo action supports error annotations - - name: Compile - uses: actions-rs/cargo@v1.0.3 - with: - command: build - args: --release - - name: Add more failing tests for GCC 12 run: cat failing-ui-tests12.txt >> failing-ui-tests.txt diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index a7489b10744f4..af46650219852 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -36,13 +36,20 @@ jobs: ] steps: + - uses: actions/checkout@v3 + + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + - name: Install packages run: | sudo apt-get update sudo apt-get install qemu qemu-user-static - - uses: actions/checkout@v3 - - name: Download GCC artifact uses: dawidd6/action-download-artifact@v2 with: @@ -72,30 +79,6 @@ jobs: echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: cargo-installed-crates2-ubuntu-latest - - #- name: Cache cargo registry - #uses: actions/cache@v3 - #with: - #path: ~/.cargo/registry - #key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} - - #- name: Cache cargo index - #uses: actions/cache@v3 - #with: - #path: ~/.cargo/git - #key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} - #- name: Cache rust repository ## We only clone the rust repository for rustc tests #if: ${{ contains(matrix.commands, 'rustc') }} @@ -126,13 +109,6 @@ jobs: git config --global user.name "User" ./y.sh prepare --cross - # Compile is a separate step, as the actions-rs/cargo action supports error annotations - - name: Compile - uses: actions-rs/cargo@v1.0.3 - with: - command: build - args: --release - - name: Add more failing tests because the sysroot is not compiled with LTO run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6dc950f88a23b..071c21d5f7bb3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,6 +26,13 @@ jobs: steps: - uses: actions/checkout@v3 + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + - name: Install packages run: sudo apt-get install ninja-build ripgrep @@ -51,30 +58,6 @@ jobs: echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: cargo-installed-crates2-ubuntu-latest - - - name: Cache cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} - - name: Build run: | ./y.sh prepare --only-libcore @@ -92,13 +75,6 @@ jobs: # FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros. echo -n 'lto = "fat"' >> build_sysroot/Cargo.toml - # Compile is a separate step, as the actions-rs/cargo action supports error annotations - - name: Compile - uses: actions-rs/cargo@v1.0.3 - with: - command: build - args: --release - - name: Add more failing tests because of undefined symbol errors (FIXME) run: cat failing-lto-tests.txt >> failing-ui-tests.txt diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index d8336fe991b63..7c3ad6281e9fb 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -26,6 +26,13 @@ jobs: steps: - uses: actions/checkout@v3 + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + - name: Install packages run: sudo apt-get install ninja-build ripgrep @@ -65,30 +72,6 @@ jobs: echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - name: Cache cargo installed crates - uses: actions/cache@v3 - with: - path: ~/.cargo/bin - key: cargo-installed-crates2-ubuntu-latest - - - name: Cache cargo registry - uses: actions/cache@v3 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v3 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo target dir - uses: actions/cache@v3 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }} - - name: Build run: | ./y.sh prepare --only-libcore @@ -108,14 +91,6 @@ jobs: git config --global user.name "User" ./y.sh prepare - # Compile is a separate step, as the actions-rs/cargo action supports error annotations - - name: Compile - uses: actions-rs/cargo@v1.0.3 - with: - command: build - # TODO: remove `--features master` when it is back to the default. - args: --release --features master - - name: Run tests if: ${{ !matrix.cargo_runner }} run: | From 0783d4505737fc2dff395065af7af0e0e3ad5962 Mon Sep 17 00:00:00 2001 From: usamoi Date: Wed, 3 Jan 2024 20:24:24 +0800 Subject: [PATCH 087/613] add avx512fp16 to x86 target features --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 03f8f43ff1643..f8f054db65ede 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -408,7 +408,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Locke .filter(|_feature| { target_info.cpu_supports(_feature) /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma, + adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves From 52946377dc9dfbeb3c2ebc31f9263d308c0af2ab Mon Sep 17 00:00:00 2001 From: Nicholas Thompson Date: Sun, 14 Jan 2024 11:52:06 -0500 Subject: [PATCH 088/613] Honor $RUSTUP_HOME --- build_system/src/test.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1577cbf2b53ed..dc1dc82736efb 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -556,7 +556,7 @@ verbose-tests = true [build] cargo = "{cargo}" local-rebuild = true -rustc = "{home}/.rustup/toolchains/{toolchain}-{host_triple}/bin/rustc" +rustc = "{rustup_home}/toolchains/{toolchain}-{host_triple}/bin/rustc" [target.x86_64-unknown-linux-gnu] llvm-filecheck = "{llvm_filecheck}" @@ -565,7 +565,10 @@ llvm-filecheck = "{llvm_filecheck}" download-ci-llvm = false "#, cargo = cargo.trim(), - home = env.get("HOME").unwrap(), + rustup_home = match env.get("RUSTUP_HOME") { + Some(rustup_dir) => rustup_dir.clone(), + None => env.get("HOME").unwrap().to_owned() + "/.rustup", + }, toolchain = toolchain, host_triple = args.config_info.host_triple, llvm_filecheck = llvm_filecheck.trim(), From 7dd3f6fffbefcd8acb142cd2d0d166b08619e62f Mon Sep 17 00:00:00 2001 From: Nicholas Thompson Date: Sun, 14 Jan 2024 14:19:40 -0500 Subject: [PATCH 089/613] call rustup which --- build_system/src/test.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index dc1dc82736efb..11622026994d1 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -488,8 +488,10 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { } fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { - let toolchain = get_toolchain()?; - + let toolchain = format!("+{channel}-{host}", + channel = get_toolchain()?, // May also include date + host = args.config_info.host_triple + ); let rust_dir = Some(Path::new("rust")); // If the repository was already cloned, command will fail, so doesn't matter. let _ = run_command_with_output_and_env( @@ -524,6 +526,18 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { Ok(cargo) } })?; + let rustc = String::from_utf8( + run_command_with_env(&[&"rustup", &OsStr::new(&*toolchain), &"which", &"rustc"], rust_dir, Some(env))?.stdout, + ) + .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error)) + .and_then(|rustc| { + let rustc = rustc.trim().to_owned(); + if rustc.is_empty() { + Err(format!("`rustc` path is empty")) + } else { + Ok(rustc) + } + })?; let llvm_filecheck = match run_command_with_env( &[ &"bash", @@ -556,7 +570,7 @@ verbose-tests = true [build] cargo = "{cargo}" local-rebuild = true -rustc = "{rustup_home}/toolchains/{toolchain}-{host_triple}/bin/rustc" +rustc = "{rustc}" [target.x86_64-unknown-linux-gnu] llvm-filecheck = "{llvm_filecheck}" @@ -564,13 +578,8 @@ llvm-filecheck = "{llvm_filecheck}" [llvm] download-ci-llvm = false "#, - cargo = cargo.trim(), - rustup_home = match env.get("RUSTUP_HOME") { - Some(rustup_dir) => rustup_dir.clone(), - None => env.get("HOME").unwrap().to_owned() + "/.rustup", - }, - toolchain = toolchain, - host_triple = args.config_info.host_triple, + cargo = cargo, + rustc = rustc, llvm_filecheck = llvm_filecheck.trim(), ), ) From dcb531f13042c5d335ce689555aae2230c3db778 Mon Sep 17 00:00:00 2001 From: Nic Date: Tue, 16 Jan 2024 12:57:34 -0500 Subject: [PATCH 090/613] Update build_system/src/test.rs Co-authored-by: antoyo --- build_system/src/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 11622026994d1..e098e3702b890 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -527,7 +527,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { } })?; let rustc = String::from_utf8( - run_command_with_env(&[&"rustup", &OsStr::new(&*toolchain), &"which", &"rustc"], rust_dir, Some(env))?.stdout, + run_command_with_env(&[&"rustup", &toolchain, &"which", &"rustc"], rust_dir, Some(env))?.stdout, ) .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error)) .and_then(|rustc| { From 94ed9d16cff42752e2fdd95ca131fa8288cb513f Mon Sep 17 00:00:00 2001 From: Rowan S-L Date: Thu, 18 Jan 2024 12:41:25 -0500 Subject: [PATCH 091/613] rename `y.sh test --clean-ui-tests` to `y.sh clean ui-tests` --- build_system/src/clean.rs | 76 +++++++++++++++++++++++---------------- build_system/src/test.rs | 15 -------- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs index 56cc19d255f96..929a878113d69 100644 --- a/build_system/src/clean.rs +++ b/build_system/src/clean.rs @@ -1,40 +1,43 @@ -use crate::utils::remove_file; +use crate::utils::{remove_file, run_command}; use std::fs::remove_dir_all; #[derive(Default)] -struct CleanArg { - all: bool, +enum CleanArg { + /// `clean all` + All, + /// `clean ui-tests` + UiTests, + /// `clean --help` + #[default] + Help, } impl CleanArg { - fn new() -> Result, String> { - let mut args = CleanArg::default(); - + fn new() -> Result { // We skip the binary and the "clean" option. for arg in std::env::args().skip(2) { - match arg.as_str() { - "all" => args.all = true, - "--help" => { - Self::usage(); - return Ok(None); - } - a => return Err(format!("Unknown argument `{}`", a)), - } + return match arg.as_str() { + "all" => Ok(Self::All), + "ui-tests" => Ok(Self::UiTests), + "--help" => Ok(Self::Help), + a => Err(format!("Unknown argument `{}`", a)), + }; } - Ok(Some(args)) + Ok(Self::default()) } +} - fn usage() { - println!( - r#" - `clean` command help: +fn usage() { + println!( + r#" +`clean` command help: - all : Clean all data - --help : Show this help - "# - ) - } + all : Clean all data + ui-tests : Clean ui tests + --help : Show this help +"# + ) } fn clean_all() -> Result<(), String> { @@ -60,14 +63,25 @@ fn clean_all() -> Result<(), String> { Ok(()) } -pub fn run() -> Result<(), String> { - let args = match CleanArg::new()? { - Some(a) => a, - None => return Ok(()), - }; +fn clean_ui_tests() -> Result<(), String> { + run_command( + &[ + &"find", + &"rust/build/x86_64-unknown-linux-gnu/test/ui/", + &"-name", + &"stamp", + &"-delete", + ], + None, + )?; + Ok(()) +} - if args.all { - clean_all()?; +pub fn run() -> Result<(), String> { + match CleanArg::new()? { + CleanArg::All => clean_all()?, + CleanArg::UiTests => clean_ui_tests()?, + CleanArg::Help => usage(), } Ok(()) } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1577cbf2b53ed..f3d0d38499cbb 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -32,7 +32,6 @@ fn get_runners() -> Runners { ("Run failing rustc tests", test_failing_rustc), ); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); - runners.insert("--clean-ui-tests", ("Clean ui tests", clean_ui_tests)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); runners.insert("--std-tests", ("Run std tests", std_tests)); @@ -1086,20 +1085,6 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { }) } -fn clean_ui_tests(_env: &Env, _args: &TestArg) -> Result<(), String> { - run_command( - &[ - &"find", - &"rust/build/x86_64-unknown-linux-gnu/test/ui/", - &"-name", - &"stamp", - &"-delete", - ], - None, - )?; - Ok(()) -} - fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { clean(env, args)?; mini_tests(env, args)?; From d34789f5d2bb31b76b8775a695ba8b559ac93303 Mon Sep 17 00:00:00 2001 From: Rowan S-L Date: Fri, 19 Jan 2024 11:18:40 -0500 Subject: [PATCH 092/613] update Intel Software Development Emulator --- .github/workflows/stdarch.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 7c3ad6281e9fb..8ffb82518efa5 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -41,9 +41,9 @@ jobs: run: | mkdir intel-sde cd intel-sde - dir=sde-external-9.14.0-2022-10-25-lin + dir=sde-external-9.33.0-2024-01-07-lin file=$dir.tar.xz - wget https://downloadmirror.intel.com/751535/$file + wget https://downloadmirror.intel.com/813591/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde From 599492a3d594312f59d051240e573176bd1df2ab Mon Sep 17 00:00:00 2001 From: liewyec Date: Sat, 20 Jan 2024 13:30:51 +0100 Subject: [PATCH 093/613] replace filter with skip and take --- build_system/src/test.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1577cbf2b53ed..e7325d5e71fe8 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -979,12 +979,7 @@ where let start = current_part * count; let end = current_part * count + count; // We remove the files we don't want to test. - for path in files - .iter() - .enumerate() - .filter(|(pos, _)| *pos < start || *pos >= end) - .map(|(_, path)| path) - { + for path in files.iter().skip(start).take(count) { remove_file(&rust_path.join(path))?; } } From b2a7afd898b06b8d575563caebb43b32b3a149ec Mon Sep 17 00:00:00 2001 From: Nicholas Thompson Date: Tue, 23 Jan 2024 12:02:31 -0500 Subject: [PATCH 094/613] Further Implement `is_val_statically_known` --- src/context.rs | 7 ++++--- src/intrinsic/mod.rs | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/context.rs b/src/context.rs index 053f759329fb1..5760d96165ddf 100644 --- a/src/context.rs +++ b/src/context.rs @@ -196,15 +196,16 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let mut functions = FxHashMap::default(); let builtins = [ - "__builtin_unreachable", "abort", "__builtin_expect", "__builtin_add_overflow", "__builtin_mul_overflow", - "__builtin_saddll_overflow", /*"__builtin_sadd_overflow",*/ "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/ + "__builtin_unreachable", "abort", "__builtin_expect", /*"__builtin_expect_with_probability",*/ + "__builtin_constant_p", "__builtin_add_overflow", "__builtin_mul_overflow", "__builtin_saddll_overflow", + /*"__builtin_sadd_overflow",*/ "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/ "__builtin_ssubll_overflow", /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow", "__builtin_uaddll_overflow", "__builtin_uadd_overflow", "__builtin_umulll_overflow", "__builtin_umul_overflow", "__builtin_usubll_overflow", "__builtin_usub_overflow", "sqrtf", "sqrt", "__builtin_powif", "__builtin_powi", "sinf", "sin", "cosf", "cos", "powf", "pow", "expf", "exp", "exp2f", "exp2", "logf", "log", "log10f", "log10", "log2f", "log2", "fmaf", "fma", "fabsf", "fabs", "fminf", "fmin", "fmaxf", "fmax", "copysignf", "copysign", "floorf", "floor", "ceilf", "ceil", "truncf", "trunc", "rintf", "rint", "nearbyintf", "nearbyint", "roundf", "round", - "__builtin_expect_with_probability", + ]; for builtin in builtins.iter() { diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 85b891fce3e42..eac8cb437794b 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -123,6 +123,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { sym::unlikely => { self.expect(args[0].immediate(), false) } + sym::is_val_statically_known => { + let a = args[0].immediate(); + let builtin = self.context.get_builtin_function("__builtin_constant_p"); + let res = self.context.new_call(None, builtin, &[a]); + self.icmp(IntPredicate::IntEQ, res, self.const_i32(0)) + } kw::Try => { try_intrinsic( self, From adbc67664b98c2c5473a61b26019c86d8304dd46 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Sep 2023 09:39:41 +0200 Subject: [PATCH 095/613] remove StructuralEq trait --- example/mini_core.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 3607b7cd9448b..a79909ce0c878 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -104,9 +104,6 @@ unsafe impl Freeze for &mut T {} #[lang = "structural_peq"] pub trait StructuralPartialEq {} -#[lang = "structural_teq"] -pub trait StructuralEq {} - #[lang = "not"] pub trait Not { type Output; From 215284a490a382cf9c1e2bde12484d7daa72e9aa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 26 Sep 2023 09:39:41 +0200 Subject: [PATCH 096/613] remove StructuralEq trait --- example/mini_core.rs | 3 --- tests/run/static.rs | 3 --- 2 files changed, 6 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index db94bc1c86af9..230009741dc41 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -100,9 +100,6 @@ unsafe impl Freeze for &mut T {} #[lang = "structural_peq"] pub trait StructuralPartialEq {} -#[lang = "structural_teq"] -pub trait StructuralEq {} - #[lang = "not"] pub trait Not { type Output; diff --git a/tests/run/static.rs b/tests/run/static.rs index 0b933754c2937..e7c46ae3fcc81 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -61,9 +61,6 @@ mod libc { #[lang = "structural_peq"] pub trait StructuralPartialEq {} -#[lang = "structural_teq"] -pub trait StructuralEq {} - #[lang = "drop_in_place"] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place(to_drop: *mut T) { From b192f911d5c861030be528d5caa962f887780b38 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 25 Jan 2024 22:20:42 -0800 Subject: [PATCH 097/613] Rebase slice_group_by stabilization PR --- patches/0027-coretests-128bit-atomic-operations.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/0027-coretests-128bit-atomic-operations.patch b/patches/0027-coretests-128bit-atomic-operations.patch index be29ae09bcfc6..271ca12eabbcd 100644 --- a/patches/0027-coretests-128bit-atomic-operations.patch +++ b/patches/0027-coretests-128bit-atomic-operations.patch @@ -21,7 +21,7 @@ index 897a5e9..331f66f 100644 -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(int_roundings)] - #![feature(slice_group_by)] + #![feature(split_array)] diff --git a/atomic.rs b/atomic.rs index b735957..ea728b6 100644 --- a/atomic.rs From 0061bb7faf34f89f0227757a04566fe319455eed Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 26 Jan 2024 18:33:45 +0000 Subject: [PATCH 098/613] Merge commit '3e50cf65025f96854d6597e80449b0d64ad89589' into sync_cg_clif-2024-01-26 --- .github/workflows/abi-cafe.yml | 4 +- .github/workflows/audit.yml | 2 +- .github/workflows/main.yml | 18 +- .github/workflows/rustc.yml | 8 +- .vscode/settings.json | 3 +- Cargo.lock | 140 ++++++-- Cargo.toml | 12 +- Readme.md | 23 ++ build_system/tests.rs | 8 +- ...nable-the-exposed_provenance-feature.patch | 22 -- patches/rand-lock.toml | 23 ++ patches/stdlib-lock.toml | 4 +- rust-toolchain | 2 +- src/debuginfo/mod.rs | 11 +- src/driver/aot.rs | 20 +- src/driver/jit.rs | 7 +- src/inline_asm.rs | 36 +- src/intrinsics/llvm.rs | 4 + src/intrinsics/llvm_aarch64.rs | 14 + src/intrinsics/llvm_x86.rs | 330 +++++++----------- src/intrinsics/simd.rs | 34 +- src/lib.rs | 23 +- src/unsize.rs | 7 +- src/vtable.rs | 2 +- 24 files changed, 434 insertions(+), 323 deletions(-) delete mode 100644 patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch diff --git a/.github/workflows/abi-cafe.yml b/.github/workflows/abi-cafe.yml index bd3b051185b46..e6bf944f5527b 100644 --- a/.github/workflows/abi-cafe.yml +++ b/.github/workflows/abi-cafe.yml @@ -33,14 +33,14 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features if: matrix.os == 'ubuntu-latest' run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 3efdec4155932..b4f8ce0f5329d 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -10,7 +10,7 @@ jobs: audit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: | sed -i 's/components.*/components = []/' rust-toolchain echo 'profile = "minimal"' >> rust-toolchain diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9bbb18fc37fca..cf9a105538df4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Avoid installing rustc-dev run: | @@ -64,14 +64,14 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features if: matrix.os == 'ubuntu-latest' run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -138,7 +138,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo @@ -164,13 +164,13 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -221,10 +221,10 @@ jobs: TARGET_TRIPLE: x86_64-pc-windows-gnu steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -276,7 +276,7 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Download all built artifacts uses: actions/download-artifact@v4 diff --git a/.github/workflows/rustc.yml b/.github/workflows/rustc.yml index 8085dc58263cc..930d025b73edc 100644 --- a/.github/workflows/rustc.yml +++ b/.github/workflows/rustc.yml @@ -9,13 +9,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} @@ -32,13 +32,13 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: CPU features run: cat /proc/cpuinfo - name: Cache cargo target dir - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: build/cg_clif key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} diff --git a/.vscode/settings.json b/.vscode/settings.json index 834a1362caf32..491646ce59bb3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,9 @@ { "editor.formatOnSave": true, - // source for rustc_* is not included in the rust-src component; disable the errors about this + // in case rustc.source is disabled for performance reasons; disable the errors about this "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"], + "rust-analyzer.rustc.source": "discover", "rust-analyzer.imports.granularity.enforce": true, "rust-analyzer.imports.granularity.group": "module", "rust-analyzer.imports.prefix": "crate", diff --git a/Cargo.lock b/Cargo.lock index 6d6a1200f5028..86bc7d0f067cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92" +checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8" +checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463" +checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330" +checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36" [[package]] name = "cranelift-control" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053" +checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7" +checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d" [[package]] name = "cranelift-frontend" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df" +checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc" +checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96" [[package]] name = "cranelift-jit" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4946271f1055e26544ef8c90fa24776f201566419dfac4b3962c39d5a804ff67" +checksum = "2f61e236d7622c3c43016e8b0f3ba27136e21ac7de328c7fda902e61db1de851" dependencies = [ "anyhow", "cranelift-codegen", @@ -138,14 +138,14 @@ dependencies = [ "region", "target-lexicon", "wasmtime-jit-icache-coherence", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "cranelift-module" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7e3bdae2597556e59edeb8ecb62eb32c7e054c4f042d393732902979db69c3" +checksum = "f30c6820342015c5009070e3e48d1da7b13521399de904663f1c84f5ee839657" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1" +checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.103.0" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e0ee3d013728903e0c513c31afa389b559bfd4fe8a44f80335c799e3132a41" +checksum = "24425a329b4343177d5f1852243841dcec17f929d72c0e7f41262140155e55e7" dependencies = [ "anyhow", "cranelift-codegen", @@ -251,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -374,13 +374,13 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "16.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a" +checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da" dependencies = [ "cfg-if", "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -411,7 +411,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -420,13 +429,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -435,38 +459,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index c57e964168f4d..586ce2286f971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.103", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.103" } -cranelift-module = { version = "0.103" } -cranelift-native = { version = "0.103" } -cranelift-jit = { version = "0.103", optional = true } -cranelift-object = { version = "0.103" } +cranelift-codegen = { version = "0.104", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.104" } +cranelift-module = { version = "0.104" } +cranelift-native = { version = "0.104" } +cranelift-jit = { version = "0.104", optional = true } +cranelift-object = { version = "0.104" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/Readme.md b/Readme.md index ca6ecdf1d0e88..4f45526196397 100644 --- a/Readme.md +++ b/Readme.md @@ -62,6 +62,27 @@ $ ./test.sh For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`. +## Platform support + +|OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)| +|---|---|---|---|---| +|Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]| +|FreeBSD|✅[^no-rustup]|❓|❓|❓| +|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| +|Other unixes|❓|❓|❓|❓| +|macOS|✅|❌[^apple-silicon]|N/A|N/A| +|Windows|✅[^no-rustup]|❌|N/A|N/A| + +✅: Fully supported and tested +❓: Maybe supported, not tested +❌: Not supported at all + +Not all targets are available as rustup component for nightly. See notes in the platform support matrix. + +[^xcoff]: XCOFF object file format is not supported. +[^apple-silicon]: Tracked in [#1248](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1248). +[^no-rustup]: Not available as rustup component for nightly. You can build it yourself. + ## Usage rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects. @@ -100,6 +121,8 @@ You need to do this steps to successfully compile and use the cranelift backend * (Optional) run tests: `rustup run stage2 ./y.sh test` 8. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`. +You can also set `rust-analyzer.rustc.source` to your rust workspace to get rust-analyzer to understand your changes. + ## Configuration See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all diff --git a/build_system/tests.rs b/build_system/tests.rs index cb7b2454cd5ed..818f3d6f08d26 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -113,8 +113,8 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ pub(crate) static RAND_REPO: GitRepo = GitRepo::github( "rust-random", "rand", - "9a02c819cc1e4ec6959ae25eafbb5cf6acb68234", - "4934f0afb1d1c2ca", + "1f4507a8e1cf8050e4ceef95eeda8f64645b6719", + "981f8bf489338978", "rand", ); @@ -133,8 +133,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "4825b2a64d765317066948867e8714674419359b", - "9e67d07c00f5fb0b", + "97007cc2e70df8c97326ce896a79e2f0ce4dd98b", + "e54a16035cedf205", "portable-simd", ); diff --git a/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch b/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch deleted file mode 100644 index b8c0783f52430..0000000000000 --- a/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch +++ /dev/null @@ -1,22 +0,0 @@ -From a101a43b795431ce617e7782afb451f4853afc00 Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Thu, 7 Dec 2023 14:51:35 +0000 -Subject: [PATCH] Enable the exposed_provenance feature - ---- - crates/core_simd/tests/pointers.rs | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/crates/core_simd/tests/pointers.rs b/crates/core_simd/tests/pointers.rs -index 0ae8f83..06620d6 100644 ---- a/crates/core_simd/tests/pointers.rs -+++ b/crates/core_simd/tests/pointers.rs -@@ -1,4 +1,4 @@ --#![feature(portable_simd, strict_provenance)] -+#![feature(exposed_provenance, portable_simd, strict_provenance)] - - use core_simd::simd::{Simd, SimdConstPtr, SimdMutPtr}; - --- -2.34.1 - diff --git a/patches/rand-lock.toml b/patches/rand-lock.toml index aacf3653c169e..815b828a68bd6 100644 --- a/patches/rand-lock.toml +++ b/patches/rand-lock.toml @@ -487,6 +487,7 @@ dependencies = [ "rand_pcg", "rayon", "serde", + "zerocopy", ] [[package]] @@ -505,6 +506,7 @@ version = "0.7.0" dependencies = [ "getrandom", "serde", + "zerocopy", ] [[package]] @@ -525,6 +527,7 @@ name = "rand_pcg" version = "0.4.0" dependencies = [ "bincode", + "rand", "rand_core", "serde", ] @@ -823,3 +826,23 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index 8e213f71c3f38..ad63b0768d313 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.104" +version = "0.1.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741" +checksum = "f4ab134a739bafec76aa91ccb15d519a54e569350644a1fea6528d5a0d407e22" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/rust-toolchain b/rust-toolchain index a086c0293601f..ccd7edbc2a917 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-12-31" +channel = "nightly-2024-01-26" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index e6edc452cfb08..2d9c2ecdbc2be 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -13,17 +13,14 @@ use gimli::write::{ }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; use indexmap::IndexSet; +use rustc_session::Session; pub(crate) use self::emit::{DebugReloc, DebugRelocName}; pub(crate) use self::unwind::UnwindContext; use crate::prelude::*; -pub(crate) fn producer() -> String { - format!( - "rustc version {} with cranelift {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - cranelift_codegen::VERSION, - ) +pub(crate) fn producer(sess: &Session) -> String { + format!("rustc version {} with cranelift {}", sess.cfg_version, cranelift_codegen::VERSION) } pub(crate) struct DebugContext { @@ -67,7 +64,7 @@ impl DebugContext { let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen(); - let producer = producer(); + let producer = producer(tcx.sess); let comp_dir = tcx .sess .opts diff --git a/src/driver/aot.rs b/src/driver/aot.rs index e77b0cd0721b2..757082a5fed1c 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -143,6 +143,7 @@ fn emit_cgu( debug: Option, unwind_context: UnwindContext, global_asm_object_file: Option, + producer: &str, ) -> Result { let mut product = module.finish(); @@ -152,8 +153,14 @@ fn emit_cgu( unwind_context.emit(&mut product); - let module_regular = - emit_module(output_filenames, prof, product.object, ModuleKind::Regular, name.clone())?; + let module_regular = emit_module( + output_filenames, + prof, + product.object, + ModuleKind::Regular, + name.clone(), + producer, + )?; Ok(ModuleCodegenResult { module_regular, @@ -174,6 +181,7 @@ fn emit_module( mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, + producer_str: &str, ) -> Result { if object.format() == cranelift_object::object::BinaryFormat::Elf { let comment_section = object.add_section( @@ -182,7 +190,7 @@ fn emit_module( cranelift_object::object::SectionKind::OtherString, ); let mut producer = vec![0]; - producer.extend(crate::debuginfo::producer().as_bytes()); + producer.extend(producer_str.as_bytes()); producer.push(0); object.set_section_data(comment_section, producer, 1); } @@ -321,6 +329,8 @@ fn module_codegen( (cgu_name, cx, module, codegened_functions) }); + let producer = crate::debuginfo::producer(tcx.sess); + OngoingModuleCodegen::Async(std::thread::spawn(move || { cx.profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| { cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( @@ -348,6 +358,7 @@ fn module_codegen( cx.debug_context, cx.unwind_context, global_asm_object_file, + &producer, ) }); std::mem::drop(token); @@ -453,6 +464,7 @@ pub(crate) fn run_aot( product.object, ModuleKind::Allocator, "allocator_shim".to_owned(), + &crate::debuginfo::producer(tcx.sess), ) { Ok(allocator_module) => Some(allocator_module), Err(err) => tcx.dcx().fatal(err), @@ -467,7 +479,7 @@ pub(crate) fn run_aot( let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); let metadata_cgu_name = cgu_name_builder - .build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")) + .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata")) .as_str() .to_string(); diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 50d9f287e74c9..6b2b946db02b6 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -321,10 +321,9 @@ fn dep_symbol_lookup_fn( Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { let name = crate_info.crate_name[&cnum]; - sess.dcx() - .struct_err(format!("Can't load static lib {}", name)) - .note("rustc_codegen_cranelift can only load dylibs in JIT mode.") - .emit(); + let mut diag = sess.dcx().struct_err(format!("Can't load static lib {}", name)); + diag.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); + diag.emit(); } Linkage::Dynamic => { dylib_paths.push(src.dylib.as_ref().unwrap().0.clone()); diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 6b9cec39d7020..7793b1b70924b 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -52,7 +52,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( } let operands = operands - .into_iter() + .iter() .map(|operand| match *operand { InlineAsmOperand::In { reg, ref value } => CInlineAsmOperand::In { reg, @@ -506,10 +506,34 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { generated_asm.push('%'); } - self.registers[*operand_idx] - .unwrap() - .emit(&mut generated_asm, self.arch, *modifier) - .unwrap(); + + let reg = self.registers[*operand_idx].unwrap(); + match self.arch { + InlineAsmArch::X86_64 => match reg { + InlineAsmReg::X86(reg) + if reg as u32 >= X86InlineAsmReg::xmm0 as u32 + && reg as u32 <= X86InlineAsmReg::xmm15 as u32 => + { + // rustc emits x0 rather than xmm0 + let class = match *modifier { + None | Some('x') => "xmm", + Some('y') => "ymm", + Some('z') => "zmm", + _ => unreachable!(), + }; + write!( + generated_asm, + "{class}{}", + reg as u32 - X86InlineAsmReg::xmm0 as u32 + ) + .unwrap(); + } + _ => reg + .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier) + .unwrap(), + }, + _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(), + } } CInlineAsmOperand::Const { ref value } => { generated_asm.push_str(value); @@ -739,7 +763,7 @@ fn call_inline_asm<'tcx>( }, ) .unwrap(); - let inline_asm_func = fx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func); + let inline_asm_func = fx.module.declare_func_in_func(inline_asm_func, fx.bcx.func); if fx.clif_comments.enabled() { fx.add_comment(inline_asm_func, asm_name); } diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 1345c4614e254..e50c74b87f603 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -35,6 +35,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( } match intrinsic { + "llvm.prefetch" => { + // Nothing to do. This is merely a perf hint. + } + _ if intrinsic.starts_with("llvm.ctlz.v") => { intrinsic_args!(fx, args => (a); intrinsic); diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index f6f3b85d3ef81..e66bcbf4e40e5 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -243,6 +243,20 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( } // FIXME generalize vector types + "llvm.aarch64.neon.tbl1.v8i8" => { + intrinsic_args!(fx, args => (t, idx); intrinsic); + + let zero = fx.bcx.ins().iconst(types::I8, 0); + for i in 0..8 { + let idx_lane = idx.value_lane(fx, i).load_scalar(fx); + let is_zero = + fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, idx_lane, 16); + let t_idx = fx.bcx.ins().uextend(fx.pointer_type, idx_lane); + let t_lane = t.value_lane_dyn(fx, t_idx).load_scalar(fx); + let res = fx.bcx.ins().select(is_zero, zero, t_lane); + ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted()); + } + } "llvm.aarch64.neon.tbl1.v16i8" => { intrinsic_args!(fx, args => (t, idx); intrinsic); diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 994dc66835cde..2e3e7ce986b36 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -610,230 +610,56 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16&ig_expand=4903 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i16); - assert_eq!(ret_lane_ty, fx.tcx.types.u8); - assert_eq!(lane_count * 2, ret_lane_count); - - let zero = fx.bcx.ins().iconst(types::I16, 0); - let max_u8 = fx.bcx.ins().iconst(types::I16, 255); - let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); - - for idx in 0..lane_count { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::U8, PackWidth::Sse); + } - for idx in 0..lane_count { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); + "llvm.x86.sse2.packsswb.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi16&ig_expand=4848 + intrinsic_args!(fx, args => (a, b); intrinsic); - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S8, PackWidth::Sse); } "llvm.x86.avx2.packuswb" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16&ig_expand=4906 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i16); - assert_eq!(ret_lane_ty, fx.tcx.types.u8); - assert_eq!(lane_count * 2, ret_lane_count); - - let zero = fx.bcx.ins().iconst(types::I16, 0); - let max_u8 = fx.bcx.ins().iconst(types::I16, 255); - let ret_lane_layout = fx.layout_of(fx.tcx.types.u8); - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, zero); - let sat = fx.bcx.ins().umin(sat, max_u8); - let res = fx.bcx.ins().ireduce(types::I8, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::U8, PackWidth::Avx); } - "llvm.x86.sse2.packssdw.128" => { - // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889 + "llvm.x86.avx2.packsswb" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi16&ig_expand=4851 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i32); - assert_eq!(ret_lane_ty, fx.tcx.types.i16); - assert_eq!(lane_count * 2, ret_lane_count); - - let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64); - let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64); - let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); - - for idx in 0..lane_count { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S8, PackWidth::Avx); } "llvm.x86.sse41.packusdw" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32&ig_expand=4912 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i32); - assert_eq!(ret_lane_ty, fx.tcx.types.u16); - assert_eq!(lane_count * 2, ret_lane_count); - - let min_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MIN)); - let max_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MAX)); - let ret_lane_layout = fx.layout_of(fx.tcx.types.u16); + pack_instruction(fx, a, b, ret, PackSize::U16, PackWidth::Sse); + } - for idx in 0..lane_count { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_u16); - let sat = fx.bcx.ins().smin(sat, max_u16); - let res = fx.bcx.ins().ireduce(types::I16, sat); + "llvm.x86.sse2.packssdw.128" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889 + intrinsic_args!(fx, args => (a, b); intrinsic); - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Sse); + } - for idx in 0..lane_count { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_u16); - let sat = fx.bcx.ins().smin(sat, max_u16); - let res = fx.bcx.ins().ireduce(types::I16, sat); + "llvm.x86.avx2.packusdw" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi32&ig_expand=4883 + intrinsic_args!(fx, args => (a, b); intrinsic); - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::U16, PackWidth::Avx); } "llvm.x86.avx2.packssdw" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32&ig_expand=4892 intrinsic_args!(fx, args => (a, b); intrinsic); - assert_eq!(a.layout(), b.layout()); - let layout = a.layout(); - - let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); - let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); - assert_eq!(lane_ty, fx.tcx.types.i32); - assert_eq!(ret_lane_ty, fx.tcx.types.i16); - assert_eq!(lane_count * 2, ret_lane_count); - - let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64); - let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64); - let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = a.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane); - } - - for idx in 0..lane_count / 2 { - let lane = b.value_lane(fx, idx).load_scalar(fx); - let sat = fx.bcx.ins().smax(lane, min_i16); - let sat = fx.bcx.ins().smin(sat, max_i16); - let res = fx.bcx.ins().ireduce(types::I16, sat); - - let res_lane = CValue::by_val(res, ret_lane_layout); - ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane); - } + pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Avx); } "llvm.x86.fma.vfmaddsub.ps" @@ -1407,3 +1233,115 @@ fn llvm_add_sub<'tcx>( (cb_out, c) } + +enum PackSize { + U8, + U16, + S8, + S16, +} + +impl PackSize { + fn ret_clif_type(&self) -> Type { + match self { + Self::U8 | Self::S8 => types::I8, + Self::U16 | Self::S16 => types::I16, + } + } + fn src_clif_type(&self) -> Type { + match self { + Self::U8 | Self::S8 => types::I16, + Self::U16 | Self::S16 => types::I32, + } + } + fn src_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self { + Self::U8 | Self::S8 => tcx.types.i16, + Self::U16 | Self::S16 => tcx.types.i32, + } + } + fn ret_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self { + Self::U8 => tcx.types.u8, + Self::S8 => tcx.types.i8, + Self::U16 => tcx.types.u16, + Self::S16 => tcx.types.i16, + } + } + fn max(&self) -> i64 { + match self { + Self::U8 => u8::MAX as u64 as i64, + Self::S8 => i8::MAX as u8 as u64 as i64, + Self::U16 => u16::MAX as u64 as i64, + Self::S16 => i16::MAX as u64 as u64 as i64, + } + } + fn min(&self) -> i64 { + match self { + Self::U8 | Self::U16 => 0, + Self::S8 => i16::from(i8::MIN) as u16 as i64, + Self::S16 => i32::from(i16::MIN) as u32 as i64, + } + } +} + +enum PackWidth { + Sse = 1, + Avx = 2, +} +impl PackWidth { + fn divisor(&self) -> u64 { + match self { + Self::Sse => 1, + Self::Avx => 2, + } + } +} + +/// Implement an x86 pack instruction with the intrinsic `_mm{,256}pack{us,s}_epi{16,32}`. +/// Validated for correctness against LLVM, see commit `c8f5d35508e062bd2d95e6c03429bfec831db6d3`. +fn pack_instruction<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + a: CValue<'tcx>, + b: CValue<'tcx>, + ret: CPlace<'tcx>, + ret_size: PackSize, + width: PackWidth, +) { + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (src_lane_count, src_lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(src_lane_ty, ret_size.src_ty(fx.tcx)); + assert_eq!(ret_lane_ty, ret_size.ret_ty(fx.tcx)); + assert_eq!(src_lane_count * 2, ret_lane_count); + + let min = fx.bcx.ins().iconst(ret_size.src_clif_type(), ret_size.min()); + let max = fx.bcx.ins().iconst(ret_size.src_clif_type(), ret_size.max()); + let ret_lane_layout = fx.layout_of(ret_size.ret_ty(fx.tcx)); + + let mut round = |source: CValue<'tcx>, source_offset: u64, dest_offset: u64| { + let step_amount = src_lane_count / width.divisor(); + let dest_offset = step_amount * dest_offset; + for idx in 0..step_amount { + let lane = source.value_lane(fx, step_amount * source_offset + idx).load_scalar(fx); + let sat = fx.bcx.ins().smax(lane, min); + let sat = match ret_size { + PackSize::U8 | PackSize::U16 => fx.bcx.ins().umin(sat, max), + PackSize::S8 | PackSize::S16 => fx.bcx.ins().smin(sat, max), + }; + let res = fx.bcx.ins().ireduce(ret_size.ret_clif_type(), sat); + let res_lane = CValue::by_val(res, ret_lane_layout); + ret.place_lane(fx, dest_offset + idx).write_cvalue(fx, res_lane); + } + }; + + round(a, 0, 0); + round(b, 0, 1); + + if let PackWidth::Avx = width { + round(a, 1, 2); + round(b, 1, 3); + } +} diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index d56d17892d5b6..ebdc744bcd833 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -293,7 +293,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } ret.write_cvalue(fx, base); - let ret_lane = ret.place_lane(fx, idx.try_into().unwrap()); + let ret_lane = ret.place_lane(fx, idx.into()); ret_lane.write_cvalue(fx, val); } @@ -340,7 +340,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ); } - let ret_lane = v.value_lane(fx, idx.try_into().unwrap()); + let ret_lane = v.value_lane(fx, idx.into()); ret.write_cvalue(fx, ret_lane); } @@ -822,7 +822,35 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); let lane_layout = fx.layout_of(lane_ty); - let m = m.load_scalar(fx); + let expected_int_bits = lane_count.max(8); + let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64); + + let m = match m.layout().ty.kind() { + ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => m.load_scalar(fx), + ty::Array(elem, len) + if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + && len.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) + == Some(expected_bytes) => + { + m.force_stack(fx).0.load( + fx, + Type::int(expected_int_bits as u16).unwrap(), + MemFlags::trusted(), + ) + } + _ => { + fx.tcx.dcx().span_fatal( + span, + format!( + "invalid monomorphization of `simd_select_bitmask` intrinsic: \ + cannot accept `{}` as mask, expected `u{}` or `[u8; {}]`", + ret.layout().ty, + expected_int_bits, + expected_bytes + ), + ); + } + }; for lane in 0..lane_count { let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64); diff --git a/src/lib.rs b/src/lib.rs index b482f0dd2f0ab..416f87fcc87b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_incremental; extern crate rustc_index; -extern crate rustc_interface; extern crate rustc_metadata; extern crate rustc_session; extern crate rustc_span; @@ -42,7 +41,7 @@ use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::config::OutputFilenames; use rustc_session::Session; -use rustc_span::Symbol; +use rustc_span::{sym, Symbol}; pub use crate::config::*; use crate::prelude::*; @@ -190,8 +189,17 @@ impl CodegenBackend for CraneliftCodegenBackend { } } - fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec { - vec![] // FIXME necessary for #[cfg(target_feature] + fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec { + // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] + if sess.target.arch == "x86_64" && sess.target.os != "none" { + // x86_64 mandates SSE2 support + vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")] + } else if sess.target.arch == "aarch64" && sess.target.os != "none" { + // AArch64 mandates Neon support + vec![sym::neon] + } else { + vec![] + } } fn print_version(&self) { @@ -305,16 +313,13 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc { - let builder = cranelift_native::builder_with_options(true).unwrap(); - builder - } + Some("native") => cranelift_native::builder_with_options(true).unwrap(), Some(value) => { let mut builder = cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { sess.dcx().fatal(format!("can't compile for {}: {}", target_triple, err)); }); - if let Err(_) = builder.enable(value) { + if builder.enable(value).is_err() { sess.dcx() .fatal("the specified target cpu isn't currently supported by Cranelift."); } diff --git a/src/unsize.rs b/src/unsize.rs index f777e11371f13..acfa461a6f30b 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -28,10 +28,9 @@ pub(crate) fn unsized_info<'tcx>( .bcx .ins() .iconst(fx.pointer_type, len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64), - ( - &ty::Dynamic(ref data_a, _, src_dyn_kind), - &ty::Dynamic(ref data_b, _, target_dyn_kind), - ) if src_dyn_kind == target_dyn_kind => { + (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind)) + if src_dyn_kind == target_dyn_kind => + { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { diff --git a/src/vtable.rs b/src/vtable.rs index 41ea0b122de73..d2254d4c15e6f 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -95,7 +95,7 @@ pub(crate) fn get_vtable<'tcx>( let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref)); let data_id = data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not); - let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); + let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func); if fx.clif_comments.enabled() { fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id)); } From 82d08913d843d9984a8b73355f772d3d41d12bc7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 27 Jan 2024 10:53:32 +0000 Subject: [PATCH 099/613] Rustup to rustc 1.77.0-nightly (e7bbe8ce9 2024-01-26) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ccd7edbc2a917..cb1e12e8c72dd 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-26" +channel = "nightly-2024-01-27" components = ["rust-src", "rustc-dev", "llvm-tools"] From 8ea292278aadcbd923e317fc39447fd6ad2f0b6c Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 9 Aug 2023 14:36:54 +0100 Subject: [PATCH 100/613] Make `impl` impl take `?Sized` --- library/std/src/os/fd/owned.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 24f2bdcf4217c..06b3c4583bf1b 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -244,7 +244,7 @@ pub trait AsFd { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for &T { +impl AsFd for &T { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { T::as_fd(self) @@ -252,7 +252,7 @@ impl AsFd for &T { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for &mut T { +impl AsFd for &mut T { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { T::as_fd(self) @@ -396,7 +396,7 @@ impl From for crate::net::UdpSocket { /// impl MyTrait for Box {} /// # } /// ``` -impl AsFd for crate::sync::Arc { +impl AsFd for crate::sync::Arc { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() @@ -404,7 +404,7 @@ impl AsFd for crate::sync::Arc { } #[stable(feature = "asfd_rc", since = "1.69.0")] -impl AsFd for crate::rc::Rc { +impl AsFd for crate::rc::Rc { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() @@ -412,7 +412,7 @@ impl AsFd for crate::rc::Rc { } #[stable(feature = "asfd_ptrs", since = "1.64.0")] -impl AsFd for Box { +impl AsFd for Box { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { (**self).as_fd() From f4aeb7030993f5c143e9a84c50061892f6b7046f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 28 Jan 2024 23:31:55 +0000 Subject: [PATCH 101/613] Make `impl` impl take `?Sized` --- library/std/src/os/windows/io/handle.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index b0540872c0b62..55c3913904432 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -422,7 +422,7 @@ pub trait AsHandle { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsHandle for &T { +impl AsHandle for &T { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { T::as_handle(self) @@ -430,7 +430,7 @@ impl AsHandle for &T { } #[stable(feature = "io_safety", since = "1.63.0")] -impl AsHandle for &mut T { +impl AsHandle for &mut T { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { T::as_handle(self) @@ -450,7 +450,7 @@ impl AsHandle for &mut T { /// impl MyTrait for Box {} /// # } /// ``` -impl AsHandle for crate::sync::Arc { +impl AsHandle for crate::sync::Arc { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() @@ -458,7 +458,7 @@ impl AsHandle for crate::sync::Arc { } #[stable(feature = "as_windows_ptrs", since = "1.71.0")] -impl AsHandle for crate::rc::Rc { +impl AsHandle for crate::rc::Rc { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() @@ -466,7 +466,7 @@ impl AsHandle for crate::rc::Rc { } #[stable(feature = "as_windows_ptrs", since = "1.71.0")] -impl AsHandle for Box { +impl AsHandle for Box { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { (**self).as_handle() From be4d3fb261c5852aaed5ac69774aa9efb02be094 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 2 Jan 2024 19:42:47 +0100 Subject: [PATCH 102/613] Update ahash dependency to 0.8.7 --- Cargo.lock | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86bc7d0f067cb..b70a1234af398 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,14 @@ version = 3 [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -293,6 +294,24 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "proc-macro2" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + [[package]] name = "regalloc2" version = "0.9.3" @@ -360,12 +379,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "syn" +version = "2.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "target-lexicon" version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "version_check" version = "0.9.4" @@ -536,3 +572,23 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] From b9d44eef7ad1fc21d3c6fed7f0ca5401ae59f5f8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jan 2024 15:27:16 +1100 Subject: [PATCH 103/613] Remove the lifetime from `DiagnosticArgValue`. Because it's almost always static. This makes `impl IntoDiagnosticArg for DiagnosticArgValue` trivial, which is nice. There are a few diagnostics constructed in `compiler/rustc_mir_build/src/check_unsafety.rs` and `compiler/rustc_mir_transform/src/errors.rs` that now need symbols converted to `String` with `to_string` instead of `&str` with `as_str`, but that' no big deal, and worth it for the simplifications elsewhere. --- src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/errors.rs b/src/errors.rs index e9283b1989453..cc0fbe46dcc11 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -35,7 +35,7 @@ pub(crate) enum PossibleFeature<'a> { struct ExitCode(Option); impl IntoDiagnosticArg for ExitCode { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { let ExitCode(exit_code) = self; match exit_code { Some(t) => t.into_diagnostic_arg(), From b2ff1231dd335a5752acd560bc0c8dbfb2484366 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 30 Jan 2024 15:39:29 +0000 Subject: [PATCH 104/613] Remove the `abi_amdgpu_kernel` feature --- src/abi/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index abd70dd4458f6..0f0d828c8fc3f 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -56,11 +56,7 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented"); } - Conv::Msp430Intr - | Conv::PtxKernel - | Conv::AmdGpuKernel - | Conv::AvrInterrupt - | Conv::AvrNonBlockingInterrupt => { + Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => { unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); } } From 04e4c5ddbc7ab8e60a9481698d97e805b81fa59a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 30 Jan 2024 20:55:56 +0000 Subject: [PATCH 105/613] Remove `ffi_returns_twice` feature --- src/attributes.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index 9f361d3688695..142f86b003ddb 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -62,9 +62,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { func.add_attribute(FnAttribute::Cold); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - func.add_attribute(FnAttribute::ReturnsTwice); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { func.add_attribute(FnAttribute::Pure); } From cdae185e3022b6e7c6c7fe363353fe1176a06604 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 30 Jan 2024 19:46:46 +0000 Subject: [PATCH 106/613] Implement SHA-1 x86 vendor intrinsics --- src/intrinsics/llvm_x86.rs | 116 +++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 2e3e7ce986b36..cd3306f4e56bd 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -1067,6 +1067,122 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( ); } + "llvm.x86.sha1rnds4" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1rnds4_epu32&ig_expand=5877 + intrinsic_args!(fx, args => (a, b, _func); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + let func = if let Some(func) = + crate::constant::mir_operand_get_const_val(fx, &args[2].node) + { + func + } else { + fx.tcx + .dcx() + .span_fatal(span, "Func argument for `_mm_sha1rnds4_epu32` is not a constant"); + }; + + let func = func.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", func)); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha1msg1" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg1_epu32&ig_expand=5874 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha1msg2" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg2_epu32&ig_expand=5875 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + + "llvm.x86.sha1nexte" => { + // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1nexte_epu32&ig_expand=5876 + intrinsic_args!(fx, args => (a, b); intrinsic); + + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + + codegen_inline_asm_inner( + fx, + &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())], + &[ + CInlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), + _late: true, + in_value: a, + out_place: Some(ret), + }, + CInlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)), + value: b, + }, + ], + InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM, + ); + } + "llvm.x86.sha256rnds2" => { // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256rnds2_epu32&ig_expand=5977 intrinsic_args!(fx, args => (a, b, k); intrinsic); From ad8e8201395b0c2a9dbacfde2c5aa7580a1cdb82 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 25 Jan 2024 21:20:12 -0400 Subject: [PATCH 107/613] Update for rebased gcc --- .github/workflows/ci.yml | 14 +++----------- .github/workflows/failures.yml | 14 +++----------- .github/workflows/gcc12.yml | 4 ++-- .github/workflows/m68k.yml | 12 +++--------- .github/workflows/release.yml | 14 +++----------- .github/workflows/stdarch.yml | 12 ++---------- .gitignore | 2 ++ Cargo.lock | 4 ++-- build_system/src/test.rs | 5 ++--- src/consts.rs | 2 +- src/mono_item.rs | 2 +- .../failing-lto-tests.txt | 0 .../failing-non-lto-tests.txt | 0 failing-ui-tests.txt => tests/failing-ui-tests.txt | 1 + .../failing-ui-tests12.txt | 1 - 15 files changed, 25 insertions(+), 62 deletions(-) rename failing-lto-tests.txt => tests/failing-lto-tests.txt (100%) rename failing-non-lto-tests.txt => tests/failing-non-lto-tests.txt (100%) rename failing-ui-tests.txt => tests/failing-ui-tests.txt (98%) rename failing-ui-tests12.txt => tests/failing-ui-tests12.txt (97%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d063f39293960..0d84926fddfec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,19 +49,11 @@ jobs: run: sudo apt-get install ninja-build ripgrep llvm-14-tools - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yml - name: gcc-13 - path: gcc-13 - repo: antoyo/gcc - branch: ${{ matrix.libgccjit_version.artifacts_branch }} - event: push - search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. + run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb - name: Setup path to libgccjit run: | - sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + sudo dpkg --force-overwrite -i gcc-13.deb echo /usr/lib/ > gcc_path - name: Set env @@ -95,7 +87,7 @@ jobs: ./y.sh prepare - name: Add more failing tests because the sysroot is not compiled with LTO - run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt + run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt - name: Run tests run: | diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index b768918a014ee..7aaf47facd87f 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -56,20 +56,12 @@ jobs: - name: Download artifact if: matrix.libgccjit_version.gcc != 'libgccjit12.so' - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yml - name: gcc-13 - path: gcc-13 - repo: antoyo/gcc - branch: ${{ matrix.libgccjit_version.artifacts_branch }} - event: push - search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. + run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: | - sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + sudo dpkg --force-overwrite -i gcc-13.deb echo /usr/lib/ > gcc_path - name: Set env @@ -99,7 +91,7 @@ jobs: run: ./y.sh prepare - name: Add more failing tests because the sysroot is not compiled with LTO - run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt + run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt - name: Run tests id: tests diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index a522423f36cc5..8d4f88ea7b1a4 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -78,10 +78,10 @@ jobs: ./y.sh prepare --libgccjit12-patches - name: Add more failing tests for GCC 12 - run: cat failing-ui-tests12.txt >> failing-ui-tests.txt + run: cat tests/failing-ui-tests12.txt >> tests/failing-ui-tests.txt - name: Add more failing tests because the sysroot is not compiled with LTO - run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt + run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt - name: Run tests run: | diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index af46650219852..b0866bafb8e31 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -50,14 +50,8 @@ jobs: sudo apt-get update sudo apt-get install qemu qemu-user-static - - name: Download GCC artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: m68k.yml - name: gcc-m68k-13 - repo: cross-cg-gcc-tools/cross-gcc - branch: master - event: push + - name: Download artifact + run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb - name: Download VM artifact uses: dawidd6/action-download-artifact@v2 @@ -110,7 +104,7 @@ jobs: ./y.sh prepare --cross - name: Add more failing tests because the sysroot is not compiled with LTO - run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt + run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt - name: Run tests run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 071c21d5f7bb3..7628fd6557166 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,19 +37,11 @@ jobs: run: sudo apt-get install ninja-build ripgrep - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yml - name: gcc-13 - path: gcc-13 - repo: antoyo/gcc - branch: "master" - event: push - search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. + run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb - name: Setup path to libgccjit run: | - sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + sudo dpkg --force-overwrite -i gcc-13.deb echo /usr/lib/ > gcc_path - name: Set env @@ -76,7 +68,7 @@ jobs: echo -n 'lto = "fat"' >> build_sysroot/Cargo.toml - name: Add more failing tests because of undefined symbol errors (FIXME) - run: cat failing-lto-tests.txt >> failing-ui-tests.txt + run: cat tests/failing-lto-tests.txt >> tests/failing-ui-tests.txt - name: Run tests run: | diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 8ffb82518efa5..a5c3a5456bd7f 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -51,19 +51,11 @@ jobs: sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64 - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: main.yml - name: gcc-13 - path: gcc-13 - repo: antoyo/gcc - branch: "master" - event: push - search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts. + run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb - name: Setup path to libgccjit run: | - sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb + sudo dpkg --force-overwrite -i gcc-13.deb echo /usr/lib/ > gcc_path - name: Set env diff --git a/.gitignore b/.gitignore index b44d1aa78c2e6..c865386dad306 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ gimple* res test-backend gcc_path +cross_gcc_path +projects benchmarks tools/llvm-project tools/llvmint diff --git a/Cargo.lock b/Cargo.lock index 7c18633692783..26dc7c535f854 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421" +source = "git+https://github.com/antoyo/gccjit.rs#e6109eb8b7ced60b5191e65b34954d04d4abeaec" dependencies = [ "gccjit_sys", ] @@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421" +source = "git+https://github.com/antoyo/gccjit.rs#e6109eb8b7ced60b5191e65b34954d04d4abeaec" dependencies = [ "libc", ] diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 44c003d8f75e5..5e8a5ebe94960 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -988,7 +988,6 @@ where // one test. let count = files.len() / nb_parts + 1; let start = current_part * count; - let end = current_part * count + count; // We remove the files we don't want to test. for path in files.iter().skip(start).take(count) { remove_file(&rust_path.join(path))?; @@ -1047,7 +1046,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { Some(Path::new("rust")), )?; // Putting back only the failing ones. - let path = "failing-ui-tests.txt"; + let path = "tests/failing-ui-tests.txt"; if let Ok(files) = std::fs::read_to_string(path) { for file in files .split('\n') @@ -1072,7 +1071,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { test_rustc_inner(env, args, || { // Removing the failing tests. - let path = "failing-ui-tests.txt"; + let path = "tests/failing-ui-tests.txt"; if let Ok(files) = std::fs::read_to_string(path) { for file in files .split('\n') diff --git a/src/consts.rs b/src/consts.rs index d8a1fd315c0a5..2501c126faf2f 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -235,7 +235,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { if !self.tcx.is_reachable_non_generic(def_id) { #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(Visibility::Hidden)); + global.add_string_attribute(VarAttribute::Visibility(Visibility::Hidden)); } global diff --git a/src/mono_item.rs b/src/mono_item.rs index 3322d56513bbe..fdeb2f96fe2c9 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -23,7 +23,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); #[cfg(feature="master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + global.add_string_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); // TODO(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); diff --git a/failing-lto-tests.txt b/tests/failing-lto-tests.txt similarity index 100% rename from failing-lto-tests.txt rename to tests/failing-lto-tests.txt diff --git a/failing-non-lto-tests.txt b/tests/failing-non-lto-tests.txt similarity index 100% rename from failing-non-lto-tests.txt rename to tests/failing-non-lto-tests.txt diff --git a/failing-ui-tests.txt b/tests/failing-ui-tests.txt similarity index 98% rename from failing-ui-tests.txt rename to tests/failing-ui-tests.txt index 023fe9d7e8311..13d79cd23e336 100644 --- a/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -70,3 +70,4 @@ tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/closures/capture-unsized-by-ref.rs tests/ui/coroutine/resume-after-return.rs tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs +tests/ui/intrinsics/intrinsics-integer.rs diff --git a/failing-ui-tests12.txt b/tests/failing-ui-tests12.txt similarity index 97% rename from failing-ui-tests12.txt rename to tests/failing-ui-tests12.txt index 3ef2bc3ebf894..857c158e42f0e 100644 --- a/failing-ui-tests12.txt +++ b/tests/failing-ui-tests12.txt @@ -38,6 +38,5 @@ tests/ui/rust-2018/proc-macro-crate-in-paths.rs tests/ui/target-feature/missing-plusminus.rs tests/ui/sse2.rs tests/ui/codegen/issue-79865-llvm-miscompile.rs -tests/ui/intrinsics/intrinsics-integer.rs tests/ui/std-backtrace.rs tests/ui/mir/alignment/packed.rs From f4b65f5caf7c7ea7a2df9cfe43727a3f9dc27f69 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 3 Feb 2024 11:01:26 +0000 Subject: [PATCH 108/613] Docs for std::ptr::slice_from_raw_parts --- library/core/src/ptr/mod.rs | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dce7e035fc73a..6e448d90c1224 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -762,6 +762,17 @@ pub const fn from_mut(r: &mut T) -> *mut T { /// let slice = ptr::slice_from_raw_parts(raw_pointer, 3); /// assert_eq!(unsafe { &*slice }[2], 7); /// ``` +/// +/// You must ensure that the pointer is valid and not null before dereferencing +/// the raw slice. A slice reference must never have a null pointer, even if it's empty. +/// +/// ```rust,should_panic +/// use std::ptr; +/// let danger: *const [u8] = ptr::slice_from_raw_parts(ptr::null(), 0); +/// unsafe { +/// danger.as_ref().expect("references must not be null"); +/// } +/// ``` #[inline] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")] @@ -771,11 +782,13 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { from_raw_parts(data.cast(), len) } +/// Forms a raw mutable slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// /// Performs the same functionality as [`slice_from_raw_parts`], except that a /// raw mutable slice is returned, as opposed to a raw immutable slice. /// -/// See the documentation of [`slice_from_raw_parts`] for more details. -/// /// This function is safe, but actually using the return value is unsafe. /// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements. /// @@ -796,6 +809,17 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { /// /// assert_eq!(unsafe { &*slice }[2], 99); /// ``` +/// +/// You must ensure that the pointer is valid and not null before dereferencing +/// the raw slice. A slice reference must never have a null pointer, even if it's empty. +/// +/// ```rust,should_panic +/// use std::ptr; +/// let danger: *mut [u8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 0); +/// unsafe { +/// danger.as_mut().expect("references must not be null"); +/// } +/// ``` #[inline] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")] From 0a38748d8a49b21d5060b6b274a4b87cd5a7c53e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 3 Feb 2024 13:26:06 -0500 Subject: [PATCH 109/613] Renable intrinsics-integer.rs test --- tests/failing-ui-tests.txt | 1 - tests/failing-ui-tests12.txt | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 13d79cd23e336..023fe9d7e8311 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -70,4 +70,3 @@ tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/closures/capture-unsized-by-ref.rs tests/ui/coroutine/resume-after-return.rs tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs -tests/ui/intrinsics/intrinsics-integer.rs diff --git a/tests/failing-ui-tests12.txt b/tests/failing-ui-tests12.txt index 857c158e42f0e..b4615b26852d8 100644 --- a/tests/failing-ui-tests12.txt +++ b/tests/failing-ui-tests12.txt @@ -40,3 +40,4 @@ tests/ui/sse2.rs tests/ui/codegen/issue-79865-llvm-miscompile.rs tests/ui/std-backtrace.rs tests/ui/mir/alignment/packed.rs +tests/ui/intrinsics/intrinsics-integer.rs From 515ee70efa93bb9ba5ca2b1bd269fdc6e9571eae Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 09:51:39 +1100 Subject: [PATCH 110/613] Invert diagnostic lints. That is, change `diagnostic_outside_of_impl` and `untranslatable_diagnostic` from `allow` to `deny`, because more than half of the compiler has be converted to use translated diagnostics. This commit removes more `deny` attributes than it adds `allow` attributes, which proves that this change is warranted. --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 416f87fcc87b3..7c432e9c59051 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ #![cfg_attr(doc, doc(rust_logo))] #![feature(rustc_private)] // Note: please avoid adding other feature gates where possible +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] From 007cea323884bc8f61effcbf625bcb1d7368a7ec Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 6 Feb 2024 09:51:39 +1100 Subject: [PATCH 111/613] Invert diagnostic lints. That is, change `diagnostic_outside_of_impl` and `untranslatable_diagnostic` from `allow` to `deny`, because more than half of the compiler has be converted to use translated diagnostics. This commit removes more `deny` attributes than it adds `allow` attributes, which proves that this change is warranted. --- src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f8f054db65ede..863b6333bcc29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,8 +27,6 @@ #![recursion_limit="256"] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate rustc_apfloat; extern crate rustc_ast; From 31f7f03c2a08396f518d7732a5dc86f9c13de106 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jan 2024 18:01:56 +0000 Subject: [PATCH 112/613] Add CoroutineClosure to TyKind, AggregateKind, UpvarArgs --- src/type_of.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type_of.rs b/src/type_of.rs index e5c0b2de4ca46..25149b8020162 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -87,7 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | - ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); From caa23f103c91315d9f6ecc5f62f7827718f8866f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 7 Feb 2024 10:26:00 -0500 Subject: [PATCH 113/613] Add a new debug_assertions instrinsic (compiler) And in clippy --- src/base.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/base.rs b/src/base.rs index 0afd6d0e670b3..a7e76fbc128ea 100644 --- a/src/base.rs +++ b/src/base.rs @@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>( NullOp::OffsetOf(fields) => { layout.offset_of_subfield(fx, fields.iter()).bytes() } + NullOp::DebugAssertions => { + let val = fx.tcx.sess.opts.debug_assertions; + let val = CValue::by_val( + fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()), + fx.layout_of(fx.tcx.types.bool), + ); + lval.write_cvalue(fx, val); + return; + } }; let val = CValue::by_val( fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()), From 6b05753cb3c7373b151774540476ae04365fd898 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 8 Feb 2024 12:17:41 -0500 Subject: [PATCH 114/613] Run the tests of popular crates in the CI --- .github/workflows/ci.yml | 1 + build_system/src/prepare.rs | 2 +- build_system/src/test.rs | 56 +++++++++++++++++++++++++++++++++++-- build_system/src/utils.rs | 12 ++++++-- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d84926fddfec..426eabdd176b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ jobs: "--extended-regex-tests", "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", + "--projects", ] steps: diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index ce9b440be053a..7f1401e594c4c 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -152,7 +152,7 @@ fn clone_and_setup(repo_url: &str, checkout_commit: &str, extra: Option) - where F: Fn(&Path) -> Result<(), String>, { - let clone_result = git_clone(repo_url, None)?; + let clone_result = git_clone(repo_url, None, false)?; if !clone_result.ran_clone { println!("`{}` has already been cloned", clone_result.repo_name); } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 5e8a5ebe94960..6564322924318 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,13 +1,13 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ - get_gcc_path, get_toolchain, remove_file, run_command, run_command_with_env, + get_gcc_path, get_toolchain, git_clone, remove_file, run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, }; use std::collections::{BTreeSet, HashMap}; use std::ffi::OsStr; -use std::fs::{remove_dir_all, File}; +use std::fs::{create_dir_all, remove_dir_all, File}; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -31,6 +31,7 @@ fn get_runners() -> Runners { "--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc), ); + runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); @@ -679,6 +680,57 @@ where // echo "[BUILD] sysroot in release mode" // ./build_sysroot/build_sysroot.sh --release +fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { + let projects = [ + //"https://gitlab.gnome.org/GNOME/librsvg", // FIXME: doesn't compile in the CI since the + // version of cairo and other libraries is too old. + "https://github.com/rust-random/getrandom", + "https://github.com/BurntSushi/memchr", + "https://github.com/dtolnay/itoa", + "https://github.com/rust-lang/cfg-if", + "https://github.com/rust-lang-nursery/lazy-static.rs", + //"https://github.com/marshallpierce/rust-base64", // FIXME: one test is OOM-killed. + // TODO: ignore the base64 test that is OOM-killed. + "https://github.com/time-rs/time", + "https://github.com/rust-lang/log", + "https://github.com/bitflags/bitflags", + //"https://github.com/serde-rs/serde", // FIXME: one test fails. + //"https://github.com/rayon-rs/rayon", // TODO: very slow, only run on master? + //"https://github.com/rust-lang/cargo", // TODO: very slow, only run on master? + ]; + + let run_tests = |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { + for project in iter { + let clone_result = git_clone(project, Some(projects_path), true)?; + let repo_path = Path::new(&clone_result.repo_dir); + run_cargo_command(&[&"build", &"--release"], Some(repo_path), env, args)?; + run_cargo_command(&[&"test"], Some(repo_path), env, args)?; + } + + Ok(()) + }; + + let projects_path = Path::new("projects"); + create_dir_all(projects_path) + .map_err(|err| format!("Failed to create directory `projects`: {}", err))?; + + let nb_parts = args.nb_parts.unwrap_or(0); + if nb_parts > 0 { + // We increment the number of tests by one because if this is an odd number, we would skip + // one test. + let count = projects.len() / nb_parts + 1; + let current_part = args.current_part.unwrap(); + let start = current_part * count; + // We remove the projects we don't want to test. + run_tests(projects_path, &mut projects.iter().skip(start).take(count))?; + } + else { + run_tests(projects_path, &mut projects.iter())?; + } + + Ok(()) +} + fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] libcore"); diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index f0a07b597a0f4..85f1e18006caf 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -283,9 +283,10 @@ pub fn get_gcc_path() -> Result { pub struct CloneResult { pub ran_clone: bool, pub repo_name: String, + pub repo_dir: String, } -pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result { +pub fn git_clone(to_clone: &str, dest: Option<&Path>, shallow_clone: bool) -> Result { let repo_name = to_clone.split('/').last().unwrap(); let repo_name = match repo_name.strip_suffix(".git") { Some(n) => n.to_string(), @@ -299,13 +300,20 @@ pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result> = vec![&"git", &"clone", &to_clone, &dest]; + if shallow_clone { + command.push(&"--depth"); + command.push(&"1"); + } + run_command_with_output(&command, None)?; Ok(CloneResult { ran_clone: true, repo_name, + repo_dir: dest.display().to_string(), }) } From 2640b316e2e64dd1c4a79ba81bd2da809ad47d41 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Feb 2024 15:26:44 +0100 Subject: [PATCH 115/613] Switch to `config.toml` instead of `gcc-path` --- .gitignore | 1 + Readme.md | 22 ++++++-- build_system/Cargo.lock | 9 +++ build_system/Cargo.toml | 3 + build_system/src/build.rs | 25 +++++---- build_system/src/config.rs | 112 ++++++++++++++++++++++++++++++++++--- build_system/src/test.rs | 35 ++++++++---- build_system/src/utils.rs | 32 ----------- config.example.toml | 2 + 9 files changed, 173 insertions(+), 68 deletions(-) create mode 100644 config.example.toml diff --git a/.gitignore b/.gitignore index c865386dad306..687c3a6797af1 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ tools/llvmint-2 # The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics. llvm build_system/target +config.toml diff --git a/Readme.md b/Readme.md index 39ff41acf84ae..a380d0d5be6d1 100644 --- a/Readme.md +++ b/Readme.md @@ -49,17 +49,27 @@ $ make check-jit $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc" ``` -**Put the path to your custom build of libgccjit in the file `gcc_path`.** +**Put the path to your custom build of libgccjit in the file `config.toml`.** + +If you followed the instructions exactly as written (ie, you have created a `gcc-build` folder +where gcc is built), the only thing you need to do is: + +```bash +$ cp config.example.toml config.toml +``` + +But if you did something different, you also need to set the `gcc-path` value in `config.toml` with +the result of this command: ```bash -$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path +$ dirname $(readlink -f `find . -name libgccjit.so`) ``` Then you can run commands like this: ```bash $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking -$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release --features master +$ ./y.sh build --release --features master ``` To run the tests: @@ -100,7 +110,7 @@ error: failed to copy bitcode to object file: No such file or directory (os erro > You should prefer using the Cargo method. ```bash -$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs +$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs ``` ## Env vars @@ -322,7 +332,7 @@ generate it in [gimple.md](./doc/gimple.md). #### Configuring rustc_codegen_gcc * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. - * Set the path to the cross-compiling libgccjit in `gcc_path`. + * Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`). * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`. * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`. @@ -338,4 +348,4 @@ If you get the following error: /usr/bin/ld: unrecognised emulation mode: m68kelf ``` -Make sure you set `gcc_path` to the install directory. +Make sure you set `gcc-path` (in `config.toml`) to the install directory. diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index 86268e1916030..e727561a2bfba 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "boml" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5" + [[package]] name = "y" version = "0.1.0" +dependencies = [ + "boml", +] diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml index f36709ea03605..d2600ed5a0314 100644 --- a/build_system/Cargo.toml +++ b/build_system/Cargo.toml @@ -3,6 +3,9 @@ name = "y" version = "0.1.0" edition = "2021" +[dependencies] +boml = "0.3.1" + [[bin]] name = "y" path = "src/main.rs" diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 3149560b458a8..efae5a46b04f9 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -1,5 +1,5 @@ use crate::config::{Channel, ConfigInfo}; -use crate::utils::{get_gcc_path, run_command, run_command_with_output_and_env, walk_dir}; +use crate::utils::{run_command, run_command_with_output_and_env, walk_dir}; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; @@ -8,17 +8,12 @@ use std::path::Path; #[derive(Default)] struct BuildArg { flags: Vec, - gcc_path: String, config_info: ConfigInfo, } impl BuildArg { fn new() -> Result, String> { - let gcc_path = get_gcc_path()?; - let mut build_arg = Self { - gcc_path, - ..Default::default() - }; + let mut build_arg = Self::default(); // We skip binary name and the `build` command. let mut args = std::env::args().skip(2); @@ -169,7 +164,8 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu fs::create_dir_all(&sysroot_src_path).map_err(|error| { format!( "Failed to create directory `{}`: {:?}", - sysroot_src_path.display(), error + sysroot_src_path.display(), + error ) })?; run_command( @@ -188,8 +184,14 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu fn build_codegen(args: &mut BuildArg) -> Result<(), String> { let mut env = HashMap::new(); - env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); - env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); + env.insert( + "LD_LIBRARY_PATH".to_string(), + args.config_info.gcc_path.clone(), + ); + env.insert( + "LIBRARY_PATH".to_string(), + args.config_info.gcc_path.clone(), + ); let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; if args.config_info.channel == Channel::Release { @@ -205,7 +207,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, Some(&args.gcc_path))?; + args.config_info.setup(&mut env, None)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); @@ -227,6 +229,7 @@ pub fn run() -> Result<(), String> { Some(args) => args, None => return Ok(()), }; + args.config_info.setup_gcc_path(None)?; build_codegen(&mut args)?; Ok(()) } diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 1824bdd292ffa..09fa3ee9d3b9c 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -1,7 +1,11 @@ -use crate::utils::{get_gcc_path, get_os_name, rustc_version_info, split_args}; +use crate::utils::{get_os_name, rustc_version_info, split_args}; use std::collections::HashMap; use std::env as std_env; use std::ffi::OsStr; +use std::fs; +use std::path::Path; + +use boml::{types::TomlValue, Toml}; #[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] pub enum Channel { @@ -19,6 +23,72 @@ impl Channel { } } +fn failed_config_parsing(err: &str) -> Result { + Err(format!( + "Failed to parse `{}`: {}", + ConfigFile::CONFIG_FILE, + err + )) +} + +#[derive(Default)] +pub struct ConfigFile { + gcc_path: Option, + download_gccjit: Option, +} + +impl ConfigFile { + pub const CONFIG_FILE: &'static str = "config.toml"; + + pub fn new() -> Result { + let content = fs::read_to_string(Self::CONFIG_FILE).map_err(|_| { + format!( + "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project", + Self::CONFIG_FILE, + ) + })?; + let toml = Toml::parse(&content).map_err(|err| { + format!( + "Error occurred around `{}`: {:?}", + &content[err.start..=err.end], + err.kind + ) + })?; + let mut config = Self::default(); + for (key, value) in toml.iter() { + match (key, value) { + ("gcc-path", TomlValue::String(value)) => { + config.gcc_path = Some(value.as_str().to_string()) + } + ("gcc-path", _) => { + return failed_config_parsing("Expected a string for `gcc-path`") + } + ("download-gccjit", TomlValue::Boolean(value)) => { + config.download_gccjit = Some(*value) + } + ("download-gccjit", _) => { + return failed_config_parsing("Expected a boolean for `download-gccjit`") + } + _ => return failed_config_parsing(&format!("Unknown key `{}`", key)), + } + } + if config.gcc_path.is_none() && config.download_gccjit.is_none() { + return failed_config_parsing( + "At least one of `gcc-path` or `download-gccjit` value must be set", + ); + } + if let Some(gcc_path) = config.gcc_path.as_mut() { + let path = Path::new(gcc_path); + *gcc_path = path + .canonicalize() + .map_err(|err| format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err))? + .display() + .to_string(); + } + Ok(config) + } +} + #[derive(Default, Debug)] pub struct ConfigInfo { pub target: String, @@ -33,6 +103,7 @@ pub struct ConfigInfo { pub sysroot_panic_abort: bool, pub cg_backend_path: String, pub sysroot_path: String, + pub gcc_path: String, } impl ConfigInfo { @@ -80,18 +151,43 @@ impl ConfigInfo { command } + pub fn setup_gcc_path(&mut self, override_gcc_path: Option<&str>) -> Result<(), String> { + let ConfigFile { gcc_path, .. } = ConfigFile::new()?; + + self.gcc_path = match override_gcc_path { + Some(path) => { + if gcc_path.is_some() { + println!("overriding setting from `{}`", ConfigFile::CONFIG_FILE); + } + path.to_string() + } + None => { + match gcc_path { + Some(path) => path, + // FIXME: Once we support "download", rewrite this. + None => { + return Err(format!( + "missing `gcc-path` value from `{}`", + ConfigFile::CONFIG_FILE + )) + } + } + } + }; + Ok(()) + } + pub fn setup( &mut self, env: &mut HashMap, - gcc_path: Option<&str>, + override_gcc_path: Option<&str>, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - let gcc_path = match gcc_path { - Some(path) => path.to_string(), - None => get_gcc_path()?, - }; - env.insert("GCC_PATH".to_string(), gcc_path.clone()); + if self.gcc_path.is_empty() || override_gcc_path.is_some() { + self.setup_gcc_path(override_gcc_path)?; + } + env.insert("GCC_PATH".to_string(), self.gcc_path.clone()); if self.cargo_target_dir.is_empty() { match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) { @@ -225,7 +321,9 @@ impl ConfigInfo { // line option to change it. target = current_dir.join("target/out").display(), sysroot = sysroot.display(), + gcc_path = self.gcc_path, ); + env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone()); env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path); diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 6564322924318..1cacd6efc7fee 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,7 +1,7 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ - get_gcc_path, get_toolchain, git_clone, remove_file, run_command, run_command_with_env, + get_toolchain, git_clone, remove_file, run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, }; @@ -109,7 +109,7 @@ fn show_usage() { struct TestArg { no_default_features: bool, build_only: bool, - gcc_path: String, + gcc_path: Option, runners: BTreeSet, flags: Vec, backend: Option, @@ -181,12 +181,10 @@ impl TestArg { } } - test_arg.gcc_path = if use_system_gcc { + if use_system_gcc { println!("Using system GCC"); - "gcc".to_string() - } else { - get_gcc_path()? - }; + test_arg.gcc_path = Some("gcc".to_string()); + } } match (test_arg.current_part, test_arg.nb_parts) { (Some(_), Some(_)) | (None, None) => {} @@ -488,7 +486,8 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { } fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { - let toolchain = format!("+{channel}-{host}", + let toolchain = format!( + "+{channel}-{host}", channel = get_toolchain()?, // May also include date host = args.config_info.host_triple ); @@ -527,7 +526,12 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { } })?; let rustc = String::from_utf8( - run_command_with_env(&[&"rustup", &toolchain, &"which", &"rustc"], rust_dir, Some(env))?.stdout, + run_command_with_env( + &[&"rustup", &toolchain, &"which", &"rustc"], + rust_dir, + Some(env), + )? + .stdout, ) .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error)) .and_then(|rustc| { @@ -1162,8 +1166,15 @@ pub fn run() -> Result<(), String> { }; let mut env: HashMap = std::env::vars().collect(); - env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); - env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); + args.config_info.setup_gcc_path(None)?; + env.insert( + "LIBRARY_PATH".to_string(), + args.config_info.gcc_path.clone(), + ); + env.insert( + "LD_LIBRARY_PATH".to_string(), + args.config_info.gcc_path.clone(), + ); build_if_no_backend(&env, &args)?; if args.build_only { @@ -1171,7 +1182,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, Some(&args.gcc_path))?; + args.config_info.setup(&mut env, args.gcc_path.as_deref())?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 85f1e18006caf..b288eff94a5d4 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -248,38 +248,6 @@ pub fn get_toolchain() -> Result { } } -pub fn get_gcc_path() -> Result { - let content = match fs::read_to_string("gcc_path") { - Ok(content) => content, - Err(_) => { - return Err( - "Please put the path to your custom build of libgccjit in the file \ - `gcc_path`, see Readme.md for details" - .into(), - ) - } - }; - match content - .split('\n') - .map(|line| line.trim()) - .filter(|line| !line.is_empty()) - .next() - { - Some(gcc_path) => { - let path = Path::new(gcc_path); - if !path.exists() { - Err(format!( - "Path `{}` contained in the `gcc_path` file doesn't exist", - gcc_path, - )) - } else { - Ok(gcc_path.into()) - } - } - None => Err("No path found in `gcc_path` file".into()), - } -} - pub struct CloneResult { pub ran_clone: bool, pub repo_name: String, diff --git a/config.example.toml b/config.example.toml new file mode 100644 index 0000000000000..dcc414b731001 --- /dev/null +++ b/config.example.toml @@ -0,0 +1,2 @@ +gcc-path = "gcc-build/gcc" +# download-gccjit = true From 0b2402fdfcf0f126abb3c2f2ce11fd8ac79f5c38 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Feb 2024 16:47:28 +0100 Subject: [PATCH 116/613] Update CI scripts to work with `config.toml` --- .github/workflows/ci.yml | 6 +++--- .github/workflows/failures.yml | 11 +++++++---- .github/workflows/gcc12.yml | 6 +++--- .github/workflows/m68k.yml | 6 +++--- .github/workflows/release.yml | 6 +++--- .github/workflows/stdarch.yml | 6 +++--- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 426eabdd176b9..ba64f40acc4ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,13 +55,13 @@ jobs: - name: Setup path to libgccjit run: | sudo dpkg --force-overwrite -i gcc-13.deb - echo /usr/lib/ > gcc_path + echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env run: | - echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV #- name: Cache rust repository ## We only clone the rust repository for rustc tests diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index 7aaf47facd87f..ae00a257e2486 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -52,7 +52,10 @@ jobs: - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc == 'libgccjit12.so' - run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path + run: | + echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml + echo "LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV - name: Download artifact if: matrix.libgccjit_version.gcc != 'libgccjit12.so' @@ -62,12 +65,12 @@ jobs: if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: | sudo dpkg --force-overwrite -i gcc-13.deb - echo /usr/lib/ > gcc_path + echo 'gcc-path = "/usr/lib"' > config.toml + echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV - name: Set env run: | - echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV #- name: Cache rust repository diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 8d4f88ea7b1a4..f7bb156049233 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -47,13 +47,13 @@ jobs: run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev - name: Setup path to libgccjit - run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path + run: echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml - name: Set env run: | - echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + echo "LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV #- name: Cache rust repository ## We only clone the rust repository for rustc tests diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index b0866bafb8e31..2428125483bdd 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -65,13 +65,13 @@ jobs: - name: Setup path to libgccjit run: | sudo dpkg -i gcc-m68k-13.deb - echo /usr/lib/ > gcc_path + echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env run: | - echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV #- name: Cache rust repository ## We only clone the rust repository for rustc tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7628fd6557166..729a76e80bf90 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,13 +42,13 @@ jobs: - name: Setup path to libgccjit run: | sudo dpkg --force-overwrite -i gcc-13.deb - echo /usr/lib/ > gcc_path + echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env run: | - echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV - name: Build run: | diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index a5c3a5456bd7f..65687756cd4eb 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -56,13 +56,13 @@ jobs: - name: Setup path to libgccjit run: | sudo dpkg --force-overwrite -i gcc-13.deb - echo /usr/lib/ > gcc_path + echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env run: | - echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV - name: Build run: | From 79241b8a4e511a4e59761477c0bdffea24bd7201 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Feb 2024 17:00:37 +0100 Subject: [PATCH 117/613] Update tests to use `config.toml` instead --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + tests/lang_tests_common.rs | 13 +++++++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26dc7c535f854..a19de10d0d29b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,12 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "boml" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5" + [[package]] name = "cc" version = "1.0.79" @@ -185,6 +191,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" name = "rustc_codegen_gcc" version = "0.1.0" dependencies = [ + "boml", "gccjit", "lang_tester", "object", diff --git a/Cargo.toml b/Cargo.toml index b0b3aeecdbdfd..a280ac73de093 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ tempfile = "3.7.1" [dev-dependencies] lang_tester = "0.3.9" tempfile = "3.1.0" +boml = "0.3.1" [profile.dev] # By compiling dependencies with optimizations, performing tests gets much faster. diff --git a/tests/lang_tests_common.rs b/tests/lang_tests_common.rs index af0133aad461d..029a3b98ff23a 100644 --- a/tests/lang_tests_common.rs +++ b/tests/lang_tests_common.rs @@ -7,6 +7,7 @@ use std::{ use lang_tester::LangTester; use tempfile::TempDir; +use boml::Toml; /// Controls the compile options (e.g., optimization level) used to compile /// test code. @@ -20,8 +21,16 @@ pub fn main_inner(profile: Profile) { let tempdir = TempDir::new().expect("temp dir"); let current_dir = current_dir().expect("current dir"); let current_dir = current_dir.to_str().expect("current dir").to_string(); - let gcc_path = include_str!("../gcc_path"); - let gcc_path = gcc_path.trim(); + let gcc_path = Toml::parse(include_str!("../config.toml")) + .expect("Failed to parse `config.toml`") + .get_string("gcc-path") + .expect("Missing `gcc-path` key in `config.toml`") + .to_string(); + let gcc_path = Path::new(&gcc_path) + .canonicalize() + .expect("failed to get absolute path of `gcc-path`") + .display() + .to_string(); env::set_var("LD_LIBRARY_PATH", gcc_path); fn rust_filter(filename: &Path) -> bool { From de9d1b63b4b1bde72baee556c833fb9fe73e013b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Feb 2024 17:37:56 +0100 Subject: [PATCH 118/613] Add `--config-file` option to override default location of `config.toml` --- build_system/src/config.rs | 48 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 09fa3ee9d3b9c..5ba6233617ec5 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -23,12 +23,8 @@ impl Channel { } } -fn failed_config_parsing(err: &str) -> Result { - Err(format!( - "Failed to parse `{}`: {}", - ConfigFile::CONFIG_FILE, - err - )) +fn failed_config_parsing(config_file: &str, err: &str) -> Result { + Err(format!("Failed to parse `{}`: {}", config_file, err)) } #[derive(Default)] @@ -38,13 +34,12 @@ pub struct ConfigFile { } impl ConfigFile { - pub const CONFIG_FILE: &'static str = "config.toml"; - - pub fn new() -> Result { - let content = fs::read_to_string(Self::CONFIG_FILE).map_err(|_| { + pub fn new(config_file: Option<&str>) -> Result { + let config_file = config_file.unwrap_or("config.toml"); + let content = fs::read_to_string(config_file).map_err(|_| { format!( "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project", - Self::CONFIG_FILE, + config_file, ) })?; let toml = Toml::parse(&content).map_err(|err| { @@ -61,19 +56,23 @@ impl ConfigFile { config.gcc_path = Some(value.as_str().to_string()) } ("gcc-path", _) => { - return failed_config_parsing("Expected a string for `gcc-path`") + return failed_config_parsing(config_file, "Expected a string for `gcc-path`") } ("download-gccjit", TomlValue::Boolean(value)) => { config.download_gccjit = Some(*value) } ("download-gccjit", _) => { - return failed_config_parsing("Expected a boolean for `download-gccjit`") + return failed_config_parsing( + config_file, + "Expected a boolean for `download-gccjit`", + ) } - _ => return failed_config_parsing(&format!("Unknown key `{}`", key)), + _ => return failed_config_parsing(config_file, &format!("Unknown key `{}`", key)), } } if config.gcc_path.is_none() && config.download_gccjit.is_none() { return failed_config_parsing( + config_file, "At least one of `gcc-path` or `download-gccjit` value must be set", ); } @@ -104,6 +103,7 @@ pub struct ConfigInfo { pub cg_backend_path: String, pub sysroot_path: String, pub gcc_path: String, + config_file: Option, } impl ConfigInfo { @@ -135,6 +135,14 @@ impl ConfigInfo { } _ => return Err("Expected a value after `--out-dir`, found nothing".to_string()), }, + "--config-file" => match args.next() { + Some(arg) if !arg.is_empty() => { + self.config_file = Some(arg.to_string()); + } + _ => { + return Err("Expected a value after `--config-file`, found nothing".to_string()) + } + }, "--release-sysroot" => self.sysroot_release_channel = true, "--release" => self.channel = Channel::Release, "--sysroot-panic-abort" => self.sysroot_panic_abort = true, @@ -152,12 +160,15 @@ impl ConfigInfo { } pub fn setup_gcc_path(&mut self, override_gcc_path: Option<&str>) -> Result<(), String> { - let ConfigFile { gcc_path, .. } = ConfigFile::new()?; + let ConfigFile { gcc_path, .. } = ConfigFile::new(self.config_file.as_deref())?; self.gcc_path = match override_gcc_path { Some(path) => { if gcc_path.is_some() { - println!("overriding setting from `{}`", ConfigFile::CONFIG_FILE); + println!( + "overriding setting from `{}`", + self.config_file.as_deref().unwrap_or("config.toml") + ); } path.to_string() } @@ -168,7 +179,7 @@ impl ConfigInfo { None => { return Err(format!( "missing `gcc-path` value from `{}`", - ConfigFile::CONFIG_FILE + self.config_file.as_deref().unwrap_or("config.toml"), )) } } @@ -363,7 +374,8 @@ impl ConfigInfo { --out-dir : Location where the files will be generated --release : Build in release mode --release-sysroot : Build sysroot in release mode - --sysroot-panic-abort : Build the sysroot without unwinding support." + --sysroot-panic-abort : Build the sysroot without unwinding support + --config-file : Location of the config file to be used" ); } } From 588db24344dc2b626bb050067e9e6cda2de3bc59 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Feb 2024 14:41:18 +0100 Subject: [PATCH 119/613] Correctly handle `--use-system-gcc` --- build_system/src/build.rs | 4 ++-- build_system/src/cargo.rs | 2 +- build_system/src/config.rs | 35 ++++++++++------------------- build_system/src/test.rs | 45 +++++++++++++++++++------------------- build_system/src/utils.rs | 6 ++++- 5 files changed, 42 insertions(+), 50 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index efae5a46b04f9..308ad34654941 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -207,7 +207,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, None)?; + args.config_info.setup(&mut env, false)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); @@ -229,7 +229,7 @@ pub fn run() -> Result<(), String> { Some(args) => args, None => return Ok(()), }; - args.config_info.setup_gcc_path(None)?; + args.config_info.setup_gcc_path()?; build_codegen(&mut args)?; Ok(()) } diff --git a/build_system/src/cargo.rs b/build_system/src/cargo.rs index 67b301d9aa646..1cfcdba6b1cd1 100644 --- a/build_system/src/cargo.rs +++ b/build_system/src/cargo.rs @@ -77,7 +77,7 @@ pub fn run() -> Result<(), String> { })?; let mut env: HashMap = std::env::vars().collect(); - ConfigInfo::default().setup(&mut env, None)?; + ConfigInfo::default().setup(&mut env, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 5ba6233617ec5..49782fc64ef70 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -159,30 +159,17 @@ impl ConfigInfo { command } - pub fn setup_gcc_path(&mut self, override_gcc_path: Option<&str>) -> Result<(), String> { + pub fn setup_gcc_path(&mut self) -> Result<(), String> { let ConfigFile { gcc_path, .. } = ConfigFile::new(self.config_file.as_deref())?; - self.gcc_path = match override_gcc_path { - Some(path) => { - if gcc_path.is_some() { - println!( - "overriding setting from `{}`", - self.config_file.as_deref().unwrap_or("config.toml") - ); - } - path.to_string() - } + self.gcc_path = match gcc_path { + Some(path) => path, + // FIXME: Once we support "download", rewrite this. None => { - match gcc_path { - Some(path) => path, - // FIXME: Once we support "download", rewrite this. - None => { - return Err(format!( - "missing `gcc-path` value from `{}`", - self.config_file.as_deref().unwrap_or("config.toml"), - )) - } - } + return Err(format!( + "missing `gcc-path` value from `{}`", + self.config_file.as_deref().unwrap_or("config.toml"), + )) } }; Ok(()) @@ -191,12 +178,12 @@ impl ConfigInfo { pub fn setup( &mut self, env: &mut HashMap, - override_gcc_path: Option<&str>, + use_system_gcc: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - if self.gcc_path.is_empty() || override_gcc_path.is_some() { - self.setup_gcc_path(override_gcc_path)?; + if self.gcc_path.is_empty() && !use_system_gcc { + self.setup_gcc_path()?; } env.insert("GCC_PATH".to_string(), self.gcc_path.clone()); diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1cacd6efc7fee..806e18431c46d 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -31,7 +31,10 @@ fn get_runners() -> Runners { "--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc), ); - runners.insert("--projects", ("Run the tests of popular crates", test_projects)); + runners.insert( + "--projects", + ("Run the tests of popular crates", test_projects), + ); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); @@ -109,7 +112,7 @@ fn show_usage() { struct TestArg { no_default_features: bool, build_only: bool, - gcc_path: Option, + use_system_gcc: bool, runners: BTreeSet, flags: Vec, backend: Option, @@ -121,7 +124,6 @@ struct TestArg { impl TestArg { fn new() -> Result, String> { - let mut use_system_gcc = false; let mut test_arg = Self::default(); // We skip binary name and the `test` command. @@ -147,7 +149,10 @@ impl TestArg { return Err("Expected an argument after `--features`, found nothing".into()) } }, - "--use-system-gcc" => use_system_gcc = true, + "--use-system-gcc" => { + println!("Using system GCC"); + test_arg.use_system_gcc = true; + } "--build-only" => test_arg.build_only = true, "--use-backend" => match args.next() { Some(backend) if !backend.is_empty() => test_arg.backend = Some(backend), @@ -180,11 +185,6 @@ impl TestArg { } } } - - if use_system_gcc { - println!("Using system GCC"); - test_arg.gcc_path = Some("gcc".to_string()); - } } match (test_arg.current_part, test_arg.nb_parts) { (Some(_), Some(_)) | (None, None) => {} @@ -703,7 +703,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { //"https://github.com/rust-lang/cargo", // TODO: very slow, only run on master? ]; - let run_tests = |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { + let run_tests = |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { for project in iter { let clone_result = git_clone(project, Some(projects_path), true)?; let repo_path = Path::new(&clone_result.repo_dir); @@ -727,8 +727,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let start = current_part * count; // We remove the projects we don't want to test. run_tests(projects_path, &mut projects.iter().skip(start).take(count))?; - } - else { + } else { run_tests(projects_path, &mut projects.iter())?; } @@ -1166,15 +1165,17 @@ pub fn run() -> Result<(), String> { }; let mut env: HashMap = std::env::vars().collect(); - args.config_info.setup_gcc_path(None)?; - env.insert( - "LIBRARY_PATH".to_string(), - args.config_info.gcc_path.clone(), - ); - env.insert( - "LD_LIBRARY_PATH".to_string(), - args.config_info.gcc_path.clone(), - ); + if !args.use_system_gcc { + args.config_info.setup_gcc_path()?; + env.insert( + "LIBRARY_PATH".to_string(), + args.config_info.gcc_path.clone(), + ); + env.insert( + "LD_LIBRARY_PATH".to_string(), + args.config_info.gcc_path.clone(), + ); + } build_if_no_backend(&env, &args)?; if args.build_only { @@ -1182,7 +1183,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.gcc_path.as_deref())?; + args.config_info.setup(&mut env, args.use_system_gcc)?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index b288eff94a5d4..046008ae1a247 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -254,7 +254,11 @@ pub struct CloneResult { pub repo_dir: String, } -pub fn git_clone(to_clone: &str, dest: Option<&Path>, shallow_clone: bool) -> Result { +pub fn git_clone( + to_clone: &str, + dest: Option<&Path>, + shallow_clone: bool, +) -> Result { let repo_name = to_clone.split('/').last().unwrap(); let repo_name = match repo_name.strip_suffix(".git") { Some(n) => n.to_string(), From 3669dba8e8dc8895ac3e396b03b462c3bad51eb5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 12 Feb 2024 16:58:51 +0000 Subject: [PATCH 120/613] Rustup to rustc 1.78.0-nightly (1a648b397 2024-02-11) --- build_system/tests.rs | 4 ++-- patches/0022-coretests-Disable-not-compiling-tests.patch | 2 +- patches/stdlib-lock.toml | 5 +++-- rust-toolchain | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 818f3d6f08d26..31d1de600d163 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -133,8 +133,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", - "97007cc2e70df8c97326ce896a79e2f0ce4dd98b", - "e54a16035cedf205", + "f505736e45e256efcb36bf85b7f920ccef320435", + "b012e6b58fa0f78d", "portable-simd", ); diff --git a/patches/0022-coretests-Disable-not-compiling-tests.patch b/patches/0022-coretests-Disable-not-compiling-tests.patch index 6afa5c71fe51f..5442c3cef9ec2 100644 --- a/patches/0022-coretests-Disable-not-compiling-tests.patch +++ b/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -39,6 +39,6 @@ index 42a26ae..5ac1042 100644 +#![cfg(test)] #![feature(alloc_layout_extra)] #![feature(array_chunks)] - #![feature(array_methods)] + #![feature(array_windows)] -- 2.21.0 (Apple Git-122) diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index ad63b0768d313..86f95fba96bd9 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" dependencies = [ "rustc-std-workspace-core", ] @@ -398,6 +398,7 @@ version = "0.0.0" dependencies = [ "core", "getopts", + "libc", "panic_abort", "panic_unwind", "std", diff --git a/rust-toolchain b/rust-toolchain index cb1e12e8c72dd..6328830897065 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-27" +channel = "nightly-2024-02-12" components = ["rust-src", "rustc-dev", "llvm-tools"] From a51b61a8b6da2e80c268f368943ab22b762d8b23 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 14:29:12 +0000 Subject: [PATCH 121/613] Add intrinsic body fallback to cranelift and use it --- src/abi/mod.rs | 10 +++++--- src/intrinsics/mod.rs | 57 +++++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 0f0d828c8fc3f..fd1f081a0a8e7 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -387,15 +387,19 @@ pub(crate) fn codegen_terminator_call<'tcx>( match instance.def { InstanceDef::Intrinsic(_) => { - crate::intrinsics::codegen_intrinsic_call( + match crate::intrinsics::codegen_intrinsic_call( fx, instance, args, ret_place, target, source_info, - ); - return; + ) { + Ok(()) => return, + // Unimplemented intrinsics must have a fallback body. The fallback body is obtained + // by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`. + Err(()) => Some(Instance::new(instance.def_id(), instance.args)), + } } InstanceDef::DropGlue(_, None) => { // empty drop glue - a nop. diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 819cb5ef137ce..5e64fec76e456 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -268,7 +268,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( destination: CPlace<'tcx>, target: Option, source_info: mir::SourceInfo, -) { +) -> Result<(), ()> { let intrinsic = fx.tcx.item_name(instance.def_id()); let instance_args = instance.args; @@ -295,8 +295,9 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( destination, target, source_info, - ); + )?; } + Ok(()) } fn codegen_float_intrinsic_call<'tcx>( @@ -430,25 +431,20 @@ fn codegen_regular_intrinsic_call<'tcx>( ret: CPlace<'tcx>, destination: Option, source_info: mir::SourceInfo, -) { +) -> Result<(), ()> { + assert_eq!(generic_args, instance.args); let usize_layout = fx.layout_of(fx.tcx.types.usize); match intrinsic { sym::abort => { fx.bcx.ins().trap(TrapCode::User(0)); - return; + return Ok(()); } sym::likely | sym::unlikely => { intrinsic_args!(fx, args => (a); intrinsic); ret.write_cvalue(fx, a); } - sym::is_val_statically_known => { - intrinsic_args!(fx, args => (_a); intrinsic); - - let res = fx.bcx.ins().iconst(types::I8, 0); - ret.write_cvalue(fx, CValue::by_val(res, ret.layout())); - } sym::breakpoint => { intrinsic_args!(fx, args => (); intrinsic); @@ -697,7 +693,7 @@ fn codegen_regular_intrinsic_call<'tcx>( }) }); crate::base::codegen_panic_nounwind(fx, &msg_str, Some(source_info.span)); - return; + return Ok(()); } } } @@ -792,7 +788,7 @@ fn codegen_regular_intrinsic_call<'tcx>( if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); - return; + return Ok(()); } else { fx.tcx .dcx() @@ -802,7 +798,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, ty); - return; + return Ok(()); } } let clif_ty = fx.clif_type(ty).unwrap(); @@ -823,7 +819,7 @@ fn codegen_regular_intrinsic_call<'tcx>( if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); - return; + return Ok(()); } else { fx.tcx .dcx() @@ -833,7 +829,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, ty); - return; + return Ok(()); } } @@ -850,7 +846,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -872,7 +868,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } @@ -895,7 +891,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -917,7 +913,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -939,7 +935,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -960,7 +956,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -981,7 +977,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -1002,7 +998,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -1023,7 +1019,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -1044,7 +1040,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -1065,7 +1061,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -1086,7 +1082,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} _ => { report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty); - return; + return Ok(()); } } let ty = fx.clif_type(layout.ty).unwrap(); @@ -1261,13 +1257,10 @@ fn codegen_regular_intrinsic_call<'tcx>( ); } - _ => { - fx.tcx - .dcx() - .span_fatal(source_info.span, format!("unsupported intrinsic {}", intrinsic)); - } + _ => return Err(()), } let ret_block = fx.get_block(destination.unwrap()); fx.bcx.ins().jump(ret_block, &[]); + Ok(()) } From bd14c7b8e5ce6bb521943a8dcb55ce2b22b828e9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 20:39:59 +0000 Subject: [PATCH 122/613] Teach llvm backend how to fall back to default bodies --- src/abi/mod.rs | 4 +--- src/intrinsics/mod.rs | 16 +++++----------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index fd1f081a0a8e7..6e846d721f2e2 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -396,9 +396,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( source_info, ) { Ok(()) => return, - // Unimplemented intrinsics must have a fallback body. The fallback body is obtained - // by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`. - Err(()) => Some(Instance::new(instance.def_id(), instance.args)), + Err(instance) => Some(instance), } } InstanceDef::DropGlue(_, None) => { diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 5e64fec76e456..210a3da2c5d9d 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -268,7 +268,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( destination: CPlace<'tcx>, target: Option, source_info: mir::SourceInfo, -) -> Result<(), ()> { +) -> Result<(), Instance<'tcx>> { let intrinsic = fx.tcx.item_name(instance.def_id()); let instance_args = instance.args; @@ -431,7 +431,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ret: CPlace<'tcx>, destination: Option, source_info: mir::SourceInfo, -) -> Result<(), ()> { +) -> Result<(), Instance<'tcx>> { assert_eq!(generic_args, instance.args); let usize_layout = fx.layout_of(fx.tcx.types.usize); @@ -1229,14 +1229,6 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, CValue::by_val(cmp, ret.layout())); } - sym::const_allocate => { - intrinsic_args!(fx, args => (_size, _align); intrinsic); - - // returns a null pointer at runtime. - let null = fx.bcx.ins().iconst(fx.pointer_type, 0); - ret.write_cvalue(fx, CValue::by_val(null, ret.layout())); - } - sym::const_deallocate => { intrinsic_args!(fx, args => (_ptr, _size, _align); intrinsic); // nop at runtime. @@ -1257,7 +1249,9 @@ fn codegen_regular_intrinsic_call<'tcx>( ); } - _ => return Err(()), + // Unimplemented intrinsics must have a fallback body. The fallback body is obtained + // by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`. + _ => return Err(Instance::new(instance.def_id(), instance.args)), } let ret_block = fx.get_block(destination.unwrap()); From 64dfa4f455ed72e1c17a82fa67a577b869ed5992 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 20:39:59 +0000 Subject: [PATCH 123/613] Teach llvm backend how to fall back to default bodies --- src/intrinsic/mod.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index eac8cb437794b..f162ef831b768 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -90,7 +90,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) -> } impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], llresult: RValue<'gcc>, span: Span) { + fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], llresult: RValue<'gcc>, span: Span) -> Result<(), Instance<'tcx>> { let tcx = self.tcx; let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); @@ -137,7 +137,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { args[2].immediate(), llresult, ); - return; + return Ok(()); } sym::breakpoint => { unimplemented!(); @@ -166,12 +166,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { sym::volatile_store => { let dst = args[0].deref(self.cx()); args[1].val.volatile_store(self, dst); - return; + return Ok(()); } sym::unaligned_volatile_store => { let dst = args[0].deref(self.cx()); args[1].val.unaligned_volatile_store(self, dst); - return; + return Ok(()); } sym::prefetch_read_data | sym::prefetch_write_data @@ -269,7 +269,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { }, None => { tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); - return; + return Ok(()); } } } @@ -339,7 +339,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { extended_asm.set_volatile_flag(true); // We have copied the value to `result` already. - return; + return Ok(()); } sym::ptr_mask => { @@ -357,11 +357,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { _ if name_str.starts_with("simd_") => { match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) { Ok(llval) => llval, - Err(()) => return, + Err(()) => return Ok(()), } } - _ => bug!("unknown intrinsic '{}'", name), + // Fall back to default body + _ => return Err(Instance::new(instance.def_id(), instance.args)), }; if !fn_abi.ret.is_ignore() { @@ -376,6 +377,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { .store(self, result); } } + Ok(()) } fn abort(&mut self) { From aa6d02f3681eb7d0f60a27eda4efe7cee56ca196 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jan 2024 20:51:29 +0000 Subject: [PATCH 124/613] Give const_deallocate a default body --- src/intrinsics/mod.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 210a3da2c5d9d..476752c7230a7 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1229,11 +1229,6 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, CValue::by_val(cmp, ret.layout())); } - sym::const_deallocate => { - intrinsic_args!(fx, args => (_ptr, _size, _align); intrinsic); - // nop at runtime. - } - sym::black_box => { intrinsic_args!(fx, args => (a); intrinsic); From 5d5137cebce6c3906238fd82d728017cac89a5c4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 12 Feb 2024 21:20:12 -0400 Subject: [PATCH 125/613] Rework the download function to only contain the platform-specific code --- build_system/src/config.rs | 156 ++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 475f9b300f74c..c9bfcb9e6ba47 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -190,83 +190,6 @@ impl ConfigInfo { command } - fn download_gccjit( - &self, - output_dir: &Path, - libgccjit_so_name: &str, - commit: &str, - ) -> Result<(), String> { - // Download time! - let tempfile_name = format!("{}.download", libgccjit_so_name); - let tempfile = output_dir.join(&tempfile_name); - let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok(); - - let url = format!( - "https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so", - commit, - ); - - println!("Downloading `{}`...", url); - // Try curl. If that fails and we are on windows, fallback to PowerShell. - let mut ret = run_command_with_output( - &[ - &"curl", - &"--speed-time", - &"30", - &"--speed-limit", - &"10", // timeout if speed is < 10 bytes/sec for > 30 seconds - &"--connect-timeout", - &"30", // timeout if cannot connect within 30 seconds - &"-o", - &tempfile_name, - &"--retry", - &"3", - &"-SRfL", - if is_in_ci { &"-s" } else { &"--progress-bar" }, - &url.as_str(), - ], - Some(&output_dir), - ); - if ret.is_err() && cfg!(windows) { - eprintln!("Fallback to PowerShell"); - ret = run_command_with_output( - &[ - &"PowerShell.exe", - &"/nologo", - &"-Command", - &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", - &format!( - "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", - url, - tempfile_name, - ).as_str(), - ], - Some(&output_dir), - ); - } - ret?; - - let libgccjit_so = output_dir.join(libgccjit_so_name); - // If we reach this point, it means the file was correctly downloaded, so let's - // rename it! - std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| { - format!( - "Failed to rename `{}` into `{}`: {:?}", - tempfile.display(), - libgccjit_so.display(), - err, - ) - })?; - - println!("Downloaded libgccjit.so version {} successfully!", commit); - // We need to create a link named `libgccjit.so.0` because that's what the linker is - // looking for. - create_symlink( - &libgccjit_so, - output_dir.join(&format!("{}.0", libgccjit_so_name)), - ) - } - fn download_gccjit_if_needed(&mut self) -> Result<(), String> { let output_dir = Path::new( std::env::var("CARGO_TARGET_DIR") @@ -313,7 +236,38 @@ impl ConfigInfo { let libgccjit_so_name = "libgccjit.so"; let libgccjit_so = output_dir.join(libgccjit_so_name); if !libgccjit_so.is_file() && !self.no_download { - self.download_gccjit(&output_dir, libgccjit_so_name, commit)?; + // Download time! + let tempfile_name = format!("{}.download", libgccjit_so_name); + let tempfile = output_dir.join(&tempfile_name); + let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok(); + + let url = format!( + "https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so", + commit, + ); + + println!("Downloading `{}`...", url); + download_gccjit(url, &output_dir, tempfile_name, !is_in_ci)?; + + let libgccjit_so = output_dir.join(libgccjit_so_name); + // If we reach this point, it means the file was correctly downloaded, so let's + // rename it! + std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| { + format!( + "Failed to rename `{}` into `{}`: {:?}", + tempfile.display(), + libgccjit_so.display(), + err, + ) + })?; + + println!("Downloaded libgccjit.so version {} successfully!", commit); + // We need to create a link named `libgccjit.so.0` because that's what the linker is + // looking for. + create_symlink( + &libgccjit_so, + output_dir.join(&format!("{}.0", libgccjit_so_name)), + )?; } self.gcc_path = output_dir.display().to_string(); @@ -547,3 +501,49 @@ impl ConfigInfo { ); } } + +fn download_gccjit( + url: String, + output_dir: &Path, + tempfile_name: String, + with_progress_bar: bool, +) -> Result<(), String> { + // Try curl. If that fails and we are on windows, fallback to PowerShell. + let mut ret = run_command_with_output( + &[ + &"curl", + &"--speed-time", + &"30", + &"--speed-limit", + &"10", // timeout if speed is < 10 bytes/sec for > 30 seconds + &"--connect-timeout", + &"30", // timeout if cannot connect within 30 seconds + &"-o", + &tempfile_name, + &"--retry", + &"3", + &"-SRfL", + if with_progress_bar { &"--progress-bar" } else { &"-s" }, + &url.as_str(), + ], + Some(&output_dir), + ); + if ret.is_err() && cfg!(windows) { + eprintln!("Fallback to PowerShell"); + ret = run_command_with_output( + &[ + &"PowerShell.exe", + &"/nologo", + &"-Command", + &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", + &format!( + "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", + url, + tempfile_name, + ).as_str(), + ], + Some(&output_dir), + ); + } + ret +} From eee04a48d9b0ba2ca7e18c6465c51a63feed8e08 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Feb 2024 18:07:05 +0100 Subject: [PATCH 126/613] Add support for "download" --- build_system/src/config.rs | 201 ++++++++++++++++++++++++++++++++----- libgccjit.version | 1 + 2 files changed, 178 insertions(+), 24 deletions(-) create mode 100644 libgccjit.version diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 49782fc64ef70..0201e3509dcd3 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -1,9 +1,9 @@ -use crate::utils::{get_os_name, rustc_version_info, split_args}; +use crate::utils::{get_os_name, run_command_with_output, rustc_version_info, split_args}; use std::collections::HashMap; use std::env as std_env; use std::ffi::OsStr; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use boml::{types::TomlValue, Toml}; @@ -23,8 +23,12 @@ impl Channel { } } -fn failed_config_parsing(config_file: &str, err: &str) -> Result { - Err(format!("Failed to parse `{}`: {}", config_file, err)) +fn failed_config_parsing(config_file: &Path, err: &str) -> Result { + Err(format!( + "Failed to parse `{}`: {}", + config_file.display(), + err + )) } #[derive(Default)] @@ -34,12 +38,11 @@ pub struct ConfigFile { } impl ConfigFile { - pub fn new(config_file: Option<&str>) -> Result { - let config_file = config_file.unwrap_or("config.toml"); + pub fn new(config_file: &Path) -> Result { let content = fs::read_to_string(config_file).map_err(|_| { format!( "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project", - config_file, + config_file.display(), ) })?; let toml = Toml::parse(&content).map_err(|err| { @@ -70,19 +73,30 @@ impl ConfigFile { _ => return failed_config_parsing(config_file, &format!("Unknown key `{}`", key)), } } - if config.gcc_path.is_none() && config.download_gccjit.is_none() { - return failed_config_parsing( - config_file, - "At least one of `gcc-path` or `download-gccjit` value must be set", - ); - } - if let Some(gcc_path) = config.gcc_path.as_mut() { - let path = Path::new(gcc_path); - *gcc_path = path - .canonicalize() - .map_err(|err| format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err))? - .display() - .to_string(); + match (config.gcc_path.as_mut(), config.download_gccjit) { + (None, None | Some(false)) => { + return failed_config_parsing( + config_file, + "At least one of `gcc-path` or `download-gccjit` value must be set", + ) + } + (Some(_), Some(true)) => { + println!( + "WARNING: both `gcc-path` and `download-gccjit` arguments are used, \ + ignoring `gcc-path`" + ); + } + (Some(gcc_path), _) => { + let path = Path::new(gcc_path); + *gcc_path = path + .canonicalize() + .map_err(|err| { + format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err) + })? + .display() + .to_string(); + } + _ => {} } Ok(config) } @@ -104,6 +118,7 @@ pub struct ConfigInfo { pub sysroot_path: String, pub gcc_path: String, config_file: Option, + cg_gcc_path: Option, } impl ConfigInfo { @@ -146,6 +161,14 @@ impl ConfigInfo { "--release-sysroot" => self.sysroot_release_channel = true, "--release" => self.channel = Channel::Release, "--sysroot-panic-abort" => self.sysroot_panic_abort = true, + "--cg_gcc-path" => match args.next() { + Some(arg) if !arg.is_empty() => { + self.cg_gcc_path = Some(arg.into()); + } + _ => { + return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string()) + } + }, _ => return Ok(false), } Ok(true) @@ -159,16 +182,144 @@ impl ConfigInfo { command } + fn download_gccjit_if_needed(&mut self) -> Result<(), String> { + let output_dir = Path::new( + std::env::var("CARGO_TARGET_DIR") + .as_deref() + .unwrap_or("target"), + ) + .join("libgccjit"); + + let commit_hash_file = self.compute_path("libgccjit.version"); + let content = fs::read_to_string(&commit_hash_file).map_err(|_| { + format!( + "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project", + commit_hash_file.display(), + ) + })?; + let commit = content.trim(); + if commit.contains('/') || commit.contains('\\') { + return Err(format!( + "{}: invalid commit hash `{}`", + commit_hash_file.display(), + commit + )); + } + let output_dir = output_dir.join(commit); + if !output_dir.is_dir() { + std::fs::create_dir_all(&output_dir).map_err(|err| { + format!( + "failed to create folder `{}`: {:?}", + output_dir.display(), + err, + ) + })?; + } + let libgccjit_so = output_dir.join("libgccjit.so"); + if !libgccjit_so.is_file() { + // Download time! + let tempfile_name = "libgccjit.so.download"; + let tempfile = output_dir.join(tempfile_name); + let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok(); + + let url = format!( + "https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so", + commit, + ); + + println!("Downloading `{}`...", url); + // Try curl. If that fails and we are on windows, fallback to PowerShell. + let mut ret = run_command_with_output( + &[ + &"curl", + &"--speed-time", + &"30", + &"--speed-limit", + &"10", // timeout if speed is < 10 bytes/sec for > 30 seconds + &"--connect-timeout", + &"30", // timeout if cannot connect within 30 seconds + &"-o", + &tempfile_name, + &"--retry", + &"3", + &"-SRfL", + if is_in_ci { &"-s" } else { &"--progress-bar" }, + &url.as_str(), + ], + Some(&output_dir), + ); + if ret.is_err() && cfg!(windows) { + eprintln!("Fallback to PowerShell"); + ret = run_command_with_output( + &[ + &"PowerShell.exe", + &"/nologo", + &"-Command", + &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", + &format!( + "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", + url, + tempfile_name, + ).as_str(), + ], + Some(&output_dir), + ); + } + ret?; + + // If we reach this point, it means the file was correctly downloaded, so let's + // rename it! + std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| { + format!( + "Failed to rename `{}` into `{}`: {:?}", + tempfile.display(), + libgccjit_so.display(), + err, + ) + })?; + + println!("Downloaded libgccjit.so version {} successfully!", commit); + } + + self.gcc_path = output_dir + .canonicalize() + .map_err(|err| { + format!( + "Failed to get absolute path of `{}`: {:?}", + output_dir.display(), + err + ) + })? + .display() + .to_string(); + println!("Using `{}` as path for libgccjit", self.gcc_path); + Ok(()) + } + + pub fn compute_path>(&self, other: P) -> PathBuf { + match self.cg_gcc_path { + Some(ref path) => path.join(other), + None => PathBuf::new().join(other), + } + } + pub fn setup_gcc_path(&mut self) -> Result<(), String> { - let ConfigFile { gcc_path, .. } = ConfigFile::new(self.config_file.as_deref())?; + let config_file = self.compute_path(self.config_file.as_deref().unwrap_or("config.toml")); + let ConfigFile { + gcc_path, + download_gccjit, + } = ConfigFile::new(&config_file)?; + if let Some(true) = download_gccjit { + self.download_gccjit_if_needed()?; + return Ok(()); + } self.gcc_path = match gcc_path { Some(path) => path, - // FIXME: Once we support "download", rewrite this. None => { return Err(format!( "missing `gcc-path` value from `{}`", - self.config_file.as_deref().unwrap_or("config.toml"), + config_file.display(), )) } }; @@ -362,7 +513,9 @@ impl ConfigInfo { --release : Build in release mode --release-sysroot : Build sysroot in release mode --sysroot-panic-abort : Build the sysroot without unwinding support - --config-file : Location of the config file to be used" + --config-file : Location of the config file to be used + --cg_gcc-path : Location of the rustc_codegen_gcc root folder (used + for accessing any file from the project)" ); } } diff --git a/libgccjit.version b/libgccjit.version new file mode 100644 index 0000000000000..3fc84f4ddd4ec --- /dev/null +++ b/libgccjit.version @@ -0,0 +1 @@ +2fc8940e1 From 0a4b0af141add015d1388c6b457530fcdd3f0316 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Feb 2024 20:09:54 +0100 Subject: [PATCH 127/613] Generate symbolic link to libgccjit.so as well --- build_system/src/config.rs | 17 +++++++++++++++-- build_system/src/utils.rs | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 0201e3509dcd3..a206bab14a9a8 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -1,4 +1,6 @@ -use crate::utils::{get_os_name, run_command_with_output, rustc_version_info, split_args}; +use crate::utils::{ + create_symlink, get_os_name, run_command_with_output, rustc_version_info, split_args, +}; use std::collections::HashMap; use std::env as std_env; use std::ffi::OsStr; @@ -215,7 +217,8 @@ impl ConfigInfo { ) })?; } - let libgccjit_so = output_dir.join("libgccjit.so"); + let libgccjit_so_name = "libgccjit.so"; + let libgccjit_so = output_dir.join(libgccjit_so_name); if !libgccjit_so.is_file() { // Download time! let tempfile_name = "libgccjit.so.download"; @@ -279,6 +282,16 @@ impl ConfigInfo { })?; println!("Downloaded libgccjit.so version {} successfully!", commit); + create_symlink( + &libgccjit_so.canonicalize().map_err(|err| { + format!( + "Failed to get absolute path of `{}`: {:?}", + libgccjit_so.display(), + err, + ) + })?, + output_dir.join(&format!("{}.0", libgccjit_so_name)), + )?; } self.gcc_path = output_dir diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 046008ae1a247..33dcd9ef7005f 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -374,6 +374,22 @@ pub fn remove_file + ?Sized>(file_path: &P) -> Result<(), String> }) } +pub fn create_symlink, Q: AsRef>(original: P, link: Q) -> Result<(), String> { + #[cfg(windows)] + let symlink = std::os::windows::fs::symlink_file; + #[cfg(not(windows))] + let symlink = std::os::unix::fs::symlink; + + symlink(&original, &link).map_err(|err| { + format!( + "failed to create a symlink `{}` to `{}`: {:?}", + original.as_ref().display(), + link.as_ref().display(), + err, + ) + }) +} + #[cfg(test)] mod tests { use super::*; From 5c6cdf5ab6399604695c94031e32087cfe3367ae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Feb 2024 20:55:14 +0100 Subject: [PATCH 128/613] Add `info` command to help get some information --- build_system/src/config.rs | 35 +++++++++++++++-------------------- build_system/src/info.rs | 19 +++++++++++++++++++ build_system/src/main.rs | 5 +++++ 3 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 build_system/src/info.rs diff --git a/build_system/src/config.rs b/build_system/src/config.rs index a206bab14a9a8..48be515a1f0f8 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -121,6 +121,9 @@ pub struct ConfigInfo { pub gcc_path: String, config_file: Option, cg_gcc_path: Option, + // Needed for the `info` command which doesn't want to actually download the lib if needed, + // just to set the `gcc_path` field to display it. + pub no_download: bool, } impl ConfigInfo { @@ -204,7 +207,7 @@ impl ConfigInfo { return Err(format!( "{}: invalid commit hash `{}`", commit_hash_file.display(), - commit + commit, )); } let output_dir = output_dir.join(commit); @@ -217,9 +220,17 @@ impl ConfigInfo { ) })?; } + let output_dir = output_dir.canonicalize().map_err(|err| { + format!( + "Failed to get absolute path of `{}`: {:?}", + output_dir.display(), + err + ) + })?; + let libgccjit_so_name = "libgccjit.so"; let libgccjit_so = output_dir.join(libgccjit_so_name); - if !libgccjit_so.is_file() { + if !libgccjit_so.is_file() && !self.no_download { // Download time! let tempfile_name = "libgccjit.so.download"; let tempfile = output_dir.join(tempfile_name); @@ -283,28 +294,12 @@ impl ConfigInfo { println!("Downloaded libgccjit.so version {} successfully!", commit); create_symlink( - &libgccjit_so.canonicalize().map_err(|err| { - format!( - "Failed to get absolute path of `{}`: {:?}", - libgccjit_so.display(), - err, - ) - })?, + &libgccjit_so, output_dir.join(&format!("{}.0", libgccjit_so_name)), )?; } - self.gcc_path = output_dir - .canonicalize() - .map_err(|err| { - format!( - "Failed to get absolute path of `{}`: {:?}", - output_dir.display(), - err - ) - })? - .display() - .to_string(); + self.gcc_path = output_dir.display().to_string(); println!("Using `{}` as path for libgccjit", self.gcc_path); Ok(()) } diff --git a/build_system/src/info.rs b/build_system/src/info.rs new file mode 100644 index 0000000000000..ea38791d38c9a --- /dev/null +++ b/build_system/src/info.rs @@ -0,0 +1,19 @@ +use crate::config::ConfigInfo; + +pub fn run() -> Result<(), String> { + let mut config = ConfigInfo::default(); + + // We skip binary name and the `info` command. + let mut args = std::env::args().skip(2); + while let Some(arg) = args.next() { + if arg == "--help" { + println!("Display the path where the libgccjit will be located"); + return Ok(()); + } + config.parse_argument(&arg, &mut args)?; + } + config.no_download = true; + config.setup_gcc_path()?; + println!("{}", config.gcc_path); + Ok(()) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 102c5486a75e4..c6958f0c5124e 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -5,6 +5,7 @@ mod build; mod cargo; mod clean; mod config; +mod info; mod prepare; mod rustc_info; mod test; @@ -29,6 +30,7 @@ Available commands for build_system: prepare : Run prepare command build : Run build command test : Run test command + info: : Run info command --help : Show this message" ); } @@ -39,6 +41,7 @@ pub enum Command { Prepare, Build, Test, + Info, } fn main() { @@ -52,6 +55,7 @@ fn main() { Some("prepare") => Command::Prepare, Some("build") => Command::Build, Some("test") => Command::Test, + Some("info") => Command::Info, Some("--help") => { usage(); process::exit(0); @@ -70,6 +74,7 @@ fn main() { Command::Prepare => prepare::run(), Command::Build => build::run(), Command::Test => test::run(), + Command::Info => info::run(), } { eprintln!("Command failed to run: {e}"); process::exit(1); From 65f4b6354d8899e9292f8666d2804a0306b0770e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Feb 2024 18:11:37 +0100 Subject: [PATCH 129/613] Add CI for download config --- .github/workflows/download.yml | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .github/workflows/download.yml diff --git a/.github/workflows/download.yml b/.github/workflows/download.yml new file mode 100644 index 0000000000000..86a8459a33c91 --- /dev/null +++ b/.github/workflows/download.yml @@ -0,0 +1,97 @@ +name: Check download command + +on: + - push + - pull_request + +permissions: + contents: read + +env: + # Enable backtraces for easier debugging + RUST_BACKTRACE: 1 + +jobs: + build: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + commands: [ + "--mini-tests", + "--std-tests", + # FIXME: re-enable asm tests when GCC can emit in the right syntax. + # "--asm-tests", + "--test-libcore", + "--extended-rand-tests", + "--extended-regex-example-tests", + "--extended-regex-tests", + "--test-successful-rustc --nb-parts 2 --current-part 0", + "--test-successful-rustc --nb-parts 2 --current-part 1", + "--projects", + ] + + steps: + - uses: actions/checkout@v3 + + # `rustup show` installs from rust-toolchain.toml + - name: Setup rust toolchain + run: rustup show + + - name: Setup rust cache + uses: Swatinem/rust-cache@v2 + + - name: Install packages + # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. + run: sudo apt-get install ninja-build ripgrep llvm-14-tools + + - name: Setup path to libgccjit + run: | + echo 'download-gccjit = true' > config.toml + + - name: Set env + run: | + echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV + + #- name: Cache rust repository + ## We only clone the rust repository for rustc tests + #if: ${{ contains(matrix.commands, 'rustc') }} + #uses: actions/cache@v3 + #id: cache-rust-repository + #with: + #path: rust + #key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }} + + - name: Build + run: | + ./y.sh prepare --only-libcore + # TODO: remove --features master when it is back to the default. + ./y.sh build --features master + # TODO: remove --features master when it is back to the default. + + - name: Set env (part 2) + run: | + # Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables... + echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV + echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV + + - name: Build (part 2) + run: | + echo "LIBRARY_PATH=" $LIBRARY_PATH + cargo test --features master + ./y.sh clean all + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + ./y.sh prepare + + - name: Add more failing tests because the sysroot is not compiled with LTO + run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt + + - name: Run tests + run: | + # TODO: remove --features master when it is back to the default. + ./y.sh test --features master --release --clean --build-sysroot ${{ matrix.commands }} From d04ffb0ffc10bbf2623f32fc6840ed3a7614ff33 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Feb 2024 22:52:57 +0100 Subject: [PATCH 130/613] Update lang_tests_common.rs test --- tests/lang_tests_common.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/lang_tests_common.rs b/tests/lang_tests_common.rs index 029a3b98ff23a..33dc6ef62ae52 100644 --- a/tests/lang_tests_common.rs +++ b/tests/lang_tests_common.rs @@ -21,11 +21,16 @@ pub fn main_inner(profile: Profile) { let tempdir = TempDir::new().expect("temp dir"); let current_dir = current_dir().expect("current dir"); let current_dir = current_dir.to_str().expect("current dir").to_string(); - let gcc_path = Toml::parse(include_str!("../config.toml")) - .expect("Failed to parse `config.toml`") - .get_string("gcc-path") - .expect("Missing `gcc-path` key in `config.toml`") - .to_string(); + let toml = Toml::parse(include_str!("../config.toml")) + .expect("Failed to parse `config.toml`"); + let gcc_path = if let Ok(gcc_path) = toml.get_string("gcc-path") { + PathBuf::from(gcc_path.to_string()) + } else { + // then we try to retrieve it from the `target` folder. + let commit = include_str!("../libgccjit.version").trim(); + Path::new("target/libgccjit").join(commit) + }; + let gcc_path = Path::new(&gcc_path) .canonicalize() .expect("failed to get absolute path of `gcc-path`") From 59546ea2d53c9f3c9f0e87bb2852d6b972ec8f8b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 14:20:39 +0100 Subject: [PATCH 131/613] Merge `download.yml` into `ci.yml` --- .github/workflows/ci.yml | 20 +++---- .github/workflows/download.yml | 97 ---------------------------------- 2 files changed, 10 insertions(+), 107 deletions(-) delete mode 100644 .github/workflows/download.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba64f40acc4ba..e4678c4e2af4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,19 +49,10 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools - - name: Download artifact - run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb - - - name: Setup path to libgccjit - run: | - sudo dpkg --force-overwrite -i gcc-13.deb - echo 'gcc-path = "/usr/lib/"' > config.toml - - name: Set env run: | echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo 'download-gccjit = true' > config.toml #- name: Cache rust repository ## We only clone the rust repository for rustc tests @@ -78,6 +69,15 @@ jobs: # TODO: remove --features master when it is back to the default. ./y.sh build --features master # TODO: remove --features master when it is back to the default. + + - name: Set env (part 2) + run: | + # Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables... + echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV + echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV + + - name: Build (part 2) + run: | cargo test --features master ./y.sh clean all diff --git a/.github/workflows/download.yml b/.github/workflows/download.yml deleted file mode 100644 index 86a8459a33c91..0000000000000 --- a/.github/workflows/download.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: Check download command - -on: - - push - - pull_request - -permissions: - contents: read - -env: - # Enable backtraces for easier debugging - RUST_BACKTRACE: 1 - -jobs: - build: - runs-on: ubuntu-22.04 - - strategy: - fail-fast: false - matrix: - commands: [ - "--mini-tests", - "--std-tests", - # FIXME: re-enable asm tests when GCC can emit in the right syntax. - # "--asm-tests", - "--test-libcore", - "--extended-rand-tests", - "--extended-regex-example-tests", - "--extended-regex-tests", - "--test-successful-rustc --nb-parts 2 --current-part 0", - "--test-successful-rustc --nb-parts 2 --current-part 1", - "--projects", - ] - - steps: - - uses: actions/checkout@v3 - - # `rustup show` installs from rust-toolchain.toml - - name: Setup rust toolchain - run: rustup show - - - name: Setup rust cache - uses: Swatinem/rust-cache@v2 - - - name: Install packages - # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. - run: sudo apt-get install ninja-build ripgrep llvm-14-tools - - - name: Setup path to libgccjit - run: | - echo 'download-gccjit = true' > config.toml - - - name: Set env - run: | - echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - - #- name: Cache rust repository - ## We only clone the rust repository for rustc tests - #if: ${{ contains(matrix.commands, 'rustc') }} - #uses: actions/cache@v3 - #id: cache-rust-repository - #with: - #path: rust - #key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }} - - - name: Build - run: | - ./y.sh prepare --only-libcore - # TODO: remove --features master when it is back to the default. - ./y.sh build --features master - # TODO: remove --features master when it is back to the default. - - - name: Set env (part 2) - run: | - # Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables... - echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV - echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV - - - name: Build (part 2) - run: | - echo "LIBRARY_PATH=" $LIBRARY_PATH - cargo test --features master - ./y.sh clean all - - - name: Prepare dependencies - run: | - git config --global user.email "user@example.com" - git config --global user.name "User" - ./y.sh prepare - - - name: Add more failing tests because the sysroot is not compiled with LTO - run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt - - - name: Run tests - run: | - # TODO: remove --features master when it is back to the default. - ./y.sh test --features master --release --clean --build-sysroot ${{ matrix.commands }} From 2bcc73540cbadaae43b539567252f79dffd43f5a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 14:44:19 +0100 Subject: [PATCH 132/613] Don't join config file path if provided through `--config-file` option --- build_system/src/config.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 48be515a1f0f8..b48e132ebd2aa 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -312,7 +312,10 @@ impl ConfigInfo { } pub fn setup_gcc_path(&mut self) -> Result<(), String> { - let config_file = self.compute_path(self.config_file.as_deref().unwrap_or("config.toml")); + let config_file = match self.config_file.as_deref() { + Some(config_file) => config_file.into(), + None => self.compute_path("config.toml"), + }; let ConfigFile { gcc_path, download_gccjit, From 1096b1b8db1ac3bdb13f77e3726a00d9516af5a0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 15:01:13 +0100 Subject: [PATCH 133/613] Add more explanation on what `cg_gcc_path` is used for and improve help message for `--cg_gcc-path` --- build_system/src/config.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index b48e132ebd2aa..fc2ef7b797d56 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -120,6 +120,9 @@ pub struct ConfigInfo { pub sysroot_path: String, pub gcc_path: String, config_file: Option, + // This is used in particular in rust compiler bootstrap because it doesn't run at the root + // of the `cg_gcc` folder, making it complicated for us to get access to local files we need + // like `libgccjit.version` or `config.toml`. cg_gcc_path: Option, // Needed for the `info` command which doesn't want to actually download the lib if needed, // just to set the `gcc_path` field to display it. @@ -526,7 +529,7 @@ impl ConfigInfo { --sysroot-panic-abort : Build the sysroot without unwinding support --config-file : Location of the config file to be used --cg_gcc-path : Location of the rustc_codegen_gcc root folder (used - for accessing any file from the project)" + when ran from another directory)" ); } } From b80a99922be9866d4117931e50127f36010a8dc9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 15:43:07 +0100 Subject: [PATCH 134/613] Improve code readability and add more code comments --- build_system/src/config.rs | 146 ++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 66 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index fc2ef7b797d56..475f9b300f74c 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -190,6 +190,83 @@ impl ConfigInfo { command } + fn download_gccjit( + &self, + output_dir: &Path, + libgccjit_so_name: &str, + commit: &str, + ) -> Result<(), String> { + // Download time! + let tempfile_name = format!("{}.download", libgccjit_so_name); + let tempfile = output_dir.join(&tempfile_name); + let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok(); + + let url = format!( + "https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so", + commit, + ); + + println!("Downloading `{}`...", url); + // Try curl. If that fails and we are on windows, fallback to PowerShell. + let mut ret = run_command_with_output( + &[ + &"curl", + &"--speed-time", + &"30", + &"--speed-limit", + &"10", // timeout if speed is < 10 bytes/sec for > 30 seconds + &"--connect-timeout", + &"30", // timeout if cannot connect within 30 seconds + &"-o", + &tempfile_name, + &"--retry", + &"3", + &"-SRfL", + if is_in_ci { &"-s" } else { &"--progress-bar" }, + &url.as_str(), + ], + Some(&output_dir), + ); + if ret.is_err() && cfg!(windows) { + eprintln!("Fallback to PowerShell"); + ret = run_command_with_output( + &[ + &"PowerShell.exe", + &"/nologo", + &"-Command", + &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", + &format!( + "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", + url, + tempfile_name, + ).as_str(), + ], + Some(&output_dir), + ); + } + ret?; + + let libgccjit_so = output_dir.join(libgccjit_so_name); + // If we reach this point, it means the file was correctly downloaded, so let's + // rename it! + std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| { + format!( + "Failed to rename `{}` into `{}`: {:?}", + tempfile.display(), + libgccjit_so.display(), + err, + ) + })?; + + println!("Downloaded libgccjit.so version {} successfully!", commit); + // We need to create a link named `libgccjit.so.0` because that's what the linker is + // looking for. + create_symlink( + &libgccjit_so, + output_dir.join(&format!("{}.0", libgccjit_so_name)), + ) + } + fn download_gccjit_if_needed(&mut self) -> Result<(), String> { let output_dir = Path::new( std::env::var("CARGO_TARGET_DIR") @@ -206,6 +283,8 @@ impl ConfigInfo { ) })?; let commit = content.trim(); + // This is a very simple check to ensure this is not a path. For the rest, it'll just fail + // when trying to download the file so we should be fine. if commit.contains('/') || commit.contains('\\') { return Err(format!( "{}: invalid commit hash `{}`", @@ -234,72 +313,7 @@ impl ConfigInfo { let libgccjit_so_name = "libgccjit.so"; let libgccjit_so = output_dir.join(libgccjit_so_name); if !libgccjit_so.is_file() && !self.no_download { - // Download time! - let tempfile_name = "libgccjit.so.download"; - let tempfile = output_dir.join(tempfile_name); - let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok(); - - let url = format!( - "https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so", - commit, - ); - - println!("Downloading `{}`...", url); - // Try curl. If that fails and we are on windows, fallback to PowerShell. - let mut ret = run_command_with_output( - &[ - &"curl", - &"--speed-time", - &"30", - &"--speed-limit", - &"10", // timeout if speed is < 10 bytes/sec for > 30 seconds - &"--connect-timeout", - &"30", // timeout if cannot connect within 30 seconds - &"-o", - &tempfile_name, - &"--retry", - &"3", - &"-SRfL", - if is_in_ci { &"-s" } else { &"--progress-bar" }, - &url.as_str(), - ], - Some(&output_dir), - ); - if ret.is_err() && cfg!(windows) { - eprintln!("Fallback to PowerShell"); - ret = run_command_with_output( - &[ - &"PowerShell.exe", - &"/nologo", - &"-Command", - &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", - &format!( - "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", - url, - tempfile_name, - ).as_str(), - ], - Some(&output_dir), - ); - } - ret?; - - // If we reach this point, it means the file was correctly downloaded, so let's - // rename it! - std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| { - format!( - "Failed to rename `{}` into `{}`: {:?}", - tempfile.display(), - libgccjit_so.display(), - err, - ) - })?; - - println!("Downloaded libgccjit.so version {} successfully!", commit); - create_symlink( - &libgccjit_so, - output_dir.join(&format!("{}.0", libgccjit_so_name)), - )?; + self.download_gccjit(&output_dir, libgccjit_so_name, commit)?; } self.gcc_path = output_dir.display().to_string(); From 267aaef81dade6f1c1ae09fe820a31ff6de95e38 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 21:26:14 +0100 Subject: [PATCH 135/613] Move some top-level folders into `build` --- build_system/src/clean.rs | 19 ++++------ build_system/src/config.rs | 12 ++++-- build_system/src/main.rs | 2 + build_system/src/prepare.rs | 7 ++-- build_system/src/test.rs | 75 +++++++++++++++++++++---------------- 5 files changed, 62 insertions(+), 53 deletions(-) diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs index 929a878113d69..cd8e691a0ed9f 100644 --- a/build_system/src/clean.rs +++ b/build_system/src/clean.rs @@ -1,6 +1,7 @@ use crate::utils::{remove_file, run_command}; use std::fs::remove_dir_all; +use std::path::Path; #[derive(Default)] enum CleanArg { @@ -46,12 +47,14 @@ fn clean_all() -> Result<(), String> { "build_sysroot/sysroot", "build_sysroot/sysroot_src", "build_sysroot/target", - "regex", - "simple-raytracer", ]; for dir in dirs_to_remove { let _ = remove_dir_all(dir); } + let dirs_to_remove = ["regex", "rand", "simple-raytracer"]; + for dir in dirs_to_remove { + let _ = remove_dir_all(Path::new(crate::BUILD_DIR).join(dir)); + } let files_to_remove = ["build_sysroot/Cargo.lock", "perf.data", "perf.data.old"]; @@ -64,16 +67,8 @@ fn clean_all() -> Result<(), String> { } fn clean_ui_tests() -> Result<(), String> { - run_command( - &[ - &"find", - &"rust/build/x86_64-unknown-linux-gnu/test/ui/", - &"-name", - &"stamp", - &"-delete", - ], - None, - )?; + let path = Path::new(crate::BUILD_DIR).join("rust/build/x86_64-unknown-linux-gnu/test/ui/"); + run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?; Ok(()) } diff --git a/build_system/src/config.rs b/build_system/src/config.rs index c9bfcb9e6ba47..d1047436cebdb 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -523,7 +523,11 @@ fn download_gccjit( &"--retry", &"3", &"-SRfL", - if with_progress_bar { &"--progress-bar" } else { &"-s" }, + if with_progress_bar { + &"--progress-bar" + } else { + &"-s" + }, &url.as_str(), ], Some(&output_dir), @@ -538,9 +542,9 @@ fn download_gccjit( &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", &format!( "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')", - url, - tempfile_name, - ).as_str(), + url, tempfile_name, + ) + .as_str(), ], Some(&output_dir), ); diff --git a/build_system/src/main.rs b/build_system/src/main.rs index c6958f0c5124e..18dc4b21a9623 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -11,6 +11,8 @@ mod rustc_info; mod test; mod utils; +const BUILD_DIR: &str = "build"; + macro_rules! arg_error { ($($err:tt)*) => {{ eprintln!($($err)*); diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 7f1401e594c4c..979438d041516 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -152,11 +152,11 @@ fn clone_and_setup(repo_url: &str, checkout_commit: &str, extra: Option) - where F: Fn(&Path) -> Result<(), String>, { - let clone_result = git_clone(repo_url, None, false)?; + let clone_result = git_clone(repo_url, Some(&Path::new(crate::BUILD_DIR)), false)?; if !clone_result.ran_clone { println!("`{}` has already been cloned", clone_result.repo_name); } - let repo_path = Path::new(&clone_result.repo_name); + let repo_path = Path::new(crate::BUILD_DIR).join(&clone_result.repo_name); run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?; run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?; let filter = format!("-{}-", clone_result.repo_name); @@ -219,8 +219,7 @@ impl PrepareArg { --only-libcore : Only setup libcore and don't clone other repositories --cross : Apply the patches needed to do cross-compilation --libgccjit12-patches : Apply patches needed for libgccjit12 - --help : Show this help -"# + --help : Show this help"# ) } } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 806e18431c46d..d7f7a0eb47ef1 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -485,19 +485,25 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { +fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let toolchain = format!( "+{channel}-{host}", channel = get_toolchain()?, // May also include date host = args.config_info.host_triple ); - let rust_dir = Some(Path::new("rust")); + let rust_dir_path = Path::new(crate::BUILD_DIR).join("rust"); // If the repository was already cloned, command will fail, so doesn't matter. let _ = run_command_with_output_and_env( - &[&"git", &"clone", &"https://github.com/rust-lang/rust.git"], + &[ + &"git", + &"clone", + &"https://github.com/rust-lang/rust.git", + &rust_dir_path, + ], None, Some(env), ); + let rust_dir: Option<&Path> = Some(&rust_dir_path); run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?; run_command_with_output_and_env(&[&"git", &"fetch"], rust_dir, Some(env))?; let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { @@ -561,8 +567,9 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> { String::new() } }; + let file_path = rust_dir_path.join("config.toml"); std::fs::write( - "rust/config.toml", + &file_path, &format!( r#"change-id = 115898 @@ -587,13 +594,19 @@ download-ci-llvm = false llvm_filecheck = llvm_filecheck.trim(), ), ) - .map_err(|error| format!("Failed to write into `rust/config.toml`: {:?}", error))?; - Ok(()) + .map_err(|error| { + format!( + "Failed to write into `{}`: {:?}", + file_path.display(), + error + ) + })?; + Ok(rust_dir_path) } fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { let mut env = env.clone(); - setup_rustc(&mut env, args)?; + let rust_dir = setup_rustc(&mut env, args)?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rustc asm test suite"); @@ -621,7 +634,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { ) .as_str(), ], - Some(Path::new("rust")), + Some(&rust_dir), Some(&env), )?; Ok(()) @@ -761,11 +774,11 @@ fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); return Ok(()); } - let path = Path::new("rand"); - run_cargo_command(&[&"clean"], Some(path), env, args)?; + let path = Path::new(crate::BUILD_DIR).join("rand"); + run_cargo_command(&[&"clean"], Some(&path), env, args)?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rust-random/rand"); - run_cargo_command(&[&"test", &"--workspace"], Some(path), env, args)?; + run_cargo_command(&[&"test", &"--workspace"], Some(&path), env, args)?; Ok(()) } @@ -774,8 +787,8 @@ fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> println!("Not using GCC master branch. Skipping `extended_regex_example_tests`."); return Ok(()); } - let path = Path::new("regex"); - run_cargo_command(&[&"clean"], Some(path), env, args)?; + let path = Path::new(crate::BUILD_DIR).join("regex"); + run_cargo_command(&[&"clean"], Some(&path), env, args)?; // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rust-lang/regex example shootout-regex-dna"); let mut env = env.clone(); @@ -788,14 +801,14 @@ fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> // Make sure `[codegen mono items] start` doesn't poison the diff run_cargo_command( &[&"build", &"--example", &"shootout-regex-dna"], - Some(path), + Some(&path), &env, args, )?; run_cargo_command_with_callback( &[&"run", &"--example", &"shootout-regex-dna"], - Some(path), + Some(&path), &env, args, |cargo_command, cwd, env| { @@ -838,6 +851,7 @@ fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { env.get("RUSTFLAGS").cloned().unwrap_or_default() ); env.insert("RUSTFLAGS".to_string(), rustflags); + let path = Path::new(crate::BUILD_DIR).join("regex"); run_cargo_command( &[ &"test", @@ -850,7 +864,7 @@ fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"-Zunstable-options", &"-q", ], - Some(Path::new("regex")), + Some(&path), &env, args, )?; @@ -928,17 +942,15 @@ fn should_remove_test(file_path: &Path) -> Result { fn test_rustc_inner(env: &Env, args: &TestArg, prepare_files_callback: F) -> Result<(), String> where - F: Fn() -> Result, + F: Fn(&Path) -> Result, { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rust-lang/rust"); let mut env = env.clone(); - setup_rustc(&mut env, args)?; - - let rust_path = Path::new("rust"); + let rust_path = setup_rustc(&mut env, args)?; walk_dir( - "rust/tests/ui", + rust_path.join("tests/ui"), |dir| { let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or(""); if [ @@ -1001,7 +1013,7 @@ where walk_dir(rust_path.join("tests/ui"), dir_handling, file_handling)?; - if !prepare_files_callback()? { + if !prepare_files_callback(&rust_path)? { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("Keeping all UI tests"); } @@ -1027,7 +1039,7 @@ where &"-path", &"*/auxiliary/*", ], - Some(rust_path), + Some(&rust_path), )? .stdout, ) @@ -1072,18 +1084,18 @@ where &"--rustc-args", &rustc_args, ], - Some(rust_path), + Some(&rust_path), Some(&env), )?; Ok(()) } fn test_rustc(env: &Env, args: &TestArg) -> Result<(), String> { - test_rustc_inner(env, args, || Ok(false)) + test_rustc_inner(env, args, |_| Ok(false)) } fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { - test_rustc_inner(env, args, || { + test_rustc_inner(env, args, |rust_path| { // Removing all tests. run_command( &[ @@ -1098,7 +1110,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { &"*/auxiliary/*", &"-delete", ], - Some(Path::new("rust")), + Some(rust_path), )?; // Putting back only the failing ones. let path = "tests/failing-ui-tests.txt"; @@ -1108,10 +1120,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { .map(|line| line.trim()) .filter(|line| !line.is_empty()) { - run_command( - &[&"git", &"checkout", &"--", &file], - Some(Path::new("rust")), - )?; + run_command(&[&"git", &"checkout", &"--", &file], Some(&rust_path))?; } } else { println!( @@ -1124,7 +1133,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { } fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { - test_rustc_inner(env, args, || { + test_rustc_inner(env, args, |rust_path| { // Removing the failing tests. let path = "tests/failing-ui-tests.txt"; if let Ok(files) = std::fs::read_to_string(path) { @@ -1133,7 +1142,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { .map(|line| line.trim()) .filter(|line| !line.is_empty()) { - let path = Path::new("rust").join(file); + let path = rust_path.join(file); remove_file(&path)?; } } else { From 896b1a9049631477e2549144a2a3a773c470213e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 21:50:00 +0100 Subject: [PATCH 136/613] Generate libgccjit.so into the `build` folder --- build_system/src/config.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/build_system/src/config.rs b/build_system/src/config.rs index d1047436cebdb..c89a6d5eb9b20 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -191,12 +191,7 @@ impl ConfigInfo { } fn download_gccjit_if_needed(&mut self) -> Result<(), String> { - let output_dir = Path::new( - std::env::var("CARGO_TARGET_DIR") - .as_deref() - .unwrap_or("target"), - ) - .join("libgccjit"); + let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit"); let commit_hash_file = self.compute_path("libgccjit.version"); let content = fs::read_to_string(&commit_hash_file).map_err(|_| { From 436fea8efbb332362a9c3b7f6854fea6bd35cd11 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 21:50:34 +0100 Subject: [PATCH 137/613] Add `build` folder into the ignored git entries --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 687c3a6797af1..ac695da16f864 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ tools/llvmint-2 llvm build_system/target config.toml +build \ No newline at end of file From 46d6e772c087c3bffb3228f36530010f16a57431 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Feb 2024 21:56:17 +0100 Subject: [PATCH 138/613] Update `tests/lang_tests_common.rs` test --- tests/lang_tests_common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lang_tests_common.rs b/tests/lang_tests_common.rs index 33dc6ef62ae52..4cc429cfa456f 100644 --- a/tests/lang_tests_common.rs +++ b/tests/lang_tests_common.rs @@ -28,7 +28,7 @@ pub fn main_inner(profile: Profile) { } else { // then we try to retrieve it from the `target` folder. let commit = include_str!("../libgccjit.version").trim(); - Path::new("target/libgccjit").join(commit) + Path::new("build/libgccjit").join(commit) }; let gcc_path = Path::new(&gcc_path) From 452ebf5f376971bec12364f56a7bb71125edf1fc Mon Sep 17 00:00:00 2001 From: tempdragon <645703113@qq.com> Date: Wed, 14 Feb 2024 08:12:10 +0800 Subject: [PATCH 139/613] feat(test.rs): Clone only 1 layer in build_system --- build_system/src/test.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index d7f7a0eb47ef1..f4e68ae710c8e 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -499,17 +499,29 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { &"clone", &"https://github.com/rust-lang/rust.git", &rust_dir_path, + &"--depth", + &"1", ], None, Some(env), ); let rust_dir: Option<&Path> = Some(&rust_dir_path); run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?; - run_command_with_output_and_env(&[&"git", &"fetch"], rust_dir, Some(env))?; let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { Some(commit_hash) => commit_hash, None => return Err("Couldn't retrieve rustc commit hash".to_string()), }; + run_command_with_output_and_env( + &[ + &"git", + &"fetch", + &"https://github.com/rust-lang/rust.git", + &rustc_commit.as_str(), + &"--depth=1", + ], + rust_dir, + Some(env), + )?; if rustc_commit != "unknown" { run_command_with_output_and_env( &[&"git", &"checkout", &rustc_commit], From 17e329777fedae708cbc5170787bd8481989e7fd Mon Sep 17 00:00:00 2001 From: tempdragon <645703113@qq.com> Date: Wed, 14 Feb 2024 17:59:16 +0800 Subject: [PATCH 140/613] feat(test.rs): Lookup the commit with cat-file to avoid re-fetches --- build_system/src/test.rs | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index f4e68ae710c8e..9fe9708c2917b 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -511,17 +511,30 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { Some(commit_hash) => commit_hash, None => return Err("Couldn't retrieve rustc commit hash".to_string()), }; - run_command_with_output_and_env( - &[ - &"git", - &"fetch", - &"https://github.com/rust-lang/rust.git", - &rustc_commit.as_str(), - &"--depth=1", - ], - rust_dir, - Some(env), - )?; + let has_commit = { + if let Ok(ty) = run_command_with_env( + &[&"git", &"cat-file", &"-t", &rustc_commit.as_str()], + rust_dir, + Some(env), + ) { + String::from_utf8_lossy(&ty.stdout).to_string() == "commit" + } else { + false + } + }; + if !has_commit { + run_command_with_output_and_env( + &[ + &"git", + &"fetch", + &"https://github.com/rust-lang/rust.git", + &rustc_commit.as_str(), + &"--depth=1", + ], + rust_dir, + Some(env), + )? + }; if rustc_commit != "unknown" { run_command_with_output_and_env( &[&"git", &"checkout", &rustc_commit], From a883c6da2055aeb2892781c6f1abe38df6c0ef88 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Feb 2024 13:35:20 +0100 Subject: [PATCH 141/613] Move `crates_patches` and `cross_patches` into the `patches` folder --- build_system/src/prepare.rs | 4 ++-- .../crate_patches}/0002-rand-Disable-failing-test.patch | 0 .../0001-Disable-libstd-and-libtest-dylib.patch | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {crate_patches => patches/crate_patches}/0002-rand-Disable-failing-test.patch (100%) rename {cross_patches => patches/cross_patches}/0001-Disable-libstd-and-libtest-dylib.patch (100%) diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 979438d041516..1a3eb7d2e57b4 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -95,7 +95,7 @@ fn prepare_libcore( )?; if cross_compile { walk_dir( - "cross_patches", + "patches/cross_patches", |_| Ok(()), |file_path: &Path| { patches.push(file_path.to_path_buf()); @@ -161,7 +161,7 @@ where run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?; let filter = format!("-{}-", clone_result.repo_name); walk_dir( - "crate_patches", + "patches/crate_patches", |_| Ok(()), |file_path| { let patch = file_path.as_os_str().to_str().unwrap(); diff --git a/crate_patches/0002-rand-Disable-failing-test.patch b/patches/crate_patches/0002-rand-Disable-failing-test.patch similarity index 100% rename from crate_patches/0002-rand-Disable-failing-test.patch rename to patches/crate_patches/0002-rand-Disable-failing-test.patch diff --git a/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch b/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch similarity index 100% rename from cross_patches/0001-Disable-libstd-and-libtest-dylib.patch rename to patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch From ebac107a554bfdefc1c3932616795e07ff44eea6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Feb 2024 14:18:17 +0100 Subject: [PATCH 142/613] Remove paths that don't exist anymore from file --- .gitignore | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitignore b/.gitignore index ac695da16f864..bf975f92014da 100644 --- a/.gitignore +++ b/.gitignore @@ -10,16 +10,10 @@ perf.data.old /build_sysroot/sysroot_src /build_sysroot/Cargo.lock /build_sysroot/test_target/Cargo.lock -/rust -/simple-raytracer -/regex -/rand gimple* *asm res test-backend -gcc_path -cross_gcc_path projects benchmarks tools/llvm-project From de57533e5644335eccd8c1430b4c60295a0b922c Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 12 Feb 2024 20:15:12 -0400 Subject: [PATCH 143/613] Implement dummy emit=llvm-ir --- .ignore | 1 + src/back/write.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.ignore b/.ignore index d8d189e5c7c64..702dd9e2a23f3 100644 --- a/.ignore +++ b/.ignore @@ -8,3 +8,4 @@ !*gimple* !*asm* !.github +!config.toml diff --git a/src/back/write.rs b/src/back/write.rs index 04772d7707abd..792fd47001d57 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -70,7 +70,8 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, diag_hand } if config.emit_ir { - unimplemented!(); + let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + std::fs::write(out, "").expect("write file"); } if config.emit_asm { From 35b431884f3ef4d77c9e9ee1ff8a8e2cf36a67c1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 15 Feb 2024 10:21:06 +0000 Subject: [PATCH 144/613] Disable test broken due to upstream bug --- scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 636f2875a6873..3c9df40737ac3 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -145,6 +145,7 @@ rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug # ====================== rm tests/ui/backtrace.rs # TODO warning rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue +rm tests/ui/async-await/async-closures/once.rs # FIXME bug in the rustc FnAbi calculation code rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd From 3918b4783d4290b5d64e5c69c30ebaee87f2b125 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 15 Feb 2024 10:23:58 +0000 Subject: [PATCH 145/613] Workaround UB in cranelift-jit --- src/constant.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/constant.rs b/src/constant.rs index b6de688130c79..18c5960ffc68a 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -372,7 +372,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant } let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec(); - data.define(bytes.into_boxed_slice()); + if bytes.is_empty() { + // FIXME(bytecodealliance/wasmtime#7918) cranelift-jit has a bug where it causes UB on + // empty data objects + data.define(Box::new([0])); + } else { + data.define(bytes.into_boxed_slice()); + } for &(offset, prov) in alloc.provenance().ptrs().iter() { let alloc_id = prov.alloc_id(); From ec5328b3d9aa08986abd3237b40c0bf74b08bc2b Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 14 Feb 2024 14:17:27 +0000 Subject: [PATCH 146/613] errors: only eagerly translate subdiagnostics Subdiagnostics don't need to be lazily translated, they can always be eagerly translated. Eager translation is slightly more complex as we need to have a `DiagCtxt` available to perform the translation, which involves slightly more threading of that context. This slight increase in complexity should enable later simplifications - like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages into the diagnostic structs rather than having them in separate files (working on that was what led to this change). Signed-off-by: David Wood --- src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/errors.rs b/src/errors.rs index cc0fbe46dcc11..79eb4406b8a33 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -122,7 +122,7 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl diag.span(span); }; if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); + diag.subdiagnostic(dcx, missing_features); } diag.arg("features", self.features.join(", ")); diag From 98c1efd5b69b64cabab6762d75687fc937d79599 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 15 Feb 2024 12:30:43 +0100 Subject: [PATCH 147/613] Put back `master` feature as default --- .github/workflows/ci.yml | 9 +++------ .github/workflows/failures.yml | 5 +---- .github/workflows/m68k.yml | 9 +++------ .github/workflows/release.yml | 9 +++------ .github/workflows/stdarch.yml | 9 +++------ Cargo.toml | 1 + Readme.md | 4 ++-- 7 files changed, 16 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4678c4e2af4f..37d2bc1c201af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,9 +66,7 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - # TODO: remove --features master when it is back to the default. - ./y.sh build --features master - # TODO: remove --features master when it is back to the default. + ./y.sh build - name: Set env (part 2) run: | @@ -78,7 +76,7 @@ jobs: - name: Build (part 2) run: | - cargo test --features master + cargo test ./y.sh clean all - name: Prepare dependencies @@ -92,8 +90,7 @@ jobs: - name: Run tests run: | - # TODO: remove --features master when it is back to the default. - ./y.sh test --features master --release --clean --build-sysroot ${{ matrix.commands }} + ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} duplicates: runs-on: ubuntu-latest diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index ae00a257e2486..2bca694e83284 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -21,14 +21,11 @@ jobs: libgccjit_version: - gcc: "libgccjit.so" artifacts_branch: "master" - # TODO: switch back to --no-default-features in the case of libgccjit 12 when the default is to enable - # master again. - extra: "--features master" - gcc: "libgccjit_without_int128.so" artifacts_branch: "master-without-128bit-integers" - extra: "--features master" - gcc: "libgccjit12.so" artifacts_branch: "gcc12" + extra: "--no-default-features" # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin. # Not sure why it's not found otherwise. env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/" diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 2428125483bdd..a8c6b614ce815 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -91,10 +91,8 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore --cross - # TODO: remove --features master when it is back to the default. - ./y.sh build --target-triple m68k-unknown-linux-gnu --features master - # TODO: remove --features master when it is back to the default. - CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test --features master + ./y.sh build --target-triple m68k-unknown-linux-gnu + CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test ./y.sh clean all - name: Prepare dependencies @@ -108,5 +106,4 @@ jobs: - name: Run tests run: | - # TODO: remove --features master when it is back to the default. - ./y.sh test --release --features master --clean --build-sysroot ${{ matrix.commands }} + ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 729a76e80bf90..28336998ffcd7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,10 +53,8 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - # TODO: remove --features master when it is back to the default. - EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot --features master - # TODO: remove --features master when it is back to the default. - cargo test --features master + EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot + cargo test ./y.sh clean all - name: Prepare dependencies @@ -72,5 +70,4 @@ jobs: - name: Run tests run: | - # TODO: remove --features master when it is back to the default. - EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master + EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 65687756cd4eb..fa40c1a2beab7 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -67,10 +67,8 @@ jobs: - name: Build run: | ./y.sh prepare --only-libcore - # TODO: remove `--features master` when it is back to the default. - ./y.sh build --release --release-sysroot --features master - # TODO: remove --features master when it is back to the default. - cargo test --features master + ./y.sh build --release --release-sysroot + cargo test - name: Clean if: ${{ !matrix.cargo_runner }} @@ -86,8 +84,7 @@ jobs: - name: Run tests if: ${{ !matrix.cargo_runner }} run: | - # TODO: remove `--features master` when it is back to the default. - ./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master + ./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} diff --git a/Cargo.toml b/Cargo.toml index a280ac73de093..5e657c7c53959 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ harness = false [features] master = ["gccjit/master"] +default = ["master"] [dependencies] gccjit = { git = "https://github.com/antoyo/gccjit.rs" } diff --git a/Readme.md b/Readme.md index a380d0d5be6d1..5d960d0c2d606 100644 --- a/Readme.md +++ b/Readme.md @@ -69,13 +69,13 @@ Then you can run commands like this: ```bash $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking -$ ./y.sh build --release --features master +$ ./y.sh build --release ``` To run the tests: ```bash -$ ./y.sh test --release --features master +$ ./y.sh test --release ``` ## Usage From e4584e84d9a4687bedf1481b60c1751a2478967c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:51:43 +0000 Subject: [PATCH 148/613] Re-enable fixed rustc tests --- scripts/test_rustc_tests.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 3c9df40737ac3..eab04ca90b5af 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -43,7 +43,6 @@ rm tests/ui/proc-macro/allowed-signatures.rs rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs # vendor intrinsics -rm tests/ui/sse2.rs # CodegenBackend::target_features not yet implemented rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant" # exotic linkages @@ -62,14 +61,12 @@ rm -r tests/run-pass-valgrind/unsized-locals # misc unimplemented things rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and nearbyintf64 intrinsics rm tests/ui/target-feature/missing-plusminus.rs # error not implemented -rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment rm -r tests/run-make/emit-named-files # requires full --emit support rm -r tests/run-make/repr128-dwarf # debuginfo test rm -r tests/run-make/split-debuginfo # same rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same -rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly # requires LTO @@ -119,15 +116,12 @@ rm -r tests/run-make/issue-88756-default-output # should work when using ./x.py test the way it is intended # ============================================================ rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump -rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere # genuine bugs # ============ rm tests/incremental/spike-neg1.rs # errors out for some reason rm tests/incremental/spike-neg2.rs # same -rm tests/ui/simd/simd-bitmask.rs # simd_bitmask doesn't implement [u*; N] return type - rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj rm -r tests/run-make/issue-30063 # same rm -r tests/run-make/multiple-emits # same From 9539feb2f73b1e9370e28a6dcdaf0fe51bc65465 Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Thu, 15 Feb 2024 08:20:15 -0600 Subject: [PATCH 149/613] Update library/std/src/fs.rs Co-authored-by: Mara Bos --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index acc0f37a688a8..29b61a8d1d0bc 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -286,8 +286,8 @@ pub fn read>(path: P) -> io::Result> { /// use std::error::Error; /// /// fn main() -> Result<(), Box> { -/// let address: String = fs::read_to_string("address.txt")?; -/// println!("{}", address); +/// let message: String = fs::read_to_string("message.txt")?; +/// println!("{}", message); /// Ok(()) /// } /// ``` From b5e1ca39180e9997efef14d3b7d06a3ddff72b59 Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Thu, 15 Feb 2024 08:20:45 -0600 Subject: [PATCH 150/613] Update library/std/src/fs.rs Co-authored-by: Mara Bos --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 29b61a8d1d0bc..5bcd92b63df95 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -244,8 +244,8 @@ pub struct DirBuilder { /// use std::fs; /// /// fn main() -> Result<(), Box> { -/// let address: String = String::from_utf8_lossy(&fs::read("address.txt")?).to_string(); -/// println!("{}", address); +/// let data: Vec = fs::read("image.jpg")?; +/// assert_eq!(data[0..3], [0xFF, 0xD8, 0xFF]); /// Ok(()) /// } /// ``` From 290cbdf50ed7aa856a6794178500c7bd76fc7ec9 Mon Sep 17 00:00:00 2001 From: ltdk Date: Thu, 15 Feb 2024 10:13:47 -0500 Subject: [PATCH 151/613] Add slice::try_range --- library/alloc/src/slice.rs | 4 +-- library/core/src/slice/index.rs | 59 ++++++++++++++++++++++++++++++--- library/core/src/slice/mod.rs | 2 +- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index f4e392760c8e4..21d5dce04a0fc 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -33,8 +33,6 @@ use crate::vec::Vec; #[cfg(test)] mod tests; -#[unstable(feature = "slice_range", issue = "76393")] -pub use core::slice::range; #[unstable(feature = "array_chunks", issue = "74985")] pub use core::slice::ArrayChunks; #[unstable(feature = "array_chunks", issue = "74985")] @@ -51,6 +49,8 @@ pub use core::slice::{from_mut, from_ref}; pub use core::slice::{from_mut_ptr_range, from_ptr_range}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; +#[unstable(feature = "slice_range", issue = "76393")] +pub use core::slice::{range, try_range}; #[stable(feature = "slice_group_by", since = "1.77.0")] pub use core::slice::{ChunkBy, ChunkByMut}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index fb9be396eab80..c34d616e268f9 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -681,8 +681,7 @@ where { let len = bounds.end; - let start: ops::Bound<&usize> = range.start_bound(); - let start = match start { + let start = match range.start_bound() { ops::Bound::Included(&start) => start, ops::Bound::Excluded(start) => { start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) @@ -690,8 +689,7 @@ where ops::Bound::Unbounded => 0, }; - let end: ops::Bound<&usize> = range.end_bound(); - let end = match end { + let end = match range.end_bound() { ops::Bound::Included(end) => { end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) } @@ -709,6 +707,59 @@ where ops::Range { start, end } } +/// Performs bounds-checking of a range without panicking. +/// +/// This is a version of [`range`] that returns [`None`] instead of panicking. +/// +/// # Examples +/// +/// ``` +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// let v = [10, 40, 30]; +/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len())); +/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len())); +/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len())); +/// ``` +/// +/// Returns [`None`] when [`Index::index`] would panic: +/// +/// ``` +/// #![feature(slice_range)] +/// +/// use std::slice; +/// +/// assert_eq!(None, slice::try_range(2..1, ..3)); +/// assert_eq!(None, slice::try_range(1..4, ..3)); +/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3)); +/// ``` +/// +/// [`Index::index`]: ops::Index::index +#[unstable(feature = "slice_range", issue = "76393")] +#[must_use] +pub fn try_range(range: R, bounds: ops::RangeTo) -> Option> +where + R: ops::RangeBounds, +{ + let len = bounds.end; + + let start = match range.start_bound() { + ops::Bound::Included(&start) => start, + ops::Bound::Excluded(start) => start.checked_add(1)?, + ops::Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + ops::Bound::Included(end) => end.checked_add(1)?, + ops::Bound::Excluded(&end) => end, + ops::Bound::Unbounded => len, + }; + + if start > end || end > len { None } else { Some(ops::Range { start, end }) } +} + /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking pub(crate) fn into_range_unchecked( len: usize, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 73e92ed1dad63..aa228e12325ef 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -91,7 +91,7 @@ pub use sort::heapsort; pub use index::SliceIndex; #[unstable(feature = "slice_range", issue = "76393")] -pub use index::range; +pub use index::{range, try_range}; #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] pub use ascii::EscapeAscii; From af289a5eacbdf531ae22c5e90be7c8c627b20a93 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 15 Feb 2024 17:16:04 -0500 Subject: [PATCH 152/613] Use the default rust mangling --- Cargo.lock | 4 ++-- build_system/src/config.rs | 5 ++++- build_system/src/test.rs | 32 ++++++++++++++++++++------------ libgccjit.version | 2 +- src/declare.rs | 7 +++++-- src/lib.rs | 1 + 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a19de10d0d29b..786d753a1505f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,7 +80,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#e6109eb8b7ced60b5191e65b34954d04d4abeaec" +source = "git+https://github.com/antoyo/gccjit.rs#4b7aba76891e6436984f7f098fe92824d95194d5" dependencies = [ "gccjit_sys", ] @@ -88,7 +88,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#e6109eb8b7ced60b5191e65b34954d04d4abeaec" +source = "git+https://github.com/antoyo/gccjit.rs#4b7aba76891e6436984f7f098fe92824d95194d5" dependencies = [ "libc", ] diff --git a/build_system/src/config.rs b/build_system/src/config.rs index c89a6d5eb9b20..ddfc0e4a925da 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -415,8 +415,11 @@ impl ConfigInfo { if let Some(linker) = linker { rustflags.push(linker.to_string()); } + + #[cfg(not(feature="master"))] + rustflags.push("-Csymbol-mangling-version=v0".to_string()); + rustflags.extend_from_slice(&[ - "-Csymbol-mangling-version=v0".to_string(), "-Cdebuginfo=2".to_string(), format!("-Zcodegen-backend={}", self.cg_backend_path), ]); diff --git a/build_system/src/test.rs b/build_system/src/test.rs index d7f7a0eb47ef1..ab65fed0f75a4 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -612,6 +612,21 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); + let rustc_args = + &format!( + r#"-Zpanic-abort-tests \ + -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ + --sysroot "{pwd}/build_sysroot/sysroot" -Cpanic=abort"#, + pwd = std::env::current_dir() + .map_err(|error| format!("`current_dir` failed: {:?}", error))? + .display(), + channel = args.config_info.channel.as_str(), + dylib_ext = args.config_info.dylib_ext, + ); + + #[cfg(not(feature="master"))] + let rustc_args = format!("{} -Csymbol-mangling-version=v0", rustc_args); + run_command_with_env( &[ &"./x.py", @@ -622,17 +637,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"0", &"tests/assembly/asm", &"--rustc-args", - &format!( - r#"-Zpanic-abort-tests -Csymbol-mangling-version=v0 \ - -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ - --sysroot "{pwd}/build_sysroot/sysroot" -Cpanic=abort"#, - pwd = std::env::current_dir() - .map_err(|error| format!("`current_dir` failed: {:?}", error))? - .display(), - channel = args.config_info.channel.as_str(), - dylib_ext = args.config_info.dylib_ext, - ) - .as_str(), + &rustc_args, ], Some(&rust_dir), Some(&env), @@ -1065,12 +1070,15 @@ where println!("[TEST] rustc test suite"); env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); let rustc_args = format!( - "{} -Csymbol-mangling-version=v0 -Zcodegen-backend={} --sysroot {}", + "{} -Zcodegen-backend={} --sysroot {}", env.get("TEST_FLAGS").unwrap_or(&String::new()), args.config_info.cg_backend_path, args.config_info.sysroot_path, ); + #[cfg(not(feature="master"))] + let rustc_args = format!("{} -Csymbol-mangling-version=v0", rustc_args); + env.get_mut("RUSTFLAGS").unwrap().clear(); run_command_with_output_and_env( &[ diff --git a/libgccjit.version b/libgccjit.version index 3fc84f4ddd4ec..281a3ef5fa65c 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -2fc8940e1 +89a92e561 diff --git a/src/declare.rs b/src/declare.rs index 247454fa58e14..5ed6739883d82 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -125,7 +125,9 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll let params: Vec<_> = param_types.into_iter().enumerate() .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name. .collect(); - let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, mangle_name(name), variadic); + #[cfg(not(feature="master"))] + let name = mangle_name(name); + let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, &name, variadic); cx.functions.borrow_mut().insert(name.to_string(), func); #[cfg(feature="master")] @@ -180,7 +182,8 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll // FIXME(antoyo): this is a hack because libgccjit currently only supports alpha, num and _. // Unsupported characters: `$` and `.`. -pub fn mangle_name(name: &str) -> String { +#[cfg(not(feature="master"))] +fn mangle_name(name: &str) -> String { name.replace(|char: char| { if !char.is_alphanumeric() && char != '_' { debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char); diff --git a/src/lib.rs b/src/lib.rs index 5f8d00bb455e8..943a71ed953b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,6 +255,7 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { } #[cfg(feature="master")] { + context.set_allow_special_chars_in_func_names(true); let version = Version::get(); let version = format!("{}.{}.{}", version.major, version.minor, version.patch); context.set_output_ident(&format!("rustc version {} with libgccjit {}", From 7b1ac28f1c235ec5cd25bb0cd42014fdc95a5b46 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 17 Feb 2024 10:51:35 +1100 Subject: [PATCH 153/613] Make `CodegenBackend::join_codegen` infallible. Because they all are, in practice. --- src/lib.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 863b6333bcc29..09ce059476ec7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,13 +217,11 @@ impl CodegenBackend for GccCodegenBackend { Box::new(res) } - fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { - let (codegen_results, work_products) = ongoing_codegen + fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> (CodegenResults, FxIndexMap) { + ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") - .join(sess); - - Ok((codegen_results, work_products)) + .join(sess) } fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> { From 0fd329b96a613dafb6c3efbf2d17677d6eef417a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 17 Feb 2024 10:51:35 +1100 Subject: [PATCH 154/613] Make `CodegenBackend::join_codegen` infallible. Because they all are, in practice. --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7c432e9c59051..7e2e1f7c6ac07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -233,11 +233,11 @@ impl CodegenBackend for CraneliftCodegenBackend { ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { - Ok(ongoing_codegen + ) -> (CodegenResults, FxIndexMap) { + ongoing_codegen .downcast::() .unwrap() - .join(sess, self.config.borrow().as_ref().unwrap())) + .join(sess, self.config.borrow().as_ref().unwrap()) } fn link( From 4d93edf34630eec77bbd3d72bb644736528b544c Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 26 Jan 2024 18:48:18 +0100 Subject: [PATCH 155/613] Allow newly added non_local_definitions lint in clippy --- .../undocumented_unsafe_blocks.rs | 2 +- tests/ui/bool_comparison.fixed | 2 +- tests/ui/bool_comparison.rs | 2 +- tests/ui/crashes/ice-4760.rs | 2 + tests/ui/crashes/ice-6179.rs | 1 + tests/ui/explicit_into_iter_loop.fixed | 1 + tests/ui/explicit_into_iter_loop.rs | 1 + tests/ui/explicit_into_iter_loop.stderr | 12 ++--- tests/ui/explicit_iter_loop.fixed | 3 +- tests/ui/explicit_iter_loop.rs | 3 +- tests/ui/explicit_iter_loop.stderr | 36 ++++++------- tests/ui/from_over_into.fixed | 1 + tests/ui/from_over_into.rs | 1 + tests/ui/from_over_into.stderr | 14 ++--- tests/ui/manual_str_repeat.fixed | 1 + tests/ui/manual_str_repeat.rs | 1 + tests/ui/manual_str_repeat.stderr | 20 +++---- tests/ui/needless_borrow.fixed | 1 + tests/ui/needless_borrow.rs | 1 + tests/ui/needless_borrow.stderr | 54 +++++++++---------- 20 files changed, 86 insertions(+), 73 deletions(-) diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index a278139876064..8997073c8a555 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -4,7 +4,7 @@ //@[disabled] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/undocumented_unsafe_blocks/disabled #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)] -#![allow(deref_nullptr, clippy::let_unit_value, clippy::missing_safety_doc)] +#![allow(deref_nullptr, non_local_definitions, clippy::let_unit_value, clippy::missing_safety_doc)] #![feature(lint_reasons)] extern crate proc_macro_unsafe; diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 02f1d09b83395..600380fd1420d 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -1,4 +1,4 @@ -#![allow(clippy::needless_if)] +#![allow(non_local_definitions, clippy::needless_if)] #![warn(clippy::bool_comparison)] #![allow(clippy::non_canonical_partial_ord_impl)] diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 5ef696d855eca..910df6151f8c2 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,4 +1,4 @@ -#![allow(clippy::needless_if)] +#![allow(non_local_definitions, clippy::needless_if)] #![warn(clippy::bool_comparison)] #![allow(clippy::non_canonical_partial_ord_impl)] diff --git a/tests/ui/crashes/ice-4760.rs b/tests/ui/crashes/ice-4760.rs index 08b06961760ff..e1265169762fc 100644 --- a/tests/ui/crashes/ice-4760.rs +++ b/tests/ui/crashes/ice-4760.rs @@ -1,3 +1,5 @@ +#![allow(non_local_definitions)] + const COUNT: usize = 2; struct Thing; trait Dummy {} diff --git a/tests/ui/crashes/ice-6179.rs b/tests/ui/crashes/ice-6179.rs index ce1895851e2d9..fffc0f7d0d4f2 100644 --- a/tests/ui/crashes/ice-6179.rs +++ b/tests/ui/crashes/ice-6179.rs @@ -3,6 +3,7 @@ #![warn(clippy::use_self)] #![allow(dead_code, clippy::let_with_type_underscore)] +#![allow(non_local_definitions)] struct Foo; diff --git a/tests/ui/explicit_into_iter_loop.fixed b/tests/ui/explicit_into_iter_loop.fixed index 2521bce6a58e1..6d67488a71309 100644 --- a/tests/ui/explicit_into_iter_loop.fixed +++ b/tests/ui/explicit_into_iter_loop.fixed @@ -1,3 +1,4 @@ +#![allow(non_local_definitions)] #![warn(clippy::explicit_into_iter_loop)] fn main() { diff --git a/tests/ui/explicit_into_iter_loop.rs b/tests/ui/explicit_into_iter_loop.rs index 9eac96d182b9f..14630c07c5cc4 100644 --- a/tests/ui/explicit_into_iter_loop.rs +++ b/tests/ui/explicit_into_iter_loop.rs @@ -1,3 +1,4 @@ +#![allow(non_local_definitions)] #![warn(clippy::explicit_into_iter_loop)] fn main() { diff --git a/tests/ui/explicit_into_iter_loop.stderr b/tests/ui/explicit_into_iter_loop.stderr index c03647ab43367..a1e632271ed32 100644 --- a/tests/ui/explicit_into_iter_loop.stderr +++ b/tests/ui/explicit_into_iter_loop.stderr @@ -1,5 +1,5 @@ error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:9:18 + --> $DIR/explicit_into_iter_loop.rs:10:18 | LL | for _ in iterator.into_iter() {} | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` @@ -8,31 +8,31 @@ LL | for _ in iterator.into_iter() {} = help: to override `-D warnings` add `#[allow(clippy::explicit_into_iter_loop)]` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:22:14 + --> $DIR/explicit_into_iter_loop.rs:23:14 | LL | for _ in t.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:25:14 + --> $DIR/explicit_into_iter_loop.rs:26:14 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:33:14 + --> $DIR/explicit_into_iter_loop.rs:34:14 | LL | for _ in mr.into_iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&*mr` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:45:14 + --> $DIR/explicit_into_iter_loop.rs:46:14 | LL | for _ in u.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut u` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/explicit_into_iter_loop.rs:48:14 + --> $DIR/explicit_into_iter_loop.rs:49:14 | LL | for _ in mr.into_iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *mr` diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed index f08397defa539..06229a52a18c4 100644 --- a/tests/ui/explicit_iter_loop.fixed +++ b/tests/ui/explicit_iter_loop.fixed @@ -5,7 +5,8 @@ clippy::needless_borrow, clippy::deref_addrof, clippy::unnecessary_mut_passed, - dead_code + dead_code, + non_local_definitions, )] use core::slice; diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs index 2ee6825d445c2..c2bf45ab2e990 100644 --- a/tests/ui/explicit_iter_loop.rs +++ b/tests/ui/explicit_iter_loop.rs @@ -5,7 +5,8 @@ clippy::needless_borrow, clippy::deref_addrof, clippy::unnecessary_mut_passed, - dead_code + dead_code, + non_local_definitions, )] use core::slice; diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr index 725d9b63cf8d6..007606b52c294 100644 --- a/tests/ui/explicit_iter_loop.stderr +++ b/tests/ui/explicit_iter_loop.stderr @@ -1,5 +1,5 @@ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:17:14 + --> $DIR/explicit_iter_loop.rs:18:14 | LL | for _ in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -11,103 +11,103 @@ LL | #![deny(clippy::explicit_iter_loop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:18:14 + --> $DIR/explicit_iter_loop.rs:19:14 | LL | for _ in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:21:14 + --> $DIR/explicit_iter_loop.rs:22:14 | LL | for _ in rvec.iter() {} | ^^^^^^^^^^^ help: to write this more concisely, try: `rvec` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:30:14 + --> $DIR/explicit_iter_loop.rs:31:14 | LL | for _ in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:34:14 + --> $DIR/explicit_iter_loop.rs:35:14 | LL | for _ in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:35:14 + --> $DIR/explicit_iter_loop.rs:36:14 | LL | for _ in [0; 33].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 33]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:38:14 + --> $DIR/explicit_iter_loop.rs:39:14 | LL | for _ in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:40:14 + --> $DIR/explicit_iter_loop.rs:41:14 | LL | for _ in rll.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `rll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:43:14 + --> $DIR/explicit_iter_loop.rs:44:14 | LL | for _ in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:45:14 + --> $DIR/explicit_iter_loop.rs:46:14 | LL | for _ in rvd.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `rvd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:48:14 + --> $DIR/explicit_iter_loop.rs:49:14 | LL | for _ in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:51:14 + --> $DIR/explicit_iter_loop.rs:52:14 | LL | for _ in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:54:14 + --> $DIR/explicit_iter_loop.rs:55:14 | LL | for _ in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:57:14 + --> $DIR/explicit_iter_loop.rs:58:14 | LL | for _ in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:60:14 + --> $DIR/explicit_iter_loop.rs:61:14 | LL | for _ in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:149:14 + --> $DIR/explicit_iter_loop.rs:150:14 | LL | for _ in x.iter() {} | ^^^^^^^^ help: to write this more concisely, try: `&x` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:150:14 + --> $DIR/explicit_iter_loop.rs:151:14 | LL | for _ in x.iter_mut() {} | ^^^^^^^^^^^^ help: to write this more concisely, try: `&mut x` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/explicit_iter_loop.rs:153:14 + --> $DIR/explicit_iter_loop.rs:154:14 | LL | for _ in r.iter() {} | ^^^^^^^^ help: to write this more concisely, try: `r` diff --git a/tests/ui/from_over_into.fixed b/tests/ui/from_over_into.fixed index 4a68505ee0b1c..a33c1ea5738b9 100644 --- a/tests/ui/from_over_into.fixed +++ b/tests/ui/from_over_into.fixed @@ -1,5 +1,6 @@ #![feature(type_alias_impl_trait)] #![warn(clippy::from_over_into)] +#![allow(non_local_definitions)] #![allow(unused)] // this should throw an error diff --git a/tests/ui/from_over_into.rs b/tests/ui/from_over_into.rs index bf3ed0c2b6422..6cd811ae401e2 100644 --- a/tests/ui/from_over_into.rs +++ b/tests/ui/from_over_into.rs @@ -1,5 +1,6 @@ #![feature(type_alias_impl_trait)] #![warn(clippy::from_over_into)] +#![allow(non_local_definitions)] #![allow(unused)] // this should throw an error diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index f1370ed844fa9..15b4e02a264f1 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -1,5 +1,5 @@ error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:8:1 + --> $DIR/from_over_into.rs:9:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL ~ StringWrapper(val) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:16:1 + --> $DIR/from_over_into.rs:17:1 | LL | impl Into for String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL ~ SelfType(String::new()) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:31:1 + --> $DIR/from_over_into.rs:32:1 | LL | impl Into for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL ~ let _: X = val; | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:43:1 + --> $DIR/from_over_into.rs:44:1 | LL | impl core::convert::Into for crate::ExplicitPaths { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL ~ val.0 | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:63:1 + --> $DIR/from_over_into.rs:64:1 | LL | impl Into for PathInExpansion { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL ~ fn from(val: PathInExpansion) -> Self { | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:85:5 + --> $DIR/from_over_into.rs:86:5 | LL | impl Into> for Vec { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL ~ FromOverInto(val) | error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into.rs:95:5 + --> $DIR/from_over_into.rs:96:5 | LL | impl Into<()> for Hello { | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/manual_str_repeat.fixed b/tests/ui/manual_str_repeat.fixed index 888a466278ccc..5f2f1bd9916d8 100644 --- a/tests/ui/manual_str_repeat.fixed +++ b/tests/ui/manual_str_repeat.fixed @@ -1,3 +1,4 @@ +#![allow(non_local_definitions)] #![warn(clippy::manual_str_repeat)] use std::borrow::Cow; diff --git a/tests/ui/manual_str_repeat.rs b/tests/ui/manual_str_repeat.rs index a366351ffa45a..3e3c7f4db4a27 100644 --- a/tests/ui/manual_str_repeat.rs +++ b/tests/ui/manual_str_repeat.rs @@ -1,3 +1,4 @@ +#![allow(non_local_definitions)] #![warn(clippy::manual_str_repeat)] use std::borrow::Cow; diff --git a/tests/ui/manual_str_repeat.stderr b/tests/ui/manual_str_repeat.stderr index 9a13aa9722737..6eb6f2b85a8f4 100644 --- a/tests/ui/manual_str_repeat.stderr +++ b/tests/ui/manual_str_repeat.stderr @@ -1,5 +1,5 @@ error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:7:21 + --> $DIR/manual_str_repeat.rs:8:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"test".repeat(10)` @@ -8,55 +8,55 @@ LL | let _: String = std::iter::repeat("test").take(10).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_str_repeat)]` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:8:21 + --> $DIR/manual_str_repeat.rs:9:21 | LL | let _: String = std::iter::repeat('x').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"x".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:9:21 + --> $DIR/manual_str_repeat.rs:10:21 | LL | let _: String = std::iter::repeat('\'').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"'".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:10:21 + --> $DIR/manual_str_repeat.rs:11:21 | LL | let _: String = std::iter::repeat('"').take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"\"".repeat(10)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:14:13 + --> $DIR/manual_str_repeat.rs:15:13 | LL | let _ = repeat(x).take(count + 2).collect::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count + 2)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:23:21 + --> $DIR/manual_str_repeat.rs:24:21 | LL | let _: String = repeat(*x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*x).repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:32:21 + --> $DIR/manual_str_repeat.rs:33:21 | LL | let _: String = repeat(x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:44:21 + --> $DIR/manual_str_repeat.rs:45:21 | LL | let _: String = repeat(Cow::Borrowed("test")).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Cow::Borrowed("test").repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:47:21 + --> $DIR/manual_str_repeat.rs:48:21 | LL | let _: String = repeat(x).take(count).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.repeat(count)` error: manual implementation of `str::repeat` using iterators - --> $DIR/manual_str_repeat.rs:62:21 + --> $DIR/manual_str_repeat.rs:63:21 | LL | let _: String = std::iter::repeat("test").take(10).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"test".repeat(10)` diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 23e8bf8a468fd..998f5430fdf05 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -1,6 +1,7 @@ #![feature(lint_reasons)] #![allow( unused, + non_local_definitions, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, clippy::unnecessary_to_owned, diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 27771a8f15b30..acb2c74d849a2 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -1,6 +1,7 @@ #![feature(lint_reasons)] #![allow( unused, + non_local_definitions, clippy::uninlined_format_args, clippy::unnecessary_mut_passed, clippy::unnecessary_to_owned, diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index a21ed8382c14e..9034bd83a0b05 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:15:15 + --> $DIR/needless_borrow.rs:16:15 | LL | let _ = x(&&a); // warn | ^^^ help: change this to: `&a` @@ -8,157 +8,157 @@ LL | let _ = x(&&a); // warn = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:19:13 + --> $DIR/needless_borrow.rs:20:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:31:13 + --> $DIR/needless_borrow.rs:32:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:33:15 + --> $DIR/needless_borrow.rs:34:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:39:27 + --> $DIR/needless_borrow.rs:40:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:46:15 + --> $DIR/needless_borrow.rs:47:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:47:15 + --> $DIR/needless_borrow.rs:48:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:48:15 + --> $DIR/needless_borrow.rs:49:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:49:15 + --> $DIR/needless_borrow.rs:50:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:52:11 + --> $DIR/needless_borrow.rs:53:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:59:13 + --> $DIR/needless_borrow.rs:60:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:60:13 + --> $DIR/needless_borrow.rs:61:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:61:23 + --> $DIR/needless_borrow.rs:62:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:62:23 + --> $DIR/needless_borrow.rs:63:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:71:14 + --> $DIR/needless_borrow.rs:72:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:77:14 + --> $DIR/needless_borrow.rs:78:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:89:13 + --> $DIR/needless_borrow.rs:90:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:91:22 + --> $DIR/needless_borrow.rs:92:22 | LL | let _ = unsafe { (&*x).0 }; | ^^^^^ help: change this to: `(*x)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:101:5 + --> $DIR/needless_borrow.rs:102:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:110:5 + --> $DIR/needless_borrow.rs:111:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:136:23 + --> $DIR/needless_borrow.rs:137:23 | LL | let x: (&str,) = (&"",); | ^^^ help: change this to: `""` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:178:13 + --> $DIR/needless_borrow.rs:179:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:187:13 + --> $DIR/needless_borrow.rs:188:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:224:22 + --> $DIR/needless_borrow.rs:225:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:231:22 + --> $DIR/needless_borrow.rs:232:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:235:22 + --> $DIR/needless_borrow.rs:236:22 | LL | let _ = &mut (&mut x.u).x; | ^^^^^^^^^^ help: change this to: `x.u` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:236:22 + --> $DIR/needless_borrow.rs:237:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` From 6bdcc3c4c71dd63a28a9920be011c20df3099f62 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 17 Feb 2024 16:59:30 +0100 Subject: [PATCH 156/613] Move subtree part of Readme into its own doc file --- Readme.md | 45 ------------------------------------------- doc/subtree.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 45 deletions(-) create mode 100644 doc/subtree.md diff --git a/Readme.md b/Readme.md index 5d960d0c2d606..dc9d0a4fd1279 100644 --- a/Readme.md +++ b/Readme.md @@ -269,51 +269,6 @@ COLLECT_NO_DEMANGLE=1 * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. -### How to install a forked git-subtree - -Using git-subtree with `rustc` requires a patched git to make it work. -The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493). -Use the following instructions to install it: - -```bash -git clone git@github.com:tqc/git.git -cd git -git checkout tqc/subtree -make -make install -cd contrib/subtree -make -cp git-subtree ~/bin -``` - -Then, do a sync with this command: - -```bash -PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name -cd ../rustc_codegen_gcc -git checkout master -git pull -git checkout sync_branch_name -git merge master -``` - -To send the changes to the rust repo: - -```bash -cd ../rust -git pull origin master -git checkout -b subtree-update_cg_gcc_YYYY-MM-DD -PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master -git push - -# Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. -PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name -``` - -TODO: write a script that does the above. - -https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725 - ### How to use [mem-trace](https://github.com/antoyo/mem-trace) `rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`. diff --git a/doc/subtree.md b/doc/subtree.md new file mode 100644 index 0000000000000..5d7af2a066bd3 --- /dev/null +++ b/doc/subtree.md @@ -0,0 +1,52 @@ +# git subtree sync + +`rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be +sync from time to time to ensure changes that happened on their side are also +included on our side. + +### How to install a forked git-subtree + +Using git-subtree with `rustc` requires a patched git to make it work. +The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493). +Use the following instructions to install it: + +```bash +git clone git@github.com:tqc/git.git +cd git +git checkout tqc/subtree +make +make install +cd contrib/subtree +make +cp git-subtree ~/bin +``` + +### Syncing with rust compiler + +Do a sync with this command: + +```bash +PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name +cd ../rustc_codegen_gcc +git checkout master +git pull +git checkout sync_branch_name +git merge master +``` + +To send the changes to the rust repo: + +```bash +cd ../rust +git pull origin master +git checkout -b subtree-update_cg_gcc_YYYY-MM-DD +PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master +git push + +# Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. +PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name +``` + +TODO: write a script that does the above. + +https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725 From cb14f43de634d3f605559158b705e03e5537ba95 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 17 Feb 2024 17:04:32 +0100 Subject: [PATCH 157/613] Improve instructions to start working on the project --- Readme.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Readme.md b/Readme.md index dc9d0a4fd1279..2c6d21b3f9602 100644 --- a/Readme.md +++ b/Readme.md @@ -17,6 +17,18 @@ A secondary goal is to check if using the gcc backend will provide any run-time **This requires a patched libgccjit in order to work. You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** +```bash +$ cp config.example.toml config.toml +``` + +If don't need to test GCC patches you wrote in our GCC fork, then the default configuration should +be all you need. You can update the `rustc_codegen_gcc` without worrying about GCC. + +### Building with your own GCC version + +If you wrote a patch for GCC and want to test it without this backend, you will need +to do a few more things. + To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue): ```bash @@ -51,18 +63,17 @@ $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc" **Put the path to your custom build of libgccjit in the file `config.toml`.** -If you followed the instructions exactly as written (ie, you have created a `gcc-build` folder -where gcc is built), the only thing you need to do is: +You now need to set the `gcc-path` value in `config.toml` with the result of this command: ```bash -$ cp config.example.toml config.toml +$ dirname $(readlink -f `find . -name libgccjit.so`) ``` -But if you did something different, you also need to set the `gcc-path` value in `config.toml` with -the result of this command: +and to comment the `download-gccjit` setting: -```bash -$ dirname $(readlink -f `find . -name libgccjit.so`) +```toml +gcc-path = "[MY PATH]" +# download-gccjit = true ``` Then you can run commands like this: From 79316d4e8313951ace166dd0c96108c3d9b70dab Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 17 Feb 2024 17:13:48 +0100 Subject: [PATCH 158/613] Split Readme even further --- Readme.md | 182 +++---------------------------------- doc/debugging-gcc-lto.md | 3 + doc/debugging-libgccjit.md | 74 +++++++++++++++ doc/errors.md | 27 ++++++ doc/tips.md | 72 +++++++++++++++ 5 files changed, 187 insertions(+), 171 deletions(-) create mode 100644 doc/debugging-gcc-lto.md create mode 100644 doc/debugging-libgccjit.md create mode 100644 doc/errors.md create mode 100644 doc/tips.md diff --git a/Readme.md b/Readme.md index 2c6d21b3f9602..da6e91587fdaf 100644 --- a/Readme.md +++ b/Readme.md @@ -139,179 +139,19 @@ $ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(ca
Dump a C-like representation to /tmp/gccjit_dumps and enable debug info in order to debug this C-like representation.
-## Licensing - -While this crate is licensed under a dual Apache/MIT license, it links to `libgccjit` which is under the GPLv3+ and thus, the resulting toolchain (rustc + GCC codegen) will need to be released under the GPL license. - -However, programs compiled with `rustc_codegen_gcc` do not need to be released under a GPL license. - -## Debugging - -Sometimes, libgccjit will crash and output an error like this: - -``` -during RTL pass: expand -libgccjit.so: error: in expmed_mode_index, at expmed.h:249 -0x7f0da2e61a35 expmed_mode_index - ../../../gcc/gcc/expmed.h:249 -0x7f0da2e61aa4 expmed_op_cost_ptr - ../../../gcc/gcc/expmed.h:271 -0x7f0da2e620dc sdiv_cost_ptr - ../../../gcc/gcc/expmed.h:540 -0x7f0da2e62129 sdiv_cost - ../../../gcc/gcc/expmed.h:558 -0x7f0da2e73c12 expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int) - ../../../gcc/gcc/expmed.c:4335 -0x7f0da2ea1423 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) - ../../../gcc/gcc/expr.c:9240 -0x7f0da2cd1a1e expand_gimple_stmt_1 - ../../../gcc/gcc/cfgexpand.c:3796 -0x7f0da2cd1c30 expand_gimple_stmt - ../../../gcc/gcc/cfgexpand.c:3857 -0x7f0da2cd90a9 expand_gimple_basic_block - ../../../gcc/gcc/cfgexpand.c:5898 -0x7f0da2cdade8 execute - ../../../gcc/gcc/cfgexpand.c:6582 -``` - -To see the code which causes this error, call the following function: - -```c -gcc_jit_context_dump_to_file(ctxt, "/tmp/output.c", 1 /* update_locations */) -``` - -This will create a C-like file and add the locations into the IR pointing to this C file. -Then, rerun the program and it will output the location in the second line: - -``` -libgccjit.so: /tmp/something.c:61322:0: error: in expmed_mode_index, at expmed.h:249 -``` - -Or add a breakpoint to `add_error` in gdb and print the line number using: - -``` -p loc->m_line -p loc->m_filename->m_buffer -``` - -To print a debug representation of a tree: - -```c -debug_tree(expr); -``` - -(defined in print-tree.h) - -To print a debug representation of a gimple struct: - -```c -debug_gimple_stmt(gimple_struct) -``` - -To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`. - -To have the correct file paths in `gdb` instead of `/usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_personality.cc`: - -Maybe by calling the following at the beginning of gdb: - -``` -set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc -``` - -TODO(antoyo): but that's not what I remember I was doing. - -### `failed to build archive` error - -When you get this error: - -``` -error: failed to build archive: failed to open object file: No such file or directory (os error 2) -``` - -That can be caused by the fact that you try to compile with `lto = "fat"`, but you didn't compile the sysroot with LTO. -(Not sure if that's the reason since I cannot reproduce anymore. Maybe it happened when forgetting setting `FAT_LTO`.) +## Extra documentation -### ld: cannot find crtbegin.o +More specific documentation is available in the [`doc`](./doc) folder: -When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors: + * [Common errors](./doc/errors.md) + * [Debugging GCC LTO](./doc/debugging-gcc-lto.md) + * [Debugging libgccjit](./doc/debugging-libgccjit.md) + * [Git subtree sync](./doc/subtree.md) + * [List of useful commands](./doc/tips.md) + * [Send a patch to GCC](./doc/sending-gcc-patch.md) -``` -ld: cannot find crtbegin.o: No such file or directory -ld: cannot find -lgcc: No such file or directory -ld: cannot find -lgcc: No such file or directory -libgccjit.so: error: error invoking gcc driver -``` - -To fix this, set the variables to `gcc-build/build/gcc`. - -### How to debug GCC LTO - -Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger. - -### How to send arguments to the GCC linker - -``` -CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../y.sh cargo build -``` - -### How to see the personality functions in the asm dump - -``` -CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../y.sh cargo build -``` - -### How to see the LLVM IR for a sysroot crate - -``` -cargo build -v --target x86_64-unknown-linux-gnu -Zbuild-std -# Take the command from the output and add --emit=llvm-ir -``` - -### To prevent the linker from unmangling symbols - -Run with: - -``` -COLLECT_NO_DEMANGLE=1 -``` - -### How to use a custom-build rustc - - * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). - * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. - -### How to use [mem-trace](https://github.com/antoyo/mem-trace) - -`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`. - -### How to generate GIMPLE - -If you need to check what gccjit is generating (GIMPLE), then take a look at how to -generate it in [gimple.md](./doc/gimple.md). - -### How to build a cross-compiling libgccjit - -#### Building libgccjit - - * Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc). - -#### Configuring rustc_codegen_gcc - - * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. - * Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`). - * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`. - * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`. - -If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler). -Then, you can use it the following way: - - * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json` - * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`. - -If you get the following error: +## Licensing -``` -/usr/bin/ld: unrecognised emulation mode: m68kelf -``` +While this crate is licensed under a dual Apache/MIT license, it links to `libgccjit` which is under the GPLv3+ and thus, the resulting toolchain (rustc + GCC codegen) will need to be released under the GPL license. -Make sure you set `gcc-path` (in `config.toml`) to the install directory. +However, programs compiled with `rustc_codegen_gcc` do not need to be released under a GPL license. diff --git a/doc/debugging-gcc-lto.md b/doc/debugging-gcc-lto.md new file mode 100644 index 0000000000000..93b150d768650 --- /dev/null +++ b/doc/debugging-gcc-lto.md @@ -0,0 +1,3 @@ +# How to debug GCC LTO + +Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger. diff --git a/doc/debugging-libgccjit.md b/doc/debugging-libgccjit.md new file mode 100644 index 0000000000000..be0ec83f7cdc6 --- /dev/null +++ b/doc/debugging-libgccjit.md @@ -0,0 +1,74 @@ +# Debugging libgccjit + +Sometimes, libgccjit will crash and output an error like this: + +``` +during RTL pass: expand +libgccjit.so: error: in expmed_mode_index, at expmed.h:249 +0x7f0da2e61a35 expmed_mode_index + ../../../gcc/gcc/expmed.h:249 +0x7f0da2e61aa4 expmed_op_cost_ptr + ../../../gcc/gcc/expmed.h:271 +0x7f0da2e620dc sdiv_cost_ptr + ../../../gcc/gcc/expmed.h:540 +0x7f0da2e62129 sdiv_cost + ../../../gcc/gcc/expmed.h:558 +0x7f0da2e73c12 expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int) + ../../../gcc/gcc/expmed.c:4335 +0x7f0da2ea1423 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier) + ../../../gcc/gcc/expr.c:9240 +0x7f0da2cd1a1e expand_gimple_stmt_1 + ../../../gcc/gcc/cfgexpand.c:3796 +0x7f0da2cd1c30 expand_gimple_stmt + ../../../gcc/gcc/cfgexpand.c:3857 +0x7f0da2cd90a9 expand_gimple_basic_block + ../../../gcc/gcc/cfgexpand.c:5898 +0x7f0da2cdade8 execute + ../../../gcc/gcc/cfgexpand.c:6582 +``` + +To see the code which causes this error, call the following function: + +```c +gcc_jit_context_dump_to_file(ctxt, "/tmp/output.c", 1 /* update_locations */) +``` + +This will create a C-like file and add the locations into the IR pointing to this C file. +Then, rerun the program and it will output the location in the second line: + +``` +libgccjit.so: /tmp/something.c:61322:0: error: in expmed_mode_index, at expmed.h:249 +``` + +Or add a breakpoint to `add_error` in gdb and print the line number using: + +``` +p loc->m_line +p loc->m_filename->m_buffer +``` + +To print a debug representation of a tree: + +```c +debug_tree(expr); +``` + +(defined in print-tree.h) + +To print a debug representation of a gimple struct: + +```c +debug_gimple_stmt(gimple_struct) +``` + +To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`. + +To have the correct file paths in `gdb` instead of `/usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_personality.cc`: + +Maybe by calling the following at the beginning of gdb: + +``` +set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc +``` + +TODO(antoyo): but that's not what I remember I was doing. diff --git a/doc/errors.md b/doc/errors.md new file mode 100644 index 0000000000000..5727b0ff7c867 --- /dev/null +++ b/doc/errors.md @@ -0,0 +1,27 @@ +# Common errors + +This file lists errors that were encountered and how to fix them. + +### `failed to build archive` error + +When you get this error: + +``` +error: failed to build archive: failed to open object file: No such file or directory (os error 2) +``` + +That can be caused by the fact that you try to compile with `lto = "fat"`, but you didn't compile the sysroot with LTO. +(Not sure if that's the reason since I cannot reproduce anymore. Maybe it happened when forgetting setting `FAT_LTO`.) + +### ld: cannot find crtbegin.o + +When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors: + +``` +ld: cannot find crtbegin.o: No such file or directory +ld: cannot find -lgcc: No such file or directory +ld: cannot find -lgcc: No such file or directory +libgccjit.so: error: error invoking gcc driver +``` + +To fix this, set the variables to `gcc-build/build/gcc`. diff --git a/doc/tips.md b/doc/tips.md new file mode 100644 index 0000000000000..1379f5130be02 --- /dev/null +++ b/doc/tips.md @@ -0,0 +1,72 @@ +# Tips + +The following shows how to do different random small things we encountered and thought could +be useful. + +### How to send arguments to the GCC linker + +``` +CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../y.sh cargo build +``` + +### How to see the personality functions in the asm dump + +``` +CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../y.sh cargo build +``` + +### How to see the LLVM IR for a sysroot crate + +``` +cargo build -v --target x86_64-unknown-linux-gnu -Zbuild-std +# Take the command from the output and add --emit=llvm-ir +``` + +### To prevent the linker from unmangling symbols + +Run with: + +``` +COLLECT_NO_DEMANGLE=1 +``` + +### How to use a custom-build rustc + + * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). + * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. + +### How to use [mem-trace](https://github.com/antoyo/mem-trace) + +`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`. + +### How to generate GIMPLE + +If you need to check what gccjit is generating (GIMPLE), then take a look at how to +generate it in [gimple.md](./doc/gimple.md). + +### How to build a cross-compiling libgccjit + +#### Building libgccjit + + * Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc). + +#### Configuring rustc_codegen_gcc + + * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. + * Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`). + * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`. + * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`. + +If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler). +Then, you can use it the following way: + + * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json` + * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`. + +If you get the following error: + +``` +/usr/bin/ld: unrecognised emulation mode: m68kelf +``` + +Make sure you set `gcc-path` (in `config.toml`) to the install directory. From 0a66c555bd4e8599e9710652509bfbdca366f36d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 17 Feb 2024 20:04:17 +0100 Subject: [PATCH 159/613] Revert "Use shallow clone in test.rs to reduce cloning overhead" --- build_system/src/test.rs | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 9fe9708c2917b..d7f7a0eb47ef1 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -499,42 +499,17 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { &"clone", &"https://github.com/rust-lang/rust.git", &rust_dir_path, - &"--depth", - &"1", ], None, Some(env), ); let rust_dir: Option<&Path> = Some(&rust_dir_path); run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?; + run_command_with_output_and_env(&[&"git", &"fetch"], rust_dir, Some(env))?; let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash { Some(commit_hash) => commit_hash, None => return Err("Couldn't retrieve rustc commit hash".to_string()), }; - let has_commit = { - if let Ok(ty) = run_command_with_env( - &[&"git", &"cat-file", &"-t", &rustc_commit.as_str()], - rust_dir, - Some(env), - ) { - String::from_utf8_lossy(&ty.stdout).to_string() == "commit" - } else { - false - } - }; - if !has_commit { - run_command_with_output_and_env( - &[ - &"git", - &"fetch", - &"https://github.com/rust-lang/rust.git", - &rustc_commit.as_str(), - &"--depth=1", - ], - rust_dir, - Some(env), - )? - }; if rustc_commit != "unknown" { run_command_with_output_and_env( &[&"git", &"checkout", &rustc_commit], From e116cb7811510936c4386322cc27255bc97f656a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 15 Feb 2024 18:12:42 -0400 Subject: [PATCH 160/613] Fix to use the correct libgccjit for the CI where 128-bit integers are disabled --- .github/workflows/ci.yml | 24 ++++++++++++------------ .github/workflows/stdarch.yml | 20 ++++++++++---------- libgccjit.version | 2 +- src/declare.rs | 3 ++- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37d2bc1c201af..ab704aa80a2b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,8 +19,8 @@ jobs: fail-fast: false matrix: libgccjit_version: - - { gcc: "libgccjit.so", artifacts_branch: "master" } - - { gcc: "libgccjit_without_int128.so", artifacts_branch: "master-without-128bit-integers" } + - { gcc: "gcc-13.deb" } + - { gcc: "gcc-13-without-int128.deb" } commands: [ "--mini-tests", "--std-tests", @@ -49,10 +49,19 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools + - name: Download artifact + run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }} + + - name: Setup path to libgccjit + run: | + sudo dpkg --force-overwrite -i ${{ matrix.libgccjit_version.gcc }} + echo 'gcc-path = "/usr/lib/"' > config.toml + - name: Set env run: | echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - echo 'download-gccjit = true' > config.toml + echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV #- name: Cache rust repository ## We only clone the rust repository for rustc tests @@ -67,15 +76,6 @@ jobs: run: | ./y.sh prepare --only-libcore ./y.sh build - - - name: Set env (part 2) - run: | - # Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables... - echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV - echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV - - - name: Build (part 2) - run: | cargo test ./y.sh clean all diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index fa40c1a2beab7..41a9318007f15 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -50,24 +50,24 @@ jobs: sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64 - - name: Download artifact - run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb - - - name: Setup path to libgccjit - run: | - sudo dpkg --force-overwrite -i gcc-13.deb - echo 'gcc-path = "/usr/lib/"' > config.toml - - name: Set env run: | echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV - echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV + echo 'download-gccjit = true' > config.toml - name: Build run: | ./y.sh prepare --only-libcore ./y.sh build --release --release-sysroot + + - name: Set env (part 2) + run: | + # Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables... + echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV + echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV + + - name: Build (part 2) + run: | cargo test - name: Clean diff --git a/libgccjit.version b/libgccjit.version index 281a3ef5fa65c..12dafeb9edeed 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -89a92e561 +cdd897840 diff --git a/src/declare.rs b/src/declare.rs index 5ed6739883d82..72cba9fbba95a 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -181,7 +181,8 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll } // FIXME(antoyo): this is a hack because libgccjit currently only supports alpha, num and _. -// Unsupported characters: `$` and `.`. +// Unsupported characters: `$`, `.` and `*`. +// FIXME(antoyo): `*` might not be expected: https://github.com/rust-lang/rust/issues/116979#issuecomment-1840926865 #[cfg(not(feature="master"))] fn mangle_name(name: &str) -> String { name.replace(|char: char| { From 5ac9bee7f13c83123cc3d184f50a255248e640f2 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Sat, 17 Feb 2024 17:19:08 -0600 Subject: [PATCH 161/613] fix tests/ui/simd/issue-89193.rs and mark as passing Work around an issue where usize and isize can sometimes (but not always) get canonicalized to their corresponding integer type. This causes shuffle_vector to panic, since the types of the vectors it got passed aren't the same. Also insert a cast on the mask element, since we might get passed a signed integer of any size, not just i32. For now, we always cast to i32. Signed-off-by: Andy Sadler --- src/intrinsic/simd.rs | 15 +++++++++++---- tests/failing-ui-tests.txt | 1 - 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 5991f061c10cc..33d659f251fe1 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -710,7 +710,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); - let mut values = vec![]; + let mut values = Vec::with_capacity(in_len as usize); for i in 0..in_len { let index = bx.context.new_rvalue_from_long(bx.i32_type, i as i64); let int = bx.context.new_vector_access(None, pointers, index).to_rvalue(); @@ -723,19 +723,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let vector = bx.context.new_rvalue_from_vector(None, vector_type, &values); - let mut mask_types = vec![]; - let mut mask_values = vec![]; + let mut mask_types = Vec::with_capacity(in_len as usize); + let mut mask_values = Vec::with_capacity(in_len as usize); for i in 0..in_len { let index = bx.context.new_rvalue_from_long(bx.i32_type, i as i64); mask_types.push(bx.context.new_field(None, bx.i32_type, "m")); let mask_value = bx.context.new_vector_access(None, mask, index).to_rvalue(); - let masked = bx.context.new_rvalue_from_int(bx.i32_type, in_len as i32) & mask_value; + let mask_value_cast = bx.context.new_cast(None, mask_value, bx.i32_type); + let masked = bx.context.new_rvalue_from_int(bx.i32_type, in_len as i32) & mask_value_cast; let value = index + masked; mask_values.push(value); } let mask_type = bx.context.new_struct_type(None, "mask_type", &mask_types); let mask = bx.context.new_struct_constructor(None, mask_type.as_type(), None, &mask_values); + // FIXME(antoyo): We sometimes need to bitcast here, since usize/isize sometimes (but not + // always) get canonicalized to their corresponding integer type (i.e. uint64_t/int64_t on + // 64-bit platforms). This causes the shuffle_vector call below to panic, since the types + // of the two vectors aren't the same. This is a workaround for now. + let vector = bx.bitcast_if_needed(vector, default.get_type()); + if invert { bx.shuffle_vector(vector, default, mask) } else { diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 023fe9d7e8311..6e020e9b354da 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -48,7 +48,6 @@ tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs -tests/ui/simd/issue-89193.rs tests/ui/statics/issue-91050-1.rs tests/ui/statics/issue-91050-2.rs tests/ui/alloc-error/default-alloc-error-hook.rs From 087456f1229998ff28cc25d8d849375f62c66d8e Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Sat, 17 Feb 2024 18:07:11 -0600 Subject: [PATCH 162/613] mark tests/ui/simd/issue-89193.rs as failing for libgccjit12 Signed-off-by: Andy Sadler --- tests/failing-ui-tests12.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/failing-ui-tests12.txt b/tests/failing-ui-tests12.txt index b4615b26852d8..64f89b03eecc8 100644 --- a/tests/failing-ui-tests12.txt +++ b/tests/failing-ui-tests12.txt @@ -33,6 +33,7 @@ tests/ui/coroutine/size-moved-locals.rs tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs tests/ui/simd/intrinsic/generic-gather-pass.rs tests/ui/simd/issue-85915-simd-ptrs.rs +tests/ui/simd/issue-89193.rs tests/ui/issues/issue-68010-large-zst-consts.rs tests/ui/rust-2018/proc-macro-crate-in-paths.rs tests/ui/target-feature/missing-plusminus.rs From b959fc1d0ae090301fa204f37bec8891957243b3 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Sat, 17 Feb 2024 22:01:56 +0300 Subject: [PATCH 163/613] Improve wording of static_mut_ref Rename `static_mut_ref` lint to `static_mut_refs`. --- example/mini_core_hello_world.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 9827e299f2a31..add77880716c8 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -99,8 +99,8 @@ fn start( static mut NUM: u8 = 6 * 7; -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] static NUM_REF: &'static u8 = unsafe { &NUM }; macro_rules! assert { From 8ce7f62e58c8f3671bce09cbfd1216e8df405f2b Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Sat, 17 Feb 2024 22:01:56 +0300 Subject: [PATCH 164/613] Improve wording of static_mut_ref Rename `static_mut_ref` lint to `static_mut_refs`. --- example/mini_core_hello_world.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 2a7b1107ffcaa..8b0b9123ac7df 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -112,8 +112,8 @@ fn start( static mut NUM: u8 = 6 * 7; -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] static NUM_REF: &'static u8 = unsafe { &NUM }; unsafe fn zeroed() -> T { From 1f34c881e87969818cab379cd7ad9dd7d1bc2e3e Mon Sep 17 00:00:00 2001 From: tempdragon <645703113@qq.com> Date: Sun, 18 Feb 2024 14:36:39 +0800 Subject: [PATCH 165/613] feat(Cargo.toml): Set `rustc_private` to `true` to allow lsp parsing --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 5e657c7c53959..85ad69e00fdef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,3 +57,6 @@ debug = false [profile.release.build-override] opt-level = 0 debug = false + +[package.metadata.rust-analyzer] +rustc_private = true \ No newline at end of file From 4ec4209ff5e41a986836d18718da5ab510390cf2 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Sun, 18 Feb 2024 12:40:20 -0600 Subject: [PATCH 166/613] use `default` as output type source in simd_gather Signed-off-by: Andy Sadler --- src/intrinsic/simd.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 33d659f251fe1..8599403c914c3 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -697,18 +697,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( default: RValue<'gcc>, pointers: RValue<'gcc>, mask: RValue<'gcc>, - pointer_count: usize, bx: &mut Builder<'a, 'gcc, 'tcx>, in_len: u64, - underlying_ty: Ty<'tcx>, invert: bool, ) -> RValue<'gcc> { - let vector_type = if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } else { - vector_ty(bx, underlying_ty, in_len) - }; - let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); + let vector_type = default.get_type(); + let elem_type = vector_type.unqualified().dyncast_vector().expect("vector type").get_element_type(); let mut values = Vec::with_capacity(in_len as usize); for i in 0..in_len { @@ -737,12 +731,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let mask_type = bx.context.new_struct_type(None, "mask_type", &mask_types); let mask = bx.context.new_struct_constructor(None, mask_type.as_type(), None, &mask_values); - // FIXME(antoyo): We sometimes need to bitcast here, since usize/isize sometimes (but not - // always) get canonicalized to their corresponding integer type (i.e. uint64_t/int64_t on - // 64-bit platforms). This causes the shuffle_vector call below to panic, since the types - // of the two vectors aren't the same. This is a workaround for now. - let vector = bx.bitcast_if_needed(vector, default.get_type()); - if invert { bx.shuffle_vector(vector, default, mask) } else { @@ -865,10 +853,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( args[0].immediate(), args[1].immediate(), args[2].immediate(), - pointer_count, bx, in_len, - underlying_ty, false, )); } @@ -983,10 +969,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( args[0].immediate(), args[1].immediate(), args[2].immediate(), - pointer_count, bx, in_len, - underlying_ty, true, ); From b886be124d5bcbc242cb1f6f6a29c9fbaa577272 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 19 Feb 2024 12:33:08 +0100 Subject: [PATCH 167/613] Fix simd_select_bitmask on big-endian systems The mask input for simd_select_bitmask depends on the host byteorder in the same way as the mask output of simd_bitmask does. Fix the implementation to work on both big- and little-endian systems. --- src/intrinsics/simd.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index ebdc744bcd833..a5490bd091b81 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -853,7 +853,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; for lane in 0..lane_count { - let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64); + // The bit order of the mask depends on the byte endianness, LSB-first for + // little endian and MSB-first for big endian. + let mask_lane = match fx.tcx.sess.target.endian { + Endian::Big => lane_count - 1 - lane, + Endian::Little => lane, + }; + let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(mask_lane) as i64); let m_lane = fx.bcx.ins().band_imm(m_lane, 1); let a_lane = a.value_lane(fx, lane).load_scalar(fx); let b_lane = b.value_lane(fx, lane).load_scalar(fx); From bc1bca798f6ab91bb513ae010c5a99f91639b125 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 19 Feb 2024 13:58:04 +0100 Subject: [PATCH 168/613] Fix download hash check on big-endian systems Ensure the hash_file and hash_dir routines give identical results on big- and little-endian systems. The default hash routines for integer types are endian-dependent, so all such hash inputs need to be byte-swapped. This applies in particular to the file hashes used as input when computing directory hashes. In addition, the default hash routines for composite types use a length prefix, which it itself an integer type (usize). In order to be able to byte-swap that prefix, we have to re-implement those bits of the standard library ourselves. --- build_system/prepare.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/build_system/prepare.rs b/build_system/prepare.rs index c68968b4fde27..3677d0a7d3607 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -1,5 +1,6 @@ use std::ffi::OsStr; use std::fs; +use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; use std::process::Command; @@ -71,7 +72,11 @@ fn hash_file(file: &std::path::Path) -> u64 { let contents = std::fs::read(file).unwrap(); #[allow(deprecated)] let mut hasher = std::hash::SipHasher::new(); - std::hash::Hash::hash(&contents, &mut hasher); + // The following is equivalent to + // std::hash::Hash::hash(&contents, &mut hasher); + // but gives the same result independent of host byte order. + hasher.write_usize(contents.len().to_le()); + Hash::hash_slice(&contents, &mut hasher); std::hash::Hasher::finish(&hasher) } @@ -80,16 +85,26 @@ fn hash_dir(dir: &std::path::Path) -> u64 { for entry in std::fs::read_dir(dir).unwrap() { let entry = entry.unwrap(); if entry.file_type().unwrap().is_dir() { - sub_hashes - .insert(entry.file_name().to_str().unwrap().to_owned(), hash_dir(&entry.path())); + sub_hashes.insert( + entry.file_name().to_str().unwrap().to_owned(), + hash_dir(&entry.path()).to_le(), + ); } else { - sub_hashes - .insert(entry.file_name().to_str().unwrap().to_owned(), hash_file(&entry.path())); + sub_hashes.insert( + entry.file_name().to_str().unwrap().to_owned(), + hash_file(&entry.path()).to_le(), + ); } } #[allow(deprecated)] let mut hasher = std::hash::SipHasher::new(); - std::hash::Hash::hash(&sub_hashes, &mut hasher); + // The following is equivalent to + // std::hash::Hash::hash(&sub_hashes, &mut hasher); + // but gives the same result independent of host byte order. + hasher.write_usize(sub_hashes.len().to_le()); + for elt in sub_hashes { + elt.hash(&mut hasher); + } std::hash::Hasher::finish(&hasher) } From 6bbbf59951a6ef9f54f5f0e2849bba2ac53928a5 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 Feb 2024 10:23:05 -0500 Subject: [PATCH 169/613] Update to nightly-2024-02-20 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 1962c217258a4..cd278090924d1 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-11-17" +channel = "nightly-2024-02-20" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From c3d5b7fe3ba0c2b04fcd4a7d2ebdb1ab9e357b6e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 Feb 2024 10:35:56 -0500 Subject: [PATCH 170/613] Fix patches --- .../0022-core-Disable-not-compiling-tests.patch | 4 +--- .../0001-Disable-libstd-and-libtest-dylib.patch | 16 ---------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/patches/0022-core-Disable-not-compiling-tests.patch b/patches/0022-core-Disable-not-compiling-tests.patch index 4db56fa3bd2c7..a7d523f940826 100644 --- a/patches/0022-core-Disable-not-compiling-tests.patch +++ b/patches/0022-core-Disable-not-compiling-tests.patch @@ -39,6 +39,4 @@ index 42a26ae..5ac1042 100644 +#![cfg(test)] #![feature(alloc_layout_extra)] #![feature(array_chunks)] - #![feature(array_methods)] --- -2.21.0 (Apple Git-122) + #![feature(array_windows)] diff --git a/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch b/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch index 74d9c208a05ac..c220f53040f05 100644 --- a/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch +++ b/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch @@ -21,19 +21,3 @@ index 5b21355..cb0c49b 100644 [dependencies] alloc = { path = "../alloc", public = true } -diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml -index 91a1abd..a58c160 100644 ---- a/library/test/Cargo.toml -+++ b/library/test/Cargo.toml -@@ -4,7 +4,7 @@ version = "0.0.0" - edition = "2021" - - [lib] --crate-type = ["dylib", "rlib"] -+crate-type = ["rlib"] - - [dependencies] - getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } --- -2.42.0 - From 49db50eaa5f74d7ff260b040d7c8ac1cfd8d17d2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 Feb 2024 16:59:44 +0000 Subject: [PATCH 171/613] Rustup to rustc 1.78.0-nightly (3246e7951 2024-02-19) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 6328830897065..0982bd88cc8ed 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-02-12" +channel = "nightly-2024-02-20" components = ["rust-src", "rustc-dev", "llvm-tools"] From e7b7c98e1c9628570bed2915e683ab298c59a0d6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 20 Feb 2024 11:08:45 -0500 Subject: [PATCH 172/613] Fix tests --- build_system/src/prepare.rs | 17 +------- .../0002-rand-Disable-failing-test.patch | 32 --------------- tests/failing-lto-tests.txt | 16 +++++++- tests/failing-ui-tests.txt | 39 +++++++++++++++++++ tests/failing-ui-tests12.txt | 4 ++ 5 files changed, 59 insertions(+), 49 deletions(-) delete mode 100644 patches/crate_patches/0002-rand-Disable-failing-test.patch diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 1a3eb7d2e57b4..66f440f53553a 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -159,21 +159,6 @@ where let repo_path = Path::new(crate::BUILD_DIR).join(&clone_result.repo_name); run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?; run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?; - let filter = format!("-{}-", clone_result.repo_name); - walk_dir( - "patches/crate_patches", - |_| Ok(()), - |file_path| { - let patch = file_path.as_os_str().to_str().unwrap(); - if patch.contains(&filter) && patch.ends_with(".patch") { - run_command_with_output( - &[&"git", &"am", &file_path.canonicalize().unwrap()], - Some(&repo_path), - )?; - } - Ok(()) - }, - )?; if let Some(extra) = extra { extra(&repo_path)?; } @@ -238,7 +223,7 @@ pub fn run() -> Result<(), String> { let to_clone = &[ ( "https://github.com/rust-random/rand.git", - "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", + "1f4507a8e1cf8050e4ceef95eeda8f64645b6719", None, ), ( diff --git a/patches/crate_patches/0002-rand-Disable-failing-test.patch b/patches/crate_patches/0002-rand-Disable-failing-test.patch deleted file mode 100644 index 449ca5f6e29cd..0000000000000 --- a/patches/crate_patches/0002-rand-Disable-failing-test.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Sat, 15 Aug 2020 20:04:38 +0200 -Subject: [PATCH] [rand] Disable failing test - ---- - src/distributions/uniform.rs | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs -index 480b859..c80bb6f 100644 ---- a/src/distributions/uniform.rs -+++ b/src/distributions/uniform.rs -@@ -1085,7 +1085,7 @@ mod tests { - _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly") - } - } -- -+ - #[test] - #[cfg(feature = "serde1")] - fn test_uniform_serialization() { -@@ -1314,6 +1314,7 @@ mod tests { - not(target_arch = "wasm32"), - not(target_arch = "asmjs") - ))] -+ #[ignore] // FIXME - fn test_float_assertions() { - use super::SampleUniform; - use std::panic::catch_unwind; --- -2.20.1 diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index 2e0b6134070b9..8de45ae0f28b1 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -1,6 +1,6 @@ tests/ui/lint/unsafe_code/forge_unsafe_block.rs tests/ui/lint/unused-qualification-in-derive-expansion.rs -tests/ui/macro-quote-test.rs +tests/ui/macros/macro-quote-test.rs tests/ui/macros/proc_macro.rs tests/ui/panic-runtime/lto-unwind.rs tests/ui/resolve/derive-macro-1.rs @@ -21,3 +21,17 @@ tests/ui/fmt/format-args-capture-issue-106408.rs tests/ui/fmt/indoc-issue-106408.rs tests/ui/hygiene/issue-77523-def-site-async-await.rs tests/ui/inherent-impls-overlap-check/no-overlap.rs +tests/ui/annotate-snippet/multispan.rs +tests/ui/enum-discriminant/issue-46519.rs +tests/ui/issues/issue-45731.rs +tests/ui/lint/test-allow-dead-extern-static-no-warning.rs +tests/ui/macros/macro-comma-behavior-rpass.rs +tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs +tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs +tests/ui/macros/stringify.rs +tests/ui/panics/test-panic.rs +tests/ui/panics/test-should-fail-bad-message.rs +tests/ui/panics/test-should-panic-bad-message.rs +tests/ui/panics/test-should-panic-no-message.rs +tests/ui/reexport-test-harness-main.rs +tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 6e020e9b354da..e504021bf2ad2 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -69,3 +69,42 @@ tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/closures/capture-unsized-by-ref.rs tests/ui/coroutine/resume-after-return.rs tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs +tests/ui/limits/issue-17913.rs +tests/ui/limits/issue-55878.rs +tests/ui/linkage-attr/common-linkage-non-zero-init.rs +tests/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs +tests/ui/numbers-arithmetic/divide-by-zero.rs +tests/ui/numbers-arithmetic/mod-zero.rs +tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs +tests/ui/numbers-arithmetic/overflowing-neg.rs +tests/ui/optimization-remark.rs +tests/ui/panic-handler/panic-handler-std.rs +tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs +tests/ui/panic-runtime/need-unwind-got-abort.rs +tests/ui/panics/issue-47429-short-backtraces.rs +tests/ui/panics/panic-in-cleanup.rs +tests/ui/panics/panic-in-ffi.rs +tests/ui/panics/runtime-switch.rs +tests/ui/panics/short-ice-remove-middle-frames-2.rs +tests/ui/panics/short-ice-remove-middle-frames.rs +tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs +tests/ui/simd/masked-load-store.rs +tests/ui/simd/repr_packed.rs +tests/ui/type_length_limit.rs +tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs +tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs +tests/ui/c-variadic/issue-86053-1.rs +tests/ui/const-ptr/out_of_bounds_read.rs +tests/ui/consts/const_unsafe_unreachable_ub.rs +tests/ui/consts/miri_unleashed/drop.rs +tests/ui/consts/timeout.rs +tests/ui/consts/try-operator.rs +tests/ui/coroutine/coroutine-resume-after-panic.rs +tests/ui/coroutine/unwind-abort-mix.rs +tests/ui/duplicate/dupe-symbols-7.rs +tests/ui/duplicate/dupe-symbols-8.rs +tests/ui/hygiene/panic-location.rs +tests/ui/invalid/issue-114435-layout-type-err.rs +tests/ui/invalid-compile-flags/invalid-llvm-passes.rs +tests/ui/lto/issue-105637.rs +tests/ui/lto/lto-duplicate-symbols.rs diff --git a/tests/failing-ui-tests12.txt b/tests/failing-ui-tests12.txt index 64f89b03eecc8..1d9bdaa552c6b 100644 --- a/tests/failing-ui-tests12.txt +++ b/tests/failing-ui-tests12.txt @@ -42,3 +42,7 @@ tests/ui/codegen/issue-79865-llvm-miscompile.rs tests/ui/std-backtrace.rs tests/ui/mir/alignment/packed.rs tests/ui/intrinsics/intrinsics-integer.rs +tests/ui/asm/x86_64/evex512-implicit-feature.rs +tests/ui/packed/dyn-trait.rs +tests/ui/packed/issue-118537-field-offset-ice.rs +tests/ui/stable-mir-print/basic_function.rs From 6ff147b2050bc99f2bca7707e29052e7e4737912 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 6 Feb 2024 14:32:00 -0500 Subject: [PATCH 173/613] Add "algebraic" versions of the fast-math intrinsics --- src/builder.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 42e61b3ccb5ad..5f1e45383765f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -705,6 +705,31 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.frem(lhs, rhs) } + fn fadd_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. + lhs + rhs + } + + fn fsub_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. + lhs - rhs + } + + fn fmul_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. + lhs * rhs + } + + fn fdiv_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. + lhs / rhs + } + + fn frem_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { + // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. + self.frem(lhs, rhs) + } + fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) { self.gcc_checked_binop(oop, typ, lhs, rhs) } From 968e79540da9d3a29cf8e57390b4775fd0bd0616 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 6 Feb 2024 14:32:00 -0500 Subject: [PATCH 174/613] Add "algebraic" versions of the fast-math intrinsics --- src/intrinsics/mod.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 476752c7230a7..199d5df29e7d0 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1152,17 +1152,26 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, ret_val); } - sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { + sym::fadd_fast + | sym::fsub_fast + | sym::fmul_fast + | sym::fdiv_fast + | sym::frem_fast + | sym::fadd_algebraic + | sym::fsub_algebraic + | sym::fmul_algebraic + | sym::fdiv_algebraic + | sym::frem_algebraic => { intrinsic_args!(fx, args => (x, y); intrinsic); let res = crate::num::codegen_float_binop( fx, match intrinsic { - sym::fadd_fast => BinOp::Add, - sym::fsub_fast => BinOp::Sub, - sym::fmul_fast => BinOp::Mul, - sym::fdiv_fast => BinOp::Div, - sym::frem_fast => BinOp::Rem, + sym::fadd_fast | sym::fadd_algebraic => BinOp::Add, + sym::fsub_fast | sym::fsub_algebraic => BinOp::Sub, + sym::fmul_fast | sym::fmul_algebraic => BinOp::Mul, + sym::fdiv_fast | sym::fdiv_algebraic => BinOp::Div, + sym::frem_fast | sym::frem_algebraic => BinOp::Rem, _ => unreachable!(), }, x, From c7a50c26367f3d1d614d5ae647f9c86919c8f422 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 Feb 2024 17:44:00 +0000 Subject: [PATCH 175/613] Adapt filtering of rustc tests for upstream changes --- scripts/test_rustc_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index eab04ca90b5af..54352c64e8e01 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -15,7 +15,7 @@ for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental} rm $test done -for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do +for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|//@ error-pattern:|//@ build-fail|//@ run-fail|-Cllvm-args" tests/ui); do rm $test done From b03b41420b2dc900a9db019f4b5a5c22c05d2bb8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:16:33 +0000 Subject: [PATCH 176/613] Fix stack alignment problem on s390x --- .../0023-coretests-Ignore-failing-tests.patch | 26 ------------------- src/common.rs | 17 ++++++++---- 2 files changed, 12 insertions(+), 31 deletions(-) delete mode 100644 patches/0023-coretests-Ignore-failing-tests.patch diff --git a/patches/0023-coretests-Ignore-failing-tests.patch b/patches/0023-coretests-Ignore-failing-tests.patch deleted file mode 100644 index 385f5a8a2e039..0000000000000 --- a/patches/0023-coretests-Ignore-failing-tests.patch +++ /dev/null @@ -1,26 +0,0 @@ -From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Sun, 24 Nov 2019 15:34:06 +0100 -Subject: [PATCH] [core] Ignore failing tests - ---- - library/core/tests/iter.rs | 4 ++++ - library/core/tests/num/bignum.rs | 10 ++++++++++ - library/core/tests/num/mod.rs | 5 +++-- - library/core/tests/time.rs | 1 + - 4 files changed, 18 insertions(+), 2 deletions(-) - -diff --git a/atomic.rs b/atomic.rs -index 13b12db..96fe4b9 100644 ---- a/atomic.rs -+++ b/atomic.rs -@@ -185,6 +185,7 @@ fn ptr_bitops() { - } - - #[test] -+#[cfg_attr(target_arch = "s390x", ignore)] // s390x backend doesn't support stack alignment >8 bytes - #[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins - fn ptr_bitops_tagging() { - #[repr(align(16))] --- -2.21.0 (Apple Git-122) diff --git a/src/common.rs b/src/common.rs index 1e37825b54896..323f2bca5a82e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -388,18 +388,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { - if align <= 16 { + let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 }; + if align <= abi_align { let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (size + 15) / 16 * 16, + // FIXME Don't force the size to a multiple of bytes once Cranelift gets + // a way to specify stack slot alignment. + size: (size + abi_align - 1) / abi_align * abi_align, }); Pointer::stack_slot(stack_slot) } else { // Alignment is too big to handle using the above hack. Dynamically realign a stack slot // instead. This wastes some space for the realignment. - let base_ptr = self.create_stack_slot(size + align, 16).get_addr(self); + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME Don't force the size to a multiple of bytes once Cranelift gets + // a way to specify stack slot alignment. + size: (size + align) / abi_align * abi_align, + }); + let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) From c5aa659832334dca7cc9b27074bdc686b9650c12 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Tue, 20 Feb 2024 18:59:56 +0000 Subject: [PATCH 177/613] Reduce alignment of TypeId to u64 alignment --- library/core/src/any.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index e8f00e8760e13..7efbabb725748 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -605,7 +605,8 @@ impl dyn Any + Send + Sync { #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct TypeId { - t: u128, + // See #115620 for this representation. + t: (u64, u64), } #[stable(feature = "rust1", since = "1.0.0")] @@ -637,7 +638,10 @@ impl TypeId { #[rustc_const_unstable(feature = "const_type_id", issue = "77125")] pub const fn of() -> TypeId { let t: u128 = intrinsics::type_id::(); - TypeId { t } + + let t1 = (t >> 64) as u64; + let t2 = t as u64; + TypeId { t: (t1, t2) } } } @@ -657,7 +661,7 @@ impl hash::Hash for TypeId { // - It is correct to do so -- only hashing a subset of `self` is still // with an `Eq` implementation that considers the entire value, as // ours does. - (self.t as u64).hash(state); + self.t.0.hash(state); } } From aa25c481b77cb9e0ec25c6350d7ded110fae7f0e Mon Sep 17 00:00:00 2001 From: Gnome! Date: Tue, 20 Feb 2024 19:12:42 +0000 Subject: [PATCH 178/613] Add extra detail to field comment Co-authored-by: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> --- library/core/src/any.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 7efbabb725748..adc45038148e8 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -605,7 +605,8 @@ impl dyn Any + Send + Sync { #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct TypeId { - // See #115620 for this representation. + // We avoid using `u128` because that imposes higher alignment requirements on many platforms. + // See issue #115620 for more information. t: (u64, u64), } From d23026ac1b8c01e2e945afb684b0217587b4638d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 Feb 2024 20:52:27 +0000 Subject: [PATCH 179/613] Update to Cranelift 0.105 --- Cargo.lock | 52 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 12 ++++++------ 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b70a1234af398..9b0010a6a4364 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0" +checksum = "77ec790dbba3970f5dc1fb615e81167adbe90a81b6d5ce53d1d7f97d1da0c816" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c" +checksum = "aff1e6625920ec73a0a222bf8f9e5b7fc6a765ccef47e0a010fe327f07eb430a" dependencies = [ "bumpalo", "cranelift-bforest", @@ -76,39 +76,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb" +checksum = "0e1b92f1d526daa2b1878f0171d3a216a70e3f05d2fe6786a5469299c6919a0a" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36" +checksum = "3333fb7671c8b6a8d24fd05dced0a4940773d9cdddeeb38b1f99260eba2c50e9" [[package]] name = "cranelift-control" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b" +checksum = "cf07b47de593bc43b7bc25a66c509469fd02c2ad850833c6a2dff45e81980c3b" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d" +checksum = "dfd988176a86d6985dd75ac0762033b36d134c4af8b806b605e8542c489fe1c2" [[package]] name = "cranelift-frontend" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd" +checksum = "214f216d2288f695bf0e0c2775d4e58759cd6ad5a118852fb5cc26d817e3cdcc" dependencies = [ "cranelift-codegen", "log", @@ -118,15 +118,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96" +checksum = "aaf4dd3bc4bd4d594180a4db16b0b411a9c3a6757a4d13c5ede1177a0131fc80" [[package]] name = "cranelift-jit" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f61e236d7622c3c43016e8b0f3ba27136e21ac7de328c7fda902e61db1de851" +checksum = "52bb8f1189dd81ed989b2cbd62371d67d35afb8977239d4a917a05b7e22e0692" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30c6820342015c5009070e3e48d1da7b13521399de904663f1c84f5ee839657" +checksum = "9ecedd1fec01db9760f94dc2abca90975ef5e90746be5aa0041dbba99268ac23" dependencies = [ "anyhow", "cranelift-codegen", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b" +checksum = "0ddcb8ffe184e9aaf941387f9bcd016236fe1bedc29a84af0771d98443a71aea" dependencies = [ "cranelift-codegen", "libc", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.104.0" +version = "0.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24425a329b4343177d5f1852243841dcec17f929d72c0e7f41262140155e55e7" +checksum = "ad11c4abd71e9e837794e9967e54ca5ecdd344459160602b5e4f090d0a258e7b" dependencies = [ "anyhow", "cranelift-codegen", @@ -410,9 +410,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "17.0.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da" +checksum = "2c87783a70d3b7602834118f42e73ed8979f1b75a01e0fc4bf311cc6dc31f8fc" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index 586ce2286f971..c9d9046ce0912 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.104", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.104" } -cranelift-module = { version = "0.104" } -cranelift-native = { version = "0.104" } -cranelift-jit = { version = "0.104", optional = true } -cranelift-object = { version = "0.104" } +cranelift-codegen = { version = "0.105", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.105" } +cranelift-module = { version = "0.105" } +cranelift-native = { version = "0.105" } +cranelift-jit = { version = "0.105", optional = true } +cranelift-object = { version = "0.105" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } From 8fb0fbef627b4ee1361f6bfecb5ee1f8e2afe402 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 Feb 2024 18:15:13 +0000 Subject: [PATCH 180/613] Fix rustc test suite --- scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 54352c64e8e01..203c5204325c3 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -44,6 +44,7 @@ rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs # vendor intrinsics rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant" +rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic # exotic linkages rm tests/ui/issues/issue-33992.rs # unsupported linkages From dba167592ee67748d2f24c8f646cbe193c95da14 Mon Sep 17 00:00:00 2001 From: Young-Flash <871946895@qq.com> Date: Thu, 16 Nov 2023 17:22:53 +0800 Subject: [PATCH 181/613] feat: add hover display for trait assoc items --- crates/hir/src/display.rs | 24 ++++++++ crates/ide/src/hover/tests.rs | 113 +++++++++++++++++++++++++++++++--- 2 files changed, 127 insertions(+), 10 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 30f402a79f3db..d76eb873bf4ef 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -595,6 +595,30 @@ impl HirDisplay for Trait { let def_id = GenericDefId::TraitId(self.id); write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + + let assoc_items = self.items(f.db); + if assoc_items.is_empty() { + f.write_str(" {}")?; + } else { + f.write_str(" {\n")?; + for item in assoc_items { + f.write_str(" ")?; + match item { + AssocItem::Function(func) => { + func.hir_fmt(f)?; + } + AssocItem::Const(cst) => { + cst.hir_fmt(f)?; + } + AssocItem::TypeAlias(type_alias) => { + type_alias.hir_fmt(f)?; + } + }; + f.write_str(",\n")?; + } + f.write_str("}")?; + } + Ok(()) } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ead4f91595f0e..73d9339a229e7 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -2685,7 +2685,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2719,7 +2719,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -2886,7 +2886,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2988,7 +2988,7 @@ pub mod future { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future", + description: "pub trait Future {}", }, }, HoverGotoTypeData { @@ -3033,7 +3033,7 @@ fn foo(ar$0g: &impl Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3096,7 +3096,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -3127,7 +3127,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -3159,7 +3159,7 @@ fn foo(ar$0g: &dyn Foo) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3288,7 +3288,7 @@ fn main() { let s$0t = test().get(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {\n type Item,\n fn get(self) -> Self::Item,\n}", }, }, ], @@ -3353,7 +3353,7 @@ fn foo(t: T$0){} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -6252,6 +6252,99 @@ impl T for () { ); } +#[test] +fn hover_trait_show_assoc_items() { + check( + r#" +trait T {} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T {} + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + } + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + const FLAG: i32, + } + ``` + "#]], + ); + + check( + r#" +trait T { + fn func() {} + const FLAG: i32 = 34; + type Bar; +} +impl T$0 for () {} +"#, + expect![[r#" + *T* + + ```rust + test + ``` + + ```rust + trait T { + fn func(), + const FLAG: i32, + type Bar, + } + ``` + "#]], + ); +} + #[test] fn hover_ranged_macro_call() { check_hover_range( From 00358b1fe078bc4d702375203f79b088d2b9a5f6 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 18 Feb 2024 15:29:45 +0800 Subject: [PATCH 182/613] rebase on lastest master --- crates/hir/src/display.rs | 5 +---- crates/ide/src/hover/tests.rs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index d76eb873bf4ef..010c3537574cc 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -17,10 +17,7 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, - Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, - Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, - TypeParam, Union, Variant, + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant }; impl HirDisplay for Function { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 73d9339a229e7..e845ef668948f 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -411,7 +411,7 @@ fn main() { name: "FnOnce", kind: Trait, container_name: "function", - description: "pub trait FnOnce\nwhere\n Args: Tuple,", + description: "pub trait FnOnce\nwhere\n Args: Tuple, {\n pub type Output,\n pub extern \"rust-call\" fn call_once(self, args: Args) -> Self::Output,\n}", }, }, ], @@ -2766,7 +2766,7 @@ fn main() { let s$0t = foo(); } focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2779,7 +2779,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, ], @@ -2816,7 +2816,7 @@ fn main() { let s$0t = foo(); } focus_range: 22..25, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2829,7 +2829,7 @@ fn main() { let s$0t = foo(); } focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -2920,7 +2920,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 19..22, name: "Bar", kind: Trait, - description: "trait Bar", + description: "trait Bar {}", }, }, HoverGotoTypeData { @@ -2933,7 +2933,7 @@ fn foo(ar$0g: &impl Foo + Bar) {} focus_range: 6..9, name: "Foo", kind: Trait, - description: "trait Foo", + description: "trait Foo {}", }, }, HoverGotoTypeData { @@ -3220,7 +3220,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 28..36, name: "DynTrait", kind: Trait, - description: "trait DynTrait", + description: "trait DynTrait {}", }, }, HoverGotoTypeData { @@ -3233,7 +3233,7 @@ fn foo(a$0rg: &impl ImplTrait>>>) {} focus_range: 6..15, name: "ImplTrait", kind: Trait, - description: "trait ImplTrait", + description: "trait ImplTrait {}", }, }, HoverGotoTypeData { @@ -7456,7 +7456,7 @@ impl Iterator for S { name: "Future", kind: Trait, container_name: "future", - description: "pub trait Future", + description: "pub trait Future {\n pub type Output,\n pub fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll,\n}", }, }, HoverGotoTypeData { @@ -7470,7 +7470,7 @@ impl Iterator for S { name: "Iterator", kind: Trait, container_name: "iterator", - description: "pub trait Iterator", + description: "pub trait Iterator {\n pub type Item,\n pub fn next(&mut self) -> Option,\n pub fn nth(&mut self, n: usize) -> Option,\n pub fn by_ref(&mut self) -> &mut Self\nwhere\n Self: Sized,,\n}", }, }, HoverGotoTypeData { @@ -7483,7 +7483,7 @@ impl Iterator for S { focus_range: 49..56, name: "Notable", kind: Trait, - description: "trait Notable", + description: "trait Notable {}", }, }, HoverGotoTypeData { From 35ec5955eb607c17d72621fab8cf59242d6bac84 Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Sun, 18 Feb 2024 17:43:22 +0800 Subject: [PATCH 183/613] add config item for hover display --- crates/hir-ty/src/display.rs | 2 +- crates/hir/src/display.rs | 9 ++++++++- crates/ide-db/src/defs.rs | 4 ++-- crates/ide/src/hover.rs | 1 + crates/ide/src/hover/render.rs | 2 +- crates/ide/src/hover/tests.rs | 1 + crates/ide/src/static_index.rs | 3 ++- crates/rust-analyzer/src/config.rs | 5 ++++- docs/user/generated_config.adoc | 5 +++++ editors/code/package.json | 9 +++++++++ 10 files changed, 34 insertions(+), 7 deletions(-) diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index fe51ec3f82108..f7e396de2d6b7 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -62,7 +62,7 @@ pub struct HirFormatter<'a> { fmt: &'a mut dyn HirWrite, buf: String, curr_size: usize, - pub(crate) max_size: Option, + pub max_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, display_target: DisplayTarget, diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 010c3537574cc..0e221a2149ae2 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -593,12 +593,14 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; + let mut display_size = 0; + let max_display_size = f.max_size.unwrap_or(7); let assoc_items = self.items(f.db); if assoc_items.is_empty() { f.write_str(" {}")?; } else { f.write_str(" {\n")?; - for item in assoc_items { + for (index, item) in assoc_items.iter().enumerate() { f.write_str(" ")?; match item { AssocItem::Function(func) => { @@ -612,6 +614,11 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; + display_size += 1; + if display_size == max_display_size && index != assoc_items.len() - 1{ + f.write_str(" ...\n")?; + break; + } } f.write_str("}")?; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 1b6ff8bad53c5..8de885f49948b 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -213,7 +213,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase) -> String { + pub fn label(&self, db: &RootDatabase, max_size: Option) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -224,7 +224,7 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => it.display(db).to_string(), + Definition::Trait(it) => it.display_truncated(db, max_size).to_string(), Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 4a7350feb385e..4b3fdaff0b346 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,6 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, + pub trait_item_display_on_hover: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 563e78253a8ae..c955f46bc454a 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -406,7 +406,7 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let label = def.label(db); + let label = def.label(db, config.trait_item_display_on_hover); let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index e845ef668948f..2df4ca5810b24 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,6 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, + trait_item_display_on_hover: Some(7), }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 2929a7522e591..8d5f5e1bf6777 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -166,6 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, + trait_item_display_on_hover: Some(7) }; let tokens = tokens.filter(|token| { matches!( @@ -196,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db)), + signature: Some(def.label(self.db, hover_config.trait_item_display_on_hover)), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 16e1a2f544907..230a0385cdb3b 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -511,7 +511,6 @@ config_data! { /// Exclude tests from find-all-references. references_excludeTests: bool = "false", - /// Command to be executed instead of 'cargo' for runnables. runnables_command: Option = "null", /// Additional arguments to be passed to cargo for runnables such as @@ -591,6 +590,9 @@ config_data! { /// Show documentation. signatureInfo_documentation_enable: bool = "true", + /// How many trait item display on hover. + trait_item_display_on_hover: Option = "7", + /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1683,6 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, + trait_item_display_on_hover: self.data.trait_item_display_on_hover, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index da7654b0f6447..9f3ab4513294e 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -927,6 +927,11 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- +[[rust-analyzer.trait.item.display.on.hover]]rust-analyzer.trait.item.display.on.hover (default: `7`):: ++ +-- +How many trait item display on hover. +-- [[rust-analyzer.typing.autoClosingAngleBrackets.enable]]rust-analyzer.typing.autoClosingAngleBrackets.enable (default: `false`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 3a1df5a2f901c..a4f54ae4f4587 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1648,6 +1648,15 @@ "default": true, "type": "boolean" }, + "rust-analyzer.trait.item.display.on.hover": { + "markdownDescription": "How many trait item display on hover.", + "default": 7, + "type": [ + "null", + "integer" + ], + "minimum": 0 + }, "rust-analyzer.typing.autoClosingAngleBrackets.enable": { "markdownDescription": "Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list.", "default": false, From b87de7325f60af4072f85ecb22b5b4582e51742b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Feb 2024 13:30:04 +0100 Subject: [PATCH 184/613] Correctly handle "master" feature --- build_system/src/build.rs | 14 +++++++--- build_system/src/config.rs | 10 +++++-- build_system/src/test.rs | 56 ++++++++++++++++++++------------------ 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 308ad34654941..7ec8b8de62a3d 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -19,9 +19,6 @@ impl BuildArg { while let Some(arg) = args.next() { match arg.as_str() { - "--no-default-features" => { - build_arg.flags.push("--no-default-features".to_string()); - } "--features" => { if let Some(arg) = args.next() { build_arg.flags.push("--features".to_string()); @@ -51,7 +48,6 @@ impl BuildArg { r#" `build` command help: - --no-default-features : Add `--no-default-features` flag --features [arg] : Add a new feature [arg]"# ); ConfigInfo::show_usage(); @@ -111,6 +107,9 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } rustflags.push_str(" -Z force-unstable-if-unmarked"); + if config.no_default_features { + rustflags.push_str(" -Csymbol-mangling-version=v0"); + } let mut env = env.clone(); let channel = if config.sysroot_release_channel { env.insert( @@ -193,6 +192,13 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { args.config_info.gcc_path.clone(), ); + if args.config_info.no_default_features { + env.insert( + "RUSTFLAGS".to_string(), + "-Csymbol-mangling-version=v0".to_string(), + ); + } + let mut command: Vec<&dyn AsRef> = vec![&"cargo", &"rustc"]; if args.config_info.channel == Channel::Release { command.push(&"--release"); diff --git a/build_system/src/config.rs b/build_system/src/config.rs index ddfc0e4a925da..f6f039370180c 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -127,6 +127,7 @@ pub struct ConfigInfo { // Needed for the `info` command which doesn't want to actually download the lib if needed, // just to set the `gcc_path` field to display it. pub no_download: bool, + pub no_default_features: bool, } impl ConfigInfo { @@ -177,6 +178,7 @@ impl ConfigInfo { return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string()) } }, + "--no-default-features" => self.no_default_features = true, _ => return Ok(false), } Ok(true) @@ -416,8 +418,9 @@ impl ConfigInfo { rustflags.push(linker.to_string()); } - #[cfg(not(feature="master"))] - rustflags.push("-Csymbol-mangling-version=v0".to_string()); + if self.no_default_features { + rustflags.push("-Csymbol-mangling-version=v0".to_string()); + } rustflags.extend_from_slice(&[ "-Cdebuginfo=2".to_string(), @@ -495,7 +498,8 @@ impl ConfigInfo { --sysroot-panic-abort : Build the sysroot without unwinding support --config-file : Location of the config file to be used --cg_gcc-path : Location of the rustc_codegen_gcc root folder (used - when ran from another directory)" + when ran from another directory) + --no-default-features : Add `--no-default-features` flag to cargo commands" ); } } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index ab65fed0f75a4..17b1868502aa6 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -90,7 +90,6 @@ fn show_usage() { --release : Build codegen in release mode --sysroot-panic-abort : Build the sysroot without unwinding support. - --no-default-features : Add `--no-default-features` flag --features [arg] : Add a new feature [arg] --use-system-gcc : Use system installed libgccjit --build-only : Only build rustc_codegen_gcc then exits @@ -110,7 +109,6 @@ fn show_usage() { #[derive(Default, Debug)] struct TestArg { - no_default_features: bool, build_only: bool, use_system_gcc: bool, runners: BTreeSet, @@ -132,13 +130,6 @@ impl TestArg { while let Some(arg) = args.next() { match arg.as_str() { - "--no-default-features" => { - // To prevent adding it more than once. - if !test_arg.no_default_features { - test_arg.flags.push("--no-default-features".into()); - } - test_arg.no_default_features = true; - } "--features" => match args.next() { Some(feature) if !feature.is_empty() => { test_arg @@ -196,11 +187,14 @@ impl TestArg { ); } } + if test_arg.config_info.no_default_features { + test_arg.flags.push("--no-default-features".into()); + } Ok(Some(test_arg)) } pub fn is_using_gcc_master_branch(&self) -> bool { - !self.no_default_features + !self.config_info.no_default_features } } @@ -612,20 +606,23 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); - let rustc_args = - &format!( - r#"-Zpanic-abort-tests \ - -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ - --sysroot "{pwd}/build_sysroot/sysroot" -Cpanic=abort"#, - pwd = std::env::current_dir() - .map_err(|error| format!("`current_dir` failed: {:?}", error))? - .display(), - channel = args.config_info.channel.as_str(), - dylib_ext = args.config_info.dylib_ext, - ); + let extra = if args.is_using_gcc_master_branch() { + "" + } else { + " -Csymbol-mangling-version=v0" + }; - #[cfg(not(feature="master"))] - let rustc_args = format!("{} -Csymbol-mangling-version=v0", rustc_args); + let rustc_args = &format!( + r#"-Zpanic-abort-tests \ + -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ + --sysroot "{pwd}/build_sysroot/sysroot" -Cpanic=abort{extra}"#, + pwd = std::env::current_dir() + .map_err(|error| format!("`current_dir` failed: {:?}", error))? + .display(), + channel = args.config_info.channel.as_str(), + dylib_ext = args.config_info.dylib_ext, + extra = extra, + ); run_command_with_env( &[ @@ -1069,16 +1066,21 @@ where // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] rustc test suite"); env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); + + let extra = if args.is_using_gcc_master_branch() { + "" + } else { + " -Csymbol-mangling-version=v0" + }; + let rustc_args = format!( - "{} -Zcodegen-backend={} --sysroot {}", + "{} -Zcodegen-backend={} --sysroot {}{}", env.get("TEST_FLAGS").unwrap_or(&String::new()), args.config_info.cg_backend_path, args.config_info.sysroot_path, + extra, ); - #[cfg(not(feature="master"))] - let rustc_args = format!("{} -Csymbol-mangling-version=v0", rustc_args); - env.get_mut("RUSTFLAGS").unwrap().clear(); run_command_with_output_and_env( &[ From d2210d497670be3fcf342277e3d95882bd9c2700 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Feb 2024 14:42:24 +0100 Subject: [PATCH 185/613] Correctly pass `--no-default-features` when argument is passed --- build_system/src/build.rs | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 7ec8b8de62a3d..e32971ca0c73a 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -107,38 +107,26 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } rustflags.push_str(" -Z force-unstable-if-unmarked"); + let mut env = env.clone(); + + let mut args: Vec<&dyn AsRef> = vec![&"cargo", &"build", &"--target", &config.target]; + if config.no_default_features { rustflags.push_str(" -Csymbol-mangling-version=v0"); + args.push(&"--no-default-features"); } - let mut env = env.clone(); + let channel = if config.sysroot_release_channel { - env.insert( - "RUSTFLAGS".to_string(), - format!("{} -Zmir-opt-level=3", rustflags), - ); - run_command_with_output_and_env( - &[ - &"cargo", - &"build", - &"--release", - &"--target", - &config.target, - ], - Some(start_dir), - Some(&env), - )?; + rustflags.push_str(" -Zmir-opt-level=3"); + args.push(&"--release"); "release" } else { - env.insert("RUSTFLAGS".to_string(), rustflags); - - run_command_with_output_and_env( - &[&"cargo", &"build", &"--target", &config.target], - Some(start_dir), - Some(&env), - )?; "debug" }; + env.insert("RUSTFLAGS".to_string(), rustflags); + run_command_with_output_and_env(&args, Some(start_dir), Some(&env))?; + // Copy files to sysroot let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple)); fs::create_dir_all(&sysroot_path).map_err(|error| { From 114c25feeb021fc3462056df2a06f715512e89e6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Feb 2024 14:58:04 +0100 Subject: [PATCH 186/613] Pass `--no-default-features` to codegen as well --- build_system/src/build.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index e32971ca0c73a..0eabd1d897292 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -195,6 +195,9 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } else { env.insert("CHANNEL".to_string(), "debug".to_string()); } + if args.config_info.no_default_features { + command.push(&"--no-default-features"); + } let flags = args.flags.iter().map(|s| s.as_str()).collect::>(); for flag in &flags { command.push(flag); From a9b5c0832fc3e7e12916ef827f9de27d968a491a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 18 Feb 2024 23:10:34 +0100 Subject: [PATCH 187/613] make simd_reduce_{mul,add}_unordered use only the 'reassoc' flag, not all fast-math flags --- src/builder.rs | 4 ++-- src/intrinsic/simd.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 5f1e45383765f..7e2139866f49e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1752,7 +1752,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.vector_reduce(src, |a, b, context| context.new_binary_op(None, op, a.get_type(), a, b)) } - pub fn vector_reduce_fadd_fast(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> { + pub fn vector_reduce_fadd_reassoc(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> { unimplemented!(); } @@ -1772,7 +1772,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { unimplemented!(); } - pub fn vector_reduce_fmul_fast(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> { + pub fn vector_reduce_fmul_reassoc(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> { unimplemented!(); } diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 9fa978cd2ef7a..dedd46538589d 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -989,14 +989,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( arith_red!( simd_reduce_add_unordered: BinaryOp::Plus, - vector_reduce_fadd_fast, + vector_reduce_fadd_reassoc, false, add, 0.0 // TODO: Use this argument. ); arith_red!( simd_reduce_mul_unordered: BinaryOp::Mult, - vector_reduce_fmul_fast, + vector_reduce_fmul_reassoc, false, mul, 1.0 From e49cd1c578227e450f0a703b08fa429e3931c228 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 21 Feb 2024 15:56:50 +0000 Subject: [PATCH 188/613] TryReserveError to ErrorKind::OutOfMemory --- library/std/src/io/error.rs | 12 ++++++++++++ library/std/src/io/tests.rs | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 13cc0511e103e..7ae15e0fd017e 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -83,6 +83,18 @@ impl From for Error { } } +#[stable(feature = "io_error_from_try_reserve", since = "CURRENT_RUSTC_VERSION")] +impl From for Error { + /// Converts `TryReserveError` to an error with [`ErrorKind::OutOfMemory`]. + /// + /// `TryReserveError` won't be available as the error `source()`, + /// but this may change in the future. + fn from(_: alloc::collections::TryReserveError) -> Error { + // ErrorData::Custom allocates, which isn't great for handling OOM errors. + ErrorKind::OutOfMemory.into() + } +} + // Only derive debug in tests, to make sure it // doesn't accidentally get printed. #[cfg_attr(test, derive(Debug))] diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 5396f7f6e216c..c306de3039fc3 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -692,3 +692,13 @@ fn read_buf_full_read() { assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE); } + +#[test] +// 64-bit only to be sure the allocator will fail fast on an impossible to satsify size +#[cfg(target_pointer_width = "64")] +fn try_oom_error() { + let mut v = Vec::::new(); + let reserve_err = v.try_reserve(isize::MAX as usize - 1).unwrap_err(); + let io_err = io::Error::from(reserve_err); + assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind()); +} From aa581f0a0a3fbb61efe1f37786c237b2733dfbfa Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 21 Feb 2024 15:59:41 +0000 Subject: [PATCH 189/613] Remove unnecessary map_err --- library/std/src/fs.rs | 8 ++++---- library/std/src/io/buffered/bufreader.rs | 2 +- library/std/src/io/impls.rs | 4 ++-- library/std/src/io/mod.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 6b1dd1b5af4c9..fee529993715b 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -261,7 +261,7 @@ pub fn read>(path: P) -> io::Result> { let mut file = File::open(path)?; let size = file.metadata().map(|m| m.len() as usize).ok(); let mut bytes = Vec::new(); - bytes.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + bytes.try_reserve_exact(size.unwrap_or(0))?; io::default_read_to_end(&mut file, &mut bytes, size)?; Ok(bytes) } @@ -304,7 +304,7 @@ pub fn read_to_string>(path: P) -> io::Result { let mut file = File::open(path)?; let size = file.metadata().map(|m| m.len() as usize).ok(); let mut string = String::new(); - string.try_reserve_exact(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + string.try_reserve_exact(size.unwrap_or(0))?; io::default_read_to_string(&mut file, &mut string, size)?; Ok(string) } @@ -777,14 +777,14 @@ impl Read for &File { // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let size = buffer_capacity_required(self); - buf.try_reserve(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + buf.try_reserve(size.unwrap_or(0))?; io::default_read_to_end(self, buf, size) } // Reserves space in the buffer based on the file size when available. fn read_to_string(&mut self, buf: &mut String) -> io::Result { let size = buffer_capacity_required(self); - buf.try_reserve(size.unwrap_or(0)).map_err(|_| io::ErrorKind::OutOfMemory)?; + buf.try_reserve(size.unwrap_or(0))?; io::default_read_to_string(self, buf, size) } } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index e0dc9f96ae9b2..83db332ee2558 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -344,7 +344,7 @@ impl Read for BufReader { // delegate to the inner implementation. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let inner_buf = self.buffer(); - buf.try_reserve(inner_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?; + buf.try_reserve(inner_buf.len())?; buf.extend_from_slice(inner_buf); let nread = inner_buf.len(); self.discard_buffer(); diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 557e64dc8674e..cb972abd2b821 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -304,7 +304,7 @@ impl Read for &[u8] { #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let len = self.len(); - buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?; + buf.try_reserve(len)?; buf.extend_from_slice(*self); *self = &self[len..]; Ok(len) @@ -452,7 +452,7 @@ impl Read for VecDeque { fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { // The total len is known upfront so we can reserve it in a single call. let len = self.len(); - buf.try_reserve(len).map_err(|_| ErrorKind::OutOfMemory)?; + buf.try_reserve(len)?; let (front, back) = self.as_slices(); buf.extend_from_slice(front); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 102db62fced34..0d1c2702b7829 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -465,7 +465,7 @@ pub(crate) fn default_read_to_end( if buf.len() == buf.capacity() { // buf is full, need more space - buf.try_reserve(PROBE_SIZE).map_err(|_| ErrorKind::OutOfMemory)?; + buf.try_reserve(PROBE_SIZE)?; } let mut spare = buf.spare_capacity_mut(); @@ -834,7 +834,7 @@ pub trait Read { /// if src_buf.is_empty() { /// break; /// } - /// dest_vec.try_reserve(src_buf.len()).map_err(|_| io::ErrorKind::OutOfMemory)?; + /// dest_vec.try_reserve(src_buf.len())?; /// dest_vec.extend_from_slice(src_buf); /// /// // Any irreversible side effects should happen after `try_reserve` succeeds, From 0abd3b76b7b20076981fcc002ca43de63f836ee8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 18 Feb 2024 09:36:36 +0100 Subject: [PATCH 190/613] remove simd_reduce_{min,max}_nanless --- src/intrinsic/simd.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index dedd46538589d..d8091724d8647 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -1041,9 +1041,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( minmax_red!(simd_reduce_min: vector_reduce_min, vector_reduce_fmin); minmax_red!(simd_reduce_max: vector_reduce_max, vector_reduce_fmax); - // TODO(sadlerap): revisit these intrinsics to generate more optimal reductions - minmax_red!(simd_reduce_min_nanless: vector_reduce_min, vector_reduce_fmin); - minmax_red!(simd_reduce_max_nanless: vector_reduce_max, vector_reduce_fmax); macro_rules! bitwise_red { ($name:ident : $op:expr, $boolean:expr) => { From ac8c8b612d958a5f65669957033cf38a2781168f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 18 Feb 2024 09:36:36 +0100 Subject: [PATCH 191/613] remove simd_reduce_{min,max}_nanless --- src/intrinsics/simd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index ebdc744bcd833..8f662808522b7 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -743,7 +743,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().bxor(a, b)); } - sym::simd_reduce_min | sym::simd_reduce_min_nanless => { + sym::simd_reduce_min => { intrinsic_args!(fx, args => (v); intrinsic); if !v.layout().ty.is_simd() { @@ -762,7 +762,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - sym::simd_reduce_max | sym::simd_reduce_max_nanless => { + sym::simd_reduce_max => { intrinsic_args!(fx, args => (v); intrinsic); if !v.layout().ty.is_simd() { From 1ea6cd715e01f14395ee3f7d944ecc68adf0dde4 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 19 Aug 2023 18:46:11 -0400 Subject: [PATCH 192/613] Add std::ffi::c_str modules --- library/alloc/src/ffi/c_str.rs | 2 ++ library/alloc/src/ffi/mod.rs | 10 +++++++--- library/core/src/ffi/c_str.rs | 17 ++++++++++++----- library/core/src/ffi/mod.rs | 14 ++++++++++++-- library/std/src/ffi/c_str.rs | 19 +++++++++++++++++++ library/std/src/ffi/mod.rs | 32 ++++++++++++++++++++++++++------ library/std/src/lib.rs | 1 + 7 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 library/std/src/ffi/c_str.rs diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 9419b0cfb24fa..35d1f681af605 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -1,3 +1,5 @@ +//! [`CString`] and its related types. + #[cfg(test)] mod tests; diff --git a/library/alloc/src/ffi/mod.rs b/library/alloc/src/ffi/mod.rs index e8530fbc1f08f..9fc1acc231bff 100644 --- a/library/alloc/src/ffi/mod.rs +++ b/library/alloc/src/ffi/mod.rs @@ -80,9 +80,13 @@ #![stable(feature = "alloc_ffi", since = "1.64.0")] +#[doc(no_inline)] #[stable(feature = "alloc_c_string", since = "1.64.0")] -pub use self::c_str::FromVecWithNulError; +pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError}; + +#[doc(inline)] #[stable(feature = "alloc_c_string", since = "1.64.0")] -pub use self::c_str::{CString, IntoStringError, NulError}; +pub use self::c_str::CString; -mod c_str; +#[unstable(feature = "c_str_module", issue = "112134")] +pub mod c_str; diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 248943cf02260..cf1427b21bc74 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -1,3 +1,5 @@ +//! [`CStr`] and its related types. + use crate::cmp::Ordering; use crate::error::Error; use crate::ffi::c_char; @@ -8,15 +10,20 @@ use crate::slice; use crate::slice::memchr; use crate::str; +// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link +// depends on where the item is being documented. however, since this is libcore, we can't +// actually reference libstd or liballoc in intra-doc links. so, the best we can do is remove the +// links to `CString` and `String` for now until a solution is developed + /// Representation of a borrowed C string. /// /// This type represents a borrowed reference to a nul-terminated /// array of bytes. It can be constructed safely from a &[[u8]] /// slice, or unsafely from a raw `*const c_char`. It can then be /// converted to a Rust &[str] by performing UTF-8 validation, or -/// into an owned [`CString`]. +/// into an owned `CString`. /// -/// `&CStr` is to [`CString`] as &[str] is to [`String`]: the former +/// `&CStr` is to `CString` as &[str] is to `String`: the former /// in each pair are borrowed references; the latter are owned /// strings. /// @@ -25,9 +32,6 @@ use crate::str; /// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor /// to provide a safe interface to other consumers. /// -/// [`CString`]: ../../std/ffi/struct.CString.html -/// [`String`]: ../../std/string/struct.String.html -/// /// # Examples /// /// Inspecting a foreign C string: @@ -124,10 +128,13 @@ enum FromBytesWithNulErrorKind { NotNulTerminated, } +// FIXME: const stability attributes should not be required here, I think impl FromBytesWithNulError { + #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] const fn interior_nul(pos: usize) -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } } + #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] const fn not_nul_terminated() -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 44200926a32eb..3627e844222ac 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -13,10 +13,20 @@ use crate::fmt; use crate::marker::PhantomData; use crate::ops::{Deref, DerefMut}; +#[doc(no_inline)] #[stable(feature = "core_c_str", since = "1.64.0")] -pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError}; +pub use self::c_str::FromBytesWithNulError; -mod c_str; +#[doc(no_inline)] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +pub use self::c_str::FromBytesUntilNulError; + +#[doc(inline)] +#[stable(feature = "core_c_str", since = "1.64.0")] +pub use self::c_str::CStr; + +#[unstable(feature = "c_str_module", issue = "112134")] +pub mod c_str; macro_rules! type_alias { { diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs new file mode 100644 index 0000000000000..b59b0c5bba65a --- /dev/null +++ b/library/std/src/ffi/c_str.rs @@ -0,0 +1,19 @@ +//! [`CStr`], [`CString`], and related types. + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::ffi::c_str::CStr; + +#[stable(feature = "cstr_from_bytes", since = "1.10.0")] +pub use core::ffi::c_str::FromBytesWithNulError; + +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +pub use core::ffi::c_str::FromBytesUntilNulError; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use alloc::ffi::c_str::{CString, NulError}; + +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] +pub use alloc::ffi::c_str::FromVecWithNulError; + +#[stable(feature = "cstring_into", since = "1.7.0")] +pub use alloc::ffi::c_str::IntoStringError; diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 818571ddaaa16..a14a3fe760da0 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -161,12 +161,32 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[stable(feature = "alloc_c_string", since = "1.64.0")] -pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError}; -#[stable(feature = "cstr_from_bytes_until_nul", since = "1.73.0")] -pub use core::ffi::FromBytesUntilNulError; -#[stable(feature = "core_c_str", since = "1.64.0")] -pub use core::ffi::{CStr, FromBytesWithNulError}; +#[unstable(feature = "c_str_module", issue = "112134")] +pub mod c_str; + +#[doc(inline)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::c_str::{CStr, CString}; + +#[doc(no_inline)] +#[stable(feature = "cstr_from_bytes", since = "1.10.0")] +pub use self::c_str::FromBytesWithNulError; + +#[doc(no_inline)] +#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] +pub use self::c_str::FromBytesUntilNulError; + +#[doc(no_inline)] +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::c_str::NulError; + +#[doc(no_inline)] +#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] +pub use self::c_str::FromVecWithNulError; + +#[doc(no_inline)] +#[stable(feature = "cstring_into", since = "1.7.0")] +pub use self::c_str::IntoStringError; #[stable(feature = "rust1", since = "1.0.0")] pub use self::os_str::{OsStr, OsString}; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c6cd2c6786ad6..87d9a0c9185e8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -314,6 +314,7 @@ // // Library features (core): // tidy-alphabetical-start +#![feature(c_str_module)] #![feature(char_internals)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] From 2e87f31fe9f9a147d7a19202e5c4f918b8c975ac Mon Sep 17 00:00:00 2001 From: Young-Flash Date: Thu, 22 Feb 2024 17:37:40 +0800 Subject: [PATCH 193/613] add HoverDisplayConfig --- crates/hir/src/display.rs | 12 +++++++----- crates/ide-db/src/defs.rs | 12 ++++++++++-- crates/ide/src/hover.rs | 2 +- crates/ide/src/hover/render.rs | 5 +++-- crates/ide/src/hover/tests.rs | 2 +- crates/ide/src/static_index.rs | 6 +++--- crates/rust-analyzer/src/config.rs | 4 ++-- docs/user/generated_config.adoc | 2 +- editors/code/package.json | 2 +- 9 files changed, 29 insertions(+), 18 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 0e221a2149ae2..08e0c6e752473 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -17,7 +17,10 @@ use hir_ty::{ }; use crate::{ - Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, + Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, + SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, + TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -593,9 +596,9 @@ impl HirDisplay for Trait { write_generic_params(def_id, f)?; write_where_clause(def_id, f)?; - let mut display_size = 0; - let max_display_size = f.max_size.unwrap_or(7); let assoc_items = self.items(f.db); + let assoc_items_size = assoc_items.len(); + let max_display_size = f.max_size.unwrap_or(assoc_items_size); if assoc_items.is_empty() { f.write_str(" {}")?; } else { @@ -614,8 +617,7 @@ impl HirDisplay for Trait { } }; f.write_str(",\n")?; - display_size += 1; - if display_size == max_display_size && index != assoc_items.len() - 1{ + if index + 1 == max_display_size && index + 1 != assoc_items_size { f.write_str(" ...\n")?; break; } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 8de885f49948b..35aaf864696af 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -24,6 +24,12 @@ use crate::documentation::{Documentation, HasDocs}; use crate::famous_defs::FamousDefs; use crate::RootDatabase; +#[derive(Default)] +pub struct HoverDisplayConfig { + pub trait_item_display_num: Option, + // todo: add config for struct & enum +} + // FIXME: a more precise name would probably be `Symbol`? #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] pub enum Definition { @@ -213,7 +219,7 @@ impl Definition { }) } - pub fn label(&self, db: &RootDatabase, max_size: Option) -> String { + pub fn label(&self, db: &RootDatabase, hover_display_config: HoverDisplayConfig) -> String { match *self { Definition::Macro(it) => it.display(db).to_string(), Definition::Field(it) => it.display(db).to_string(), @@ -224,7 +230,9 @@ impl Definition { Definition::Variant(it) => it.display(db).to_string(), Definition::Const(it) => it.display(db).to_string(), Definition::Static(it) => it.display(db).to_string(), - Definition::Trait(it) => it.display_truncated(db, max_size).to_string(), + Definition::Trait(it) => { + it.display_truncated(db, hover_display_config.trait_item_display_num).to_string() + } Definition::TraitAlias(it) => it.display(db).to_string(), Definition::TypeAlias(it) => it.display(db).to_string(), Definition::BuiltinType(it) => it.name().display(db).to_string(), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 4b3fdaff0b346..64346a59b77fb 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -32,7 +32,7 @@ pub struct HoverConfig { pub documentation: bool, pub keywords: bool, pub format: HoverDocFormat, - pub trait_item_display_on_hover: Option, + pub trait_item_display_num: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index c955f46bc454a..6d7886feec338 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -8,7 +8,7 @@ use hir::{ }; use ide_db::{ base_db::SourceDatabase, - defs::Definition, + defs::{Definition, HoverDisplayConfig}, documentation::HasDocs, famous_defs::FamousDefs, generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, @@ -406,7 +406,8 @@ pub(super) fn definition( config: &HoverConfig, ) -> Markup { let mod_path = definition_mod_path(db, &def); - let label = def.label(db, config.trait_item_display_on_hover); + let hover_config = HoverDisplayConfig { trait_item_display_num: config.trait_item_display_num }; + let label = def.label(db, hover_config); let docs = def.docs(db, famous_defs); let value = (|| match def { Definition::Variant(it) => { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 2df4ca5810b24..e2278fe4b3abc 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -17,7 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { documentation: true, format: HoverDocFormat::Markdown, keywords: true, - trait_item_display_on_hover: Some(7), + trait_item_display_num: Some(7), }; fn check_hover_no_result(ra_fixture: &str) { diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 8d5f5e1bf6777..8d6e161c1b971 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -4,7 +4,7 @@ use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use ide_db::{ base_db::{FileId, FileRange, SourceDatabaseExt}, - defs::Definition, + defs::{Definition, HoverDisplayConfig}, documentation::Documentation, famous_defs::FamousDefs, helpers::get_definition, @@ -166,7 +166,7 @@ impl StaticIndex<'_> { documentation: true, keywords: true, format: crate::HoverDocFormat::Markdown, - trait_item_display_on_hover: Some(7) + trait_item_display_num: None, }; let tokens = tokens.filter(|token| { matches!( @@ -197,7 +197,7 @@ impl StaticIndex<'_> { enclosing_moniker: current_crate .zip(def.enclosing_definition(self.db)) .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)), - signature: Some(def.label(self.db, hover_config.trait_item_display_on_hover)), + signature: Some(def.label(self.db, HoverDisplayConfig::default())), kind: def_to_kind(self.db, def), }); self.def_map.insert(def, it); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 230a0385cdb3b..40a2077cb1855 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -591,7 +591,7 @@ config_data! { signatureInfo_documentation_enable: bool = "true", /// How many trait item display on hover. - trait_item_display_on_hover: Option = "7", + traitItemDisplayNum: Option = "7", /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = "false", @@ -1685,7 +1685,7 @@ impl Config { } }, keywords: self.data.hover_documentation_keywords_enable, - trait_item_display_on_hover: self.data.trait_item_display_on_hover, + trait_item_display_num: self.data.traitItemDisplayNum, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 9f3ab4513294e..7d005828b8c60 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -927,7 +927,7 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- -[[rust-analyzer.trait.item.display.on.hover]]rust-analyzer.trait.item.display.on.hover (default: `7`):: +[[rust-analyzer.traitItemDisplayNum]]rust-analyzer.traitItemDisplayNum (default: `7`):: + -- How many trait item display on hover. diff --git a/editors/code/package.json b/editors/code/package.json index a4f54ae4f4587..b68ab66cdab67 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1648,7 +1648,7 @@ "default": true, "type": "boolean" }, - "rust-analyzer.trait.item.display.on.hover": { + "rust-analyzer.traitItemDisplayNum": { "markdownDescription": "How many trait item display on hover.", "default": 7, "type": [ From 26ee4c93b54739872f3a6575dd49e59e8ed648ea Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 23 Feb 2024 17:33:46 +0100 Subject: [PATCH 194/613] Update libc dependency to 0.2.153 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b0010a6a4364..b8852599065b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,9 +241,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" From bb5b75f28dff36bb2ffded0ee3c3384745a1b3e1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 23 Feb 2024 12:32:14 -0500 Subject: [PATCH 195/613] Update gcc version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 12dafeb9edeed..20aebf091a70a 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -cdd897840 +d24c8dae3 From ea476b1fa1cd42f5ee10a4d6cc95d6bbaf63ce86 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 23 Feb 2024 22:41:21 +0300 Subject: [PATCH 196/613] on the fly type casting for `build.rustc` and `build.cargo` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 834025c81887e..3461beba0bd0a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -811,8 +811,8 @@ define_config! { host: Option> = "host", target: Option> = "target", build_dir: Option = "build-dir", - cargo: Option = "cargo", - rustc: Option = "rustc", + cargo: Option = "cargo", + rustc: Option = "rustc", rustfmt: Option = "rustfmt", docs: Option = "docs", compiler_docs: Option = "compiler-docs", @@ -1421,7 +1421,7 @@ impl Config { if !flags.skip_stage0_validation { config.check_stage0_version(&rustc, "rustc"); } - PathBuf::from(rustc) + rustc } else { config.download_beta_toolchain(); config.out.join(config.build.triple).join("stage0/bin/rustc") @@ -1431,7 +1431,7 @@ impl Config { if !flags.skip_stage0_validation { config.check_stage0_version(&cargo, "cargo"); } - PathBuf::from(cargo) + cargo } else { config.download_beta_toolchain(); config.out.join(config.build.triple).join("stage0/bin/cargo") @@ -2292,7 +2292,7 @@ impl Config { } // check rustc/cargo version is same or lower with 1 apart from the building one - pub fn check_stage0_version(&self, program_path: &str, component_name: &'static str) { + pub fn check_stage0_version(&self, program_path: &Path, component_name: &'static str) { if self.dry_run() { return; } @@ -2303,7 +2303,8 @@ impl Config { let stage0_name = stage0_output.next().unwrap(); if stage0_name != component_name { fail(&format!( - "Expected to find {component_name} at {program_path} but it claims to be {stage0_name}" + "Expected to find {component_name} at {} but it claims to be {stage0_name}", + program_path.display() )); } From c638defad75543fe2762a2afd34e4b7f97be5a35 Mon Sep 17 00:00:00 2001 From: tempdragon <645703113@qq.com> Date: Fri, 23 Feb 2024 22:31:05 +0800 Subject: [PATCH 197/613] feat(debuginfo): Init Commit for debuginfo Support TODO: 1. Add int.rs locations 2. Add demangling support 3. Add debug scope support 4. Add vtable support 5. Clean up builder.rs locations --- src/base.rs | 4 +- src/builder.rs | 362 ++++++++++++++++++++++++----------------------- src/context.rs | 4 +- src/debuginfo.rs | 227 ++++++++++++++++++++++++++--- src/int.rs | 10 +- src/lib.rs | 3 +- 6 files changed, 398 insertions(+), 212 deletions(-) diff --git a/src/base.rs b/src/base.rs index 773e234150d1b..bcf467839a45d 100644 --- a/src/base.rs +++ b/src/base.rs @@ -184,8 +184,8 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock // wrapper here maybe_create_entry_wrapper::>(&cx); - // Finalize debuginfo - if cx.sess().opts.debuginfo != DebugInfo::None { + // FINALIZE debuginfo + if cx.sess().opts.debuginfo != DebugInfo::None { cx.debuginfo_finalize(); } } diff --git a/src/builder.rs b/src/builder.rs index 56d9fd30bf675..fc4c4d86a7d63 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,16 +4,7 @@ use std::convert::TryFrom; use std::ops::Deref; use gccjit::{ - BinaryOp, - Block, - ComparisonOp, - Context, - Function, - LValue, - RValue, - ToRValue, - Type, - UnaryOp, + BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, UnaryOp }; use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_codegen_ssa::MemFlags; @@ -70,6 +61,7 @@ pub struct Builder<'a: 'gcc, 'gcc, 'tcx> { pub cx: &'a CodegenCx<'gcc, 'tcx>, pub block: Block<'gcc>, stack_var_count: Cell, + pub loc: Option>, } impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { @@ -78,6 +70,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { cx, block, stack_var_count: Cell::new(0), + loc:None } } @@ -93,14 +86,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => order, }; let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size)); - let previous_var = func.new_local(None, previous_value.get_type(), "previous_value"); - let return_value = func.new_local(None, previous_value.get_type(), "return_value"); - self.llbb().add_assignment(None, previous_var, previous_value); - self.llbb().add_assignment(None, return_value, previous_var.to_rvalue()); + let previous_var = func.new_local(self.loc, previous_value.get_type(), "previous_value"); + let return_value = func.new_local(self.loc, previous_value.get_type(), "return_value"); + self.llbb().add_assignment(self.loc, previous_var, previous_value); + self.llbb().add_assignment(self.loc, return_value, previous_var.to_rvalue()); let while_block = func.new_block("while"); let after_block = func.new_block("after_while"); - self.llbb().end_with_jump(None, while_block); + self.llbb().end_with_jump(self.loc, while_block); // NOTE: since jumps were added and compare_exchange doesn't expect this, the current block in the // state need to be updated. @@ -112,12 +105,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ExtremumOperation::Min => ComparisonOp::GreaterThan, }; - let cond1 = self.context.new_comparison(None, comparison_operator, previous_var.to_rvalue(), self.context.new_cast(None, src, previous_value.get_type())); + let cond1 = self.context.new_comparison(self.loc, comparison_operator, previous_var.to_rvalue(), self.context.new_cast(self.loc, src, previous_value.get_type())); let compare_exchange = self.compare_exchange(dst, previous_var, src, order, load_ordering, false); - let cond2 = self.cx.context.new_unary_op(None, UnaryOp::LogicalNegate, compare_exchange.get_type(), compare_exchange); - let cond = self.cx.context.new_binary_op(None, BinaryOp::LogicalAnd, self.cx.bool_type, cond1, cond2); + let cond2 = self.cx.context.new_unary_op(self.loc, UnaryOp::LogicalNegate, compare_exchange.get_type(), compare_exchange); + let cond = self.cx.context.new_binary_op(self.loc, BinaryOp::LogicalAnd, self.cx.bool_type, cond1, cond2); - while_block.end_with_conditional(None, cond, while_block, after_block); + while_block.end_with_conditional(self.loc, cond, while_block, after_block); // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. @@ -135,17 +128,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let void_ptr_type = self.context.new_type::<*mut ()>(); let volatile_void_ptr_type = void_ptr_type.make_volatile(); - let dst = self.context.new_cast(None, dst, volatile_void_ptr_type); - let expected = self.context.new_cast(None, cmp.get_address(None), void_ptr_type); + let dst = self.context.new_cast(self.loc, dst, volatile_void_ptr_type); + let expected = self.context.new_cast(self.loc, cmp.get_address(self.loc), void_ptr_type); // NOTE: not sure why, but we have the wrong type here. let int_type = compare_exchange.get_param(2).to_rvalue().get_type(); - let src = self.context.new_cast(None, src, int_type); - self.context.new_call(None, compare_exchange, &[dst, expected, src, weak, order, failure_order]) + let src = self.context.new_cast(self.loc, src, int_type); + self.context.new_call(self.loc, compare_exchange, &[dst, expected, src, weak, order, failure_order]) } pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) { - self.llbb().add_assignment(None, lvalue, value); + self.llbb().add_assignment(self.loc, lvalue, value); } fn check_call<'b>(&mut self, _typ: &str, func: Function<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { @@ -220,10 +213,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let actual_ty = actual_val.get_type(); if expected_ty != actual_ty { if !actual_ty.is_vector() && !expected_ty.is_vector() && (actual_ty.is_integral() && expected_ty.is_integral()) || (actual_ty.get_pointee().is_some() && expected_ty.get_pointee().is_some()) { - self.context.new_cast(None, actual_val, expected_ty) + self.context.new_cast(self.loc, actual_val, expected_ty) } else if on_stack_param_indices.contains(&index) { - actual_val.dereference(None).to_rvalue() + actual_val.dereference(self.loc).to_rvalue() } else { assert!(!((actual_ty.is_vector() && !expected_ty.is_vector()) || (!actual_ty.is_vector() && expected_ty.is_vector())), "{:?} ({}) -> {:?} ({}), index: {:?}[{}]", actual_ty, actual_ty.is_vector(), expected_ty, expected_ty.is_vector(), func_ptr, index); @@ -268,12 +261,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let current_func = self.block.get_function(); if return_type != void_type { unsafe { RETURN_VALUE_COUNT += 1 }; - let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); - self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); + let result = current_func.new_local(self.loc, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT })); + self.block.add_assignment(self.loc, result, self.cx.context.new_call(self.loc, func, &args)); result.to_rvalue() } else { - self.block.add_eval(None, self.cx.context.new_call(None, func, &args)); + self.block.add_eval(self.loc, self.cx.context.new_call(self.loc, func, &args)); // Return dummy value when not having return value. self.context.new_rvalue_from_long(self.isize_type, 0) } @@ -286,7 +279,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { None => { // NOTE: due to opaque pointers now being used, we need to cast here. let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr"); - func_ptr = self.context.new_cast(None, func_ptr, typ); + func_ptr = self.context.new_cast(self.loc, func_ptr, typ); new_func_type }, }; @@ -309,26 +302,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if return_type != void_type { unsafe { RETURN_VALUE_COUNT += 1 }; - let return_value = self.cx.context.new_call_through_ptr(None, func_ptr, &args); + let return_value = self.cx.context.new_call_through_ptr(self.loc, func_ptr, &args); let return_value = llvm::adjust_intrinsic_return_value(&self, return_value, &func_name, &args, args_adjusted, orig_args); - let result = current_func.new_local(None, return_value.get_type(), &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT })); - self.block.add_assignment(None, result, return_value); + let result = current_func.new_local(self.loc, return_value.get_type(), &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT })); + self.block.add_assignment(self.loc, result, return_value); result.to_rvalue() } else { #[cfg(not(feature="master"))] if gcc_func.get_param_count() == 0 { // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics. - self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[])); + self.block.add_eval(self.loc, self.cx.context.new_call_through_ptr(self.loc, func_ptr, &[])); } else { - self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); + self.block.add_eval(self.loc, self.cx.context.new_call_through_ptr(self.loc, func_ptr, &args)); } #[cfg(feature="master")] - self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args)); + self.block.add_eval(self.loc, self.cx.context.new_call_through_ptr(self.loc, func_ptr, &args)); // Return dummy value when not having return value. - let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed"); - self.block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0)); + let result = current_func.new_local(self.loc, self.isize_type, "dummyValueThatShouldNeverBeUsed"); + self.block.add_assignment(self.loc, result, self.context.new_rvalue_from_long(self.isize_type, 0)); result.to_rvalue() } } @@ -340,8 +333,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let current_func = self.block.get_function(); // TODO(antoyo): return the new_call() directly? Since the overflow function has no side-effects. unsafe { RETURN_VALUE_COUNT += 1 }; - let result = current_func.new_local(None, return_type, &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT })); - self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args)); + let result = current_func.new_local(self.loc, return_type, &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT })); + self.block.add_assignment(self.loc, result, self.cx.context.new_call(self.loc, func, &args)); result.to_rvalue() } } @@ -429,29 +422,29 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn ret_void(&mut self) { - self.llbb().end_with_void_return(None) + self.llbb().end_with_void_return(self.loc) } fn ret(&mut self, mut value: RValue<'gcc>) { if self.structs_as_pointer.borrow().contains(&value) { // NOTE: hack to workaround a limitation of the rustc API: see comment on // CodegenCx.structs_as_pointer - value = value.dereference(None).to_rvalue(); + value = value.dereference(self.loc).to_rvalue(); } let expected_return_type = self.current_func().get_return_type(); if !expected_return_type.is_compatible_with(value.get_type()) { // NOTE: due to opaque pointers now being used, we need to cast here. - value = self.context.new_cast(None, value, expected_return_type); + value = self.context.new_cast(self.loc, value, expected_return_type); } - self.llbb().end_with_return(None, value); + self.llbb().end_with_return(self.loc, value); } fn br(&mut self, dest: Block<'gcc>) { - self.llbb().end_with_jump(None, dest) + self.llbb().end_with_jump(self.loc, dest) } fn cond_br(&mut self, cond: RValue<'gcc>, then_block: Block<'gcc>, else_block: Block<'gcc>) { - self.llbb().end_with_conditional(None, cond, then_block, else_block) + self.llbb().end_with_conditional(self.loc, cond, then_block, else_block) } fn switch(&mut self, value: RValue<'gcc>, default_block: Block<'gcc>, cases: impl ExactSizeIterator)>) { @@ -461,7 +454,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let on_val = self.const_uint_big(typ, on_val); gcc_cases.push(self.context.new_case(on_val, on_val, dest)); } - self.block.end_with_switch(None, value, default_block, &gcc_cases); + self.block.end_with_switch(self.loc, value, default_block, &gcc_cases); } #[cfg(feature="master")] @@ -474,20 +467,20 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.block = current_block; let return_value = self.current_func() - .new_local(None, call.get_type(), "invokeResult"); + .new_local(self.loc, call.get_type(), "invokeResult"); - try_block.add_assignment(None, return_value, call); + try_block.add_assignment(self.loc, return_value, call); - try_block.end_with_jump(None, then); + try_block.end_with_jump(self.loc, then); if self.cleanup_blocks.borrow().contains(&catch) { - self.block.add_try_finally(None, try_block, catch); + self.block.add_try_finally(self.loc, try_block, catch); } else { - self.block.add_try_catch(None, try_block, catch); + self.block.add_try_catch(self.loc, try_block, catch); } - self.block.end_with_jump(None, then); + self.block.end_with_jump(self.loc, then); return_value.to_rvalue() } @@ -496,7 +489,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> { let call_site = self.call(typ, fn_attrs, None, func, args, None); let condition = self.context.new_rvalue_from_int(self.bool_type, 1); - self.llbb().end_with_conditional(None, condition, then, catch); + self.llbb().end_with_conditional(self.loc, condition, then, catch); if let Some(_fn_abi) = fn_abi { // TODO(bjorn3): Apply function attributes } @@ -505,16 +498,16 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn unreachable(&mut self) { let func = self.context.get_builtin_function("__builtin_unreachable"); - self.block.add_eval(None, self.context.new_call(None, func, &[])); + self.block.add_eval(self.loc, self.context.new_call(self.loc, func, &[])); let return_type = self.block.get_function().get_return_type(); let void_type = self.context.new_type::<()>(); if return_type == void_type { - self.block.end_with_void_return(None) + self.block.end_with_void_return(self.loc) } else { let return_value = self.current_func() - .new_local(None, return_type, "unreachableReturn"); - self.block.end_with_return(None, return_value) + .new_local(self.loc, return_type, "unreachableReturn"); + self.block.end_with_return(self.loc, return_value) } } @@ -539,7 +532,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - a * b + let i=a * b; + if self.loc.is_some() { + unsafe{ + i.set_location(self.loc.clone().unwrap()); + } + } + i } fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -564,7 +563,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they // should be the same. let typ = a.get_type().to_signed(self); - let b = self.context.new_cast(None, b, typ); + let b = self.context.new_cast(self.loc, b, typ); a / b } @@ -611,7 +610,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if a_type.is_compatible_with(self.cx.float_type) { let fmodf = self.context.get_builtin_function("fmodf"); // FIXME(antoyo): this seems to produce the wrong result. - return self.context.new_call(None, fmodf, &[a, b]); + return self.context.new_call(self.loc, fmodf, &[a, b]); } else if let Some(vector_type) = a_type_unqualified.dyncast_vector() { assert_eq!(a_type_unqualified, b.get_type().unqualified()); @@ -626,12 +625,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }) .collect(); - return self.context.new_rvalue_from_vector(None, a_type, &new_elements) + return self.context.new_rvalue_from_vector(self.loc, a_type, &new_elements) } assert_eq!(a_type_unqualified, self.cx.double_type); let fmod = self.context.get_builtin_function("fmod"); - return self.context.new_call(None, fmod, &[a, b]); + return self.context.new_call(self.loc, fmod, &[a, b]); } fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -665,7 +664,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) + self.cx.context.new_unary_op(self.loc, UnaryOp::Minus, a.get_type(), a) } fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { @@ -738,7 +737,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }; // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial. self.stack_var_count.set(self.stack_var_count.get() + 1); - self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None) + self.current_func().new_local(self.loc, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(self.loc) } fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> { @@ -760,17 +759,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { else { pointee_ty.get_aligned(align.bytes()) }; - let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer()); - let deref = ptr.dereference(None).to_rvalue(); + let ptr = self.context.new_cast(self.loc, ptr, aligned_type.make_pointer()); + let deref = ptr.dereference(self.loc).to_rvalue(); unsafe { RETURN_VALUE_COUNT += 1 }; - let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); - block.add_assignment(None, loaded_value, deref); + let loaded_value = function.new_local(self.loc, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT })); + block.add_assignment(self.loc, loaded_value, deref); loaded_value.to_rvalue() } fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> { - let ptr = self.context.new_cast(None, ptr, ty.make_volatile().make_pointer()); - ptr.dereference(None).to_rvalue() + let ptr = self.context.new_cast(self.loc, ptr, ty.make_volatile().make_pointer()); + ptr.dereference(self.loc).to_rvalue() } fn atomic_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) -> RValue<'gcc> { @@ -783,8 +782,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { .make_const() .make_volatile() .make_pointer(); - let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); - self.context.new_call(None, atomic_load, &[ptr, ordering]) + let ptr = self.context.new_cast(self.loc, ptr, volatile_const_void_ptr_type); + self.context.new_call(self.loc, atomic_load, &[ptr, ordering]) } fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'tcx, RValue<'gcc>> { @@ -859,7 +858,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); - let current = self.llbb().get_function().new_local(None, ptr_type, "loop_var"); + let current = self.llbb().get_function().new_local(self.loc, ptr_type, "loop_var"); let current_val = current.to_rvalue(); self.assign(current, start); @@ -874,7 +873,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]); - self.llbb().add_assignment(None, current, next); + self.llbb().add_assignment(self.loc, current, next); self.br(header_bb); self.switch_to_block(next_bb); @@ -894,14 +893,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn store_with_flags(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align, _flags: MemFlags) -> RValue<'gcc> { let ptr = self.check_store(val, ptr); - let destination = ptr.dereference(None); + let destination = ptr.dereference(self.loc); // NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast // to type so it gets the proper alignment. let destination_type = destination.to_rvalue().get_type().unqualified(); let aligned_type = destination_type.get_aligned(align.bytes()).make_pointer(); - let aligned_destination = self.cx.context.new_bitcast(None, ptr, aligned_type); - let aligned_destination = aligned_destination.dereference(None); - self.llbb().add_assignment(None, aligned_destination, val); + let aligned_destination = self.cx.context.new_bitcast(self.loc, ptr, aligned_type); + let aligned_destination = aligned_destination.dereference(self.loc); + self.llbb().add_assignment(self.loc, aligned_destination, val); // TODO(antoyo): handle align and flags. // NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here? self.cx.context.new_rvalue_zero(self.type_i32()) @@ -914,26 +913,26 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let volatile_const_void_ptr_type = self.context.new_type::<()>() .make_volatile() .make_pointer(); - let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); + let ptr = self.context.new_cast(self.loc, ptr, volatile_const_void_ptr_type); // FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because // the following cast is required to avoid this error: // gcc_jit_context_new_call: mismatching types for argument 2 of function "__atomic_store_4": assignment to param arg1 (type: int) from loadedValue3577 (type: unsigned int __attribute__((aligned(4)))) let int_type = atomic_store.get_param(1).to_rvalue().get_type(); - let value = self.context.new_cast(None, value, int_type); + let value = self.context.new_cast(self.loc, value, int_type); self.llbb() - .add_eval(None, self.context.new_call(None, atomic_store, &[ptr, value, ordering])); + .add_eval(self.loc, self.context.new_call(self.loc, atomic_store, &[ptr, value, ordering])); } fn gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { // NOTE: due to opaque pointers now being used, we need to cast here. - let ptr = self.context.new_cast(None, ptr, typ.make_pointer()); + let ptr = self.context.new_cast(self.loc, ptr, typ.make_pointer()); let ptr_type = ptr.get_type(); let mut pointee_type = ptr.get_type(); // NOTE: we cannot use array indexing here like in inbounds_gep because array indexing is // always considered in bounds in GCC (TODO(antoyo): to be verified). // So, we have to cast to a number. - let mut result = self.context.new_bitcast(None, ptr, self.sizet_type); + let mut result = self.context.new_bitcast(self.loc, ptr, self.sizet_type); // FIXME(antoyo): if there were more than 1 index, this code is probably wrong and would // require dereferencing the pointer. for index in indices { @@ -941,49 +940,49 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(feature="master")] let pointee_size = { let size = self.cx.context.new_sizeof(pointee_type); - self.context.new_cast(None, size, index.get_type()) + self.context.new_cast(self.loc, size, index.get_type()) }; #[cfg(not(feature="master"))] let pointee_size = self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32); result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type); } - self.context.new_bitcast(None, result, ptr_type) + self.context.new_bitcast(self.loc, result, ptr_type) } fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> { // NOTE: due to opaque pointers now being used, we need to cast here. - let ptr = self.context.new_cast(None, ptr, typ.make_pointer()); + let ptr = self.context.new_cast(self.loc, ptr, typ.make_pointer()); // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified). let mut indices = indices.into_iter(); let index = indices.next().expect("first index in inbounds_gep"); - let mut result = self.context.new_array_access(None, ptr, *index); + let mut result = self.context.new_array_access(self.loc, ptr, *index); for index in indices { - result = self.context.new_array_access(None, result, *index); + result = self.context.new_array_access(self.loc, result, *index); } - result.get_address(None) + result.get_address(self.loc) } fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) -> RValue<'gcc> { // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays. assert_eq!(idx as usize as u64, idx); - let value = ptr.dereference(None).to_rvalue(); + let value = ptr.dereference(self.loc).to_rvalue(); if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - let element = self.context.new_array_access(None, value, index); - element.get_address(None) + let element = self.context.new_array_access(self.loc, value, index); + element.get_address(self.loc) } else if let Some(vector_type) = value_type.dyncast_vector() { let array_type = vector_type.get_element_type().make_pointer(); let array = self.bitcast(ptr, array_type); let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - let element = self.context.new_array_access(None, array, index); - element.get_address(None) + let element = self.context.new_array_access(self.loc, array, index); + element.get_address(self.loc) } else if let Some(struct_type) = value_type.is_struct() { // NOTE: due to opaque pointers now being used, we need to bitcast here. let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer()); - ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None) + ptr.dereference_field(self.loc, struct_type.get_field(idx as i32)).get_address(self.loc) } else { panic!("Unexpected type {:?}", value_type); @@ -1002,7 +1001,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // TODO(antoyo): nothing to do as it is only for LLVM? return value; } - self.context.new_cast(None, value, dest_ty) + self.context.new_cast(self.loc, value, dest_ty) } fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1023,11 +1022,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { // TODO(antoyo): make sure it truncates. - self.context.new_cast(None, value, dest_ty) + self.context.new_cast(self.loc, value, dest_ty) } fn fpext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(None, value, dest_ty) + self.context.new_cast(self.loc, value, dest_ty) } fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { @@ -1055,13 +1054,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { (false, true) => { // NOTE: Projecting a field of a pointer type will attempt a cast from a signed char to // a pointer, which is not supported by gccjit. - return self.cx.context.new_cast(None, self.inttoptr(value, val_type.make_pointer()), dest_ty); + return self.cx.context.new_cast(self.loc, self.inttoptr(value, val_type.make_pointer()), dest_ty); }, (false, false) => { // When they are not pointers, we want a transmute (or reinterpret_cast). self.bitcast(value, dest_ty) }, - (true, true) => self.cx.context.new_cast(None, value, dest_ty), + (true, true) => self.cx.context.new_cast(self.loc, value, dest_ty), (true, false) => unimplemented!(), } } @@ -1072,7 +1071,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { - self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + self.context.new_comparison(self.loc, op.to_gcc_comparison(), lhs, rhs) } /* Miscellaneous instructions */ @@ -1084,7 +1083,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let src = self.pointercast(src, self.type_ptr_to(self.type_void())); let memcpy = self.context.get_builtin_function("memcpy"); // TODO(antoyo): handle aligns and is_volatile. - self.block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size])); + self.block.add_eval(self.loc, self.context.new_call(self.loc, memcpy, &[dst, src, size])); } fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) { @@ -1102,7 +1101,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let memmove = self.context.get_builtin_function("memmove"); // TODO(antoyo): handle is_volatile. - self.block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size])); + self.block.add_eval(self.loc, self.context.new_call(self.loc, memmove, &[dst, src, size])); } fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) { @@ -1110,27 +1109,27 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let ptr = self.pointercast(ptr, self.type_i8p()); let memset = self.context.get_builtin_function("memset"); // TODO(antoyo): handle align and is_volatile. - let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type); + let fill_byte = self.context.new_cast(self.loc, fill_byte, self.i32_type); let size = self.intcast(size, self.type_size_t(), false); - self.block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size])); + self.block.add_eval(self.loc, self.context.new_call(self.loc, memset, &[ptr, fill_byte, size])); } fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> { let func = self.current_func(); - let variable = func.new_local(None, then_val.get_type(), "selectVar"); + let variable = func.new_local(self.loc, then_val.get_type(), "selectVar"); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); - self.llbb().end_with_conditional(None, cond, then_block, else_block); + self.llbb().end_with_conditional(self.loc, cond, then_block, else_block); - then_block.add_assignment(None, variable, then_val); - then_block.end_with_jump(None, after_block); + then_block.add_assignment(self.loc, variable, then_val); + then_block.end_with_jump(self.loc, after_block); if !then_val.get_type().is_compatible_with(else_val.get_type()) { - else_val = self.context.new_cast(None, else_val, then_val.get_type()); + else_val = self.context.new_cast(self.loc, else_val, then_val.get_type()); } - else_block.add_assignment(None, variable, else_val); - else_block.end_with_jump(None, after_block); + else_block.add_assignment(self.loc, variable, else_val); + else_block.end_with_jump(self.loc, after_block); // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. @@ -1146,7 +1145,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(feature="master")] fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> { - self.context.new_vector_access(None, vec, idx).to_rvalue() + self.context.new_vector_access(self.loc, vec, idx).to_rvalue() } #[cfg(not(feature="master"))] @@ -1154,9 +1153,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let vector_type = vec.get_type().unqualified().dyncast_vector().expect("Called extract_element on a non-vector type"); let element_type = vector_type.get_element_type(); let vec_num_units = vector_type.get_num_units(); - let array_type = self.context.new_array_type(None, element_type, vec_num_units as u64); - let array = self.context.new_bitcast(None, vec, array_type).to_rvalue(); - self.context.new_array_access(None, array, idx).to_rvalue() + let array_type = self.context.new_array_type(self.loc, element_type, vec_num_units as u64); + let array = self.context.new_bitcast(self.loc, vec, array_type).to_rvalue(); + self.context.new_array_access(self.loc, array, idx).to_rvalue() } fn vector_splat(&mut self, _num_elts: usize, _elt: RValue<'gcc>) -> RValue<'gcc> { @@ -1170,8 +1169,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - let element = self.context.new_array_access(None, aggregate_value, index); - element.get_address(None) + let element = self.context.new_array_access(self.loc, aggregate_value, index); + element.get_address(self.loc) } else if value_type.dyncast_vector().is_some() { panic!(); @@ -1180,14 +1179,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if let Some(struct_type) = pointer_type.is_struct() { // NOTE: hack to workaround a limitation of the rustc API: see comment on // CodegenCx.structs_as_pointer - aggregate_value.dereference_field(None, struct_type.get_field(idx as i32)).to_rvalue() + aggregate_value.dereference_field(self.loc, struct_type.get_field(idx as i32)).to_rvalue() } else { panic!("Unexpected type {:?}", value_type); } } else if let Some(struct_type) = value_type.is_struct() { - aggregate_value.access_field(None, struct_type.get_field(idx as i32)).to_rvalue() + aggregate_value.access_field(self.loc, struct_type.get_field(idx as i32)).to_rvalue() } else { panic!("Unexpected type {:?}", value_type); @@ -1202,7 +1201,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let lvalue = if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - self.context.new_array_access(None, aggregate_value, index) + self.context.new_array_access(self.loc, aggregate_value, index) } else if value_type.dyncast_vector().is_some() { panic!(); @@ -1211,7 +1210,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if let Some(struct_type) = pointer_type.is_struct() { // NOTE: hack to workaround a limitation of the rustc API: see comment on // CodegenCx.structs_as_pointer - aggregate_value.dereference_field(None, struct_type.get_field(idx as i32)) + aggregate_value.dereference_field(self.loc, struct_type.get_field(idx as i32)) } else { panic!("Unexpected type {:?}", value_type); @@ -1225,13 +1224,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let value = // NOTE: sometimes, rustc will create a value with the wrong type. if lvalue_type != value.get_type() { - self.context.new_cast(None, value, lvalue_type) + self.context.new_cast(self.loc, value, lvalue_type) } else { value }; - self.llbb().add_assignment(None, lvalue, value); + self.llbb().add_assignment(self.loc, lvalue, value); aggregate_value } @@ -1254,10 +1253,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let eh_pointer_builtin = self.cx.context.get_target_builtin_function("__builtin_eh_pointer"); let zero = self.cx.context.new_rvalue_zero(self.int_type); - let ptr = self.cx.context.new_call(None, eh_pointer_builtin, &[zero]); + let ptr = self.cx.context.new_call(self.loc, eh_pointer_builtin, &[zero]); let value1_type = self.u8_type.make_pointer(); - let ptr = self.cx.context.new_cast(None, ptr, value1_type); + let ptr = self.cx.context.new_cast(self.loc, ptr, value1_type); let value1 = ptr; let value2 = zero; // TODO(antoyo): set the proper value here (the type of exception?). @@ -1266,9 +1265,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature="master"))] fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { - let value1 = self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0") + let value1 = self.current_func().new_local(self.loc, self.u8_type.make_pointer(), "landing_pad0") .to_rvalue(); - let value2 = self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue(); + let value2 = self.current_func().new_local(self.loc, self.i32_type, "landing_pad1").to_rvalue(); (value1, value2) } @@ -1280,9 +1279,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(feature="master")] fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) { let exn_type = exn0.get_type(); - let exn = self.context.new_cast(None, exn0, exn_type); + let exn = self.context.new_cast(self.loc, exn0, exn_type); let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume"); - self.llbb().add_eval(None, self.context.new_call(None, unwind_resume, &[exn])); + self.llbb().add_eval(self.loc, self.context.new_call(self.loc, unwind_resume, &[exn])); self.unreachable(); } @@ -1329,8 +1328,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before // expected so that we store expected after the call. - let success_var = self.current_func().new_local(None, self.bool_type, "success"); - self.llbb().add_assignment(None, success_var, success); + let success_var = self.current_func().new_local(self.loc, self.bool_type, "success"); + self.llbb().add_assignment(self.loc, success_var, success); (expected.to_rvalue(), success_var.to_rvalue()) } @@ -1358,12 +1357,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let void_ptr_type = self.context.new_type::<*mut ()>(); let volatile_void_ptr_type = void_ptr_type.make_volatile(); - let dst = self.context.new_cast(None, dst, volatile_void_ptr_type); + let dst = self.context.new_cast(self.loc, dst, volatile_void_ptr_type); // FIXME(antoyo): not sure why, but we have the wrong type here. let new_src_type = atomic_function.get_param(1).to_rvalue().get_type(); - let src = self.context.new_cast(None, src, new_src_type); - let res = self.context.new_call(None, atomic_function, &[dst, src, order]); - self.context.new_cast(None, res, src.get_type()) + let src = self.context.new_cast(self.loc, src, new_src_type); + let res = self.context.new_call(self.loc, atomic_function, &[dst, src, order]); + self.context.new_cast(self.loc, res, src.get_type()) } fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) { @@ -1374,7 +1373,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { }; let thread_fence = self.context.get_builtin_function(name); let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); - self.llbb().add_eval(None, self.context.new_call(None, thread_fence, &[order])); + self.llbb().add_eval(self.loc, self.context.new_call(self.loc, thread_fence, &[order])); } fn set_invariant_load(&mut self, load: RValue<'gcc>) { @@ -1650,7 +1649,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }; for i in 0..mask_num_units { let field = struct_type.get_field(i as i32); - vector_elements.push(self.context.new_cast(None, mask.access_field(None, field).to_rvalue(), mask_element_type)); + vector_elements.push(self.context.new_cast(self.loc, mask.access_field(self.loc, field).to_rvalue(), mask_element_type)); } // NOTE: the mask needs to be the same length as the input vectors, so add the missing @@ -1666,14 +1665,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // vectors and create a dummy second vector. let mut elements = vec![]; for i in 0..vec_num_units { - elements.push(self.context.new_vector_access(None, v1, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue()); + elements.push(self.context.new_vector_access(self.loc, v1, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue()); } for i in 0..(mask_num_units - vec_num_units) { - elements.push(self.context.new_vector_access(None, v2, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue()); + elements.push(self.context.new_vector_access(self.loc, v2, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue()); } - let v1 = self.context.new_rvalue_from_vector(None, result_type, &elements); + let v1 = self.context.new_rvalue_from_vector(self.loc, result_type, &elements); let zero = self.context.new_rvalue_zero(element_type); - let v2 = self.context.new_rvalue_from_vector(None, result_type, &vec![zero; mask_num_units]); + let v2 = self.context.new_rvalue_from_vector(self.loc, result_type, &vec![zero; mask_num_units]); (v1, v2) } else { @@ -1682,17 +1681,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let new_mask_num_units = std::cmp::max(mask_num_units, vec_num_units); let mask_type = self.context.new_vector_type(mask_element_type, new_mask_num_units as u64); - let mask = self.context.new_rvalue_from_vector(None, mask_type, &vector_elements); - let result = self.context.new_rvalue_vector_perm(None, v1, v2, mask); + let mask = self.context.new_rvalue_from_vector(self.loc, mask_type, &vector_elements); + let result = self.context.new_rvalue_vector_perm(self.loc, v1, v2, mask); if vec_num_units != mask_num_units { // NOTE: if padding was added, only select the number of elements of the masks to // remove that padding in the result. let mut elements = vec![]; for i in 0..mask_num_units { - elements.push(self.context.new_vector_access(None, result, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue()); + elements.push(self.context.new_vector_access(self.loc, result, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue()); } - self.context.new_rvalue_from_vector(None, result_type, &elements) + self.context.new_rvalue_from_vector(self.loc, result_type, &elements) } else { result @@ -1724,12 +1723,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { vector_elements.iter() .map(|i| self.context.new_rvalue_from_int(mask_element_type, ((i + shift) % element_count) as i32)) .collect(); - let mask = self.context.new_rvalue_from_vector(None, mask_type, &vector_elements); - let shifted = self.context.new_rvalue_vector_perm(None, res, res, mask); + let mask = self.context.new_rvalue_from_vector(self.loc, mask_type, &vector_elements); + let shifted = self.context.new_rvalue_vector_perm(self.loc, res, res, mask); shift *= 2; res = op(res, shifted, &self.context); } - self.context.new_vector_access(None, res, self.context.new_rvalue_zero(self.int_type)) + self.context.new_vector_access(self.loc, res, self.context.new_rvalue_zero(self.int_type)) .to_rvalue() } @@ -1741,7 +1740,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } pub fn vector_reduce_op(&mut self, src: RValue<'gcc>, op: BinaryOp) -> RValue<'gcc> { - self.vector_reduce(src, |a, b, context| context.new_binary_op(None, op, a.get_type(), a, b)) + let loc = self.loc.clone(); + self.vector_reduce(src, |a, b, context| context.new_binary_op(loc, op, a.get_type(), a, b)) } pub fn vector_reduce_fadd_fast(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> { @@ -1754,7 +1754,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let element_count = vector_type.get_num_units(); (0..element_count).into_iter() .map(|i| self.context - .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _)) + .new_vector_access(self.loc, src, self.context.new_rvalue_from_int(self.int_type, i as _)) .to_rvalue()) .fold(acc, |x, i| x + i) } @@ -1774,7 +1774,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let element_count = vector_type.get_num_units(); (0..element_count).into_iter() .map(|i| self.context - .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _)) + .new_vector_access(self.loc, src, self.context.new_rvalue_from_int(self.int_type, i as _)) .to_rvalue()) .fold(acc, |x, i| x * i) } @@ -1786,17 +1786,19 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // Inspired by Hacker's Delight min implementation. pub fn vector_reduce_min(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { + let loc = self.loc.clone(); self.vector_reduce(src, |a, b, context| { - let differences_or_zeros = difference_or_zero(a, b, context); - context.new_binary_op(None, BinaryOp::Plus, b.get_type(), b, differences_or_zeros) + let differences_or_zeros = difference_or_zero(loc, a, b, context); + context.new_binary_op(loc, BinaryOp::Plus, b.get_type(), b, differences_or_zeros) }) } // Inspired by Hacker's Delight max implementation. pub fn vector_reduce_max(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { + let loc = self.loc.clone(); self.vector_reduce(src, |a, b, context| { - let differences_or_zeros = difference_or_zero(a, b, context); - context.new_binary_op(None, BinaryOp::Minus, a.get_type(), a, differences_or_zeros) + let differences_or_zeros = difference_or_zero(loc, a, b, context); + context.new_binary_op(loc, BinaryOp::Minus, a.get_type(), a, differences_or_zeros) }) } @@ -1805,23 +1807,23 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // mask out the NaNs in b and replace them with the corresponding lane in a, so when a and // b get compared & spliced together, we get the numeric values instead of NaNs. - let b_nan_mask = self.context.new_comparison(None, ComparisonOp::NotEquals, b, b); + let b_nan_mask = self.context.new_comparison(self.loc, ComparisonOp::NotEquals, b, b); let mask_type = b_nan_mask.get_type(); - let b_nan_mask_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, mask_type, b_nan_mask); - let a_cast = self.context.new_bitcast(None, a, mask_type); - let b_cast = self.context.new_bitcast(None, b, mask_type); + let b_nan_mask_inverted = self.context.new_unary_op(self.loc, UnaryOp::BitwiseNegate, mask_type, b_nan_mask); + let a_cast = self.context.new_bitcast(self.loc, a, mask_type); + let b_cast = self.context.new_bitcast(self.loc, b, mask_type); let res = (b_nan_mask & a_cast) | (b_nan_mask_inverted & b_cast); - let b = self.context.new_bitcast(None, res, vector_type); + let b = self.context.new_bitcast(self.loc, res, vector_type); // now do the actual comparison let comparison_op = match direction { ExtremumOperation::Min => ComparisonOp::LessThan, ExtremumOperation::Max => ComparisonOp::GreaterThan, }; - let cmp = self.context.new_comparison(None, comparison_op, a, b); - let cmp_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, cmp.get_type(), cmp); + let cmp = self.context.new_comparison(self.loc, comparison_op, a, b); + let cmp_inverted = self.context.new_unary_op(self.loc, UnaryOp::BitwiseNegate, cmp.get_type(), cmp); let res = (cmp & a_cast) | (cmp_inverted & res); - self.context.new_bitcast(None, res, vector_type) + self.context.new_bitcast(self.loc, res, vector_type) } pub fn vector_fmin(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -1832,12 +1834,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn vector_reduce_fmin(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type"); let element_count = vector_type.get_num_units(); - let mut acc = self.context.new_vector_access(None, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue(); + let mut acc = self.context.new_vector_access(self.loc, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue(); for i in 1..element_count { let elem = self.context - .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _)) + .new_vector_access(self.loc, src, self.context.new_rvalue_from_int(self.int_type, i as _)) .to_rvalue(); - let cmp = self.context.new_comparison(None, ComparisonOp::LessThan, acc, elem); + let cmp = self.context.new_comparison(self.loc, ComparisonOp::LessThan, acc, elem); acc = self.select(cmp, acc, elem); } acc @@ -1856,12 +1858,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn vector_reduce_fmax(&mut self, src: RValue<'gcc>) -> RValue<'gcc> { let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type"); let element_count = vector_type.get_num_units(); - let mut acc = self.context.new_vector_access(None, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue(); + let mut acc = self.context.new_vector_access(self.loc, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue(); for i in 1..element_count { let elem = self.context - .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _)) + .new_vector_access(self.loc, src, self.context.new_rvalue_from_int(self.int_type, i as _)) .to_rvalue(); - let cmp = self.context.new_comparison(None, ComparisonOp::GreaterThan, acc, elem); + let cmp = self.context.new_comparison(self.loc, ComparisonOp::GreaterThan, acc, elem); acc = self.select(cmp, acc, elem); } acc @@ -1890,7 +1892,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if then_val_element_size != element_type.get_size() { let new_element_type = self.type_ix(then_val_element_size as u64 * 8); let new_vector_type = self.context.new_vector_type(new_element_type, num_units as u64); - let cond = self.context.convert_vector(None, cond, new_vector_type); + let cond = self.context.convert_vector(self.loc, cond, new_vector_type); (cond, new_element_type) } else { @@ -1901,24 +1903,24 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let cond_type = cond.get_type(); let zeros = vec![self.context.new_rvalue_zero(element_type); num_units]; - let zeros = self.context.new_rvalue_from_vector(None, cond_type, &zeros); + let zeros = self.context.new_rvalue_from_vector(self.loc, cond_type, &zeros); let result_type = then_val.get_type(); - let masks = self.context.new_comparison(None, ComparisonOp::NotEquals, cond, zeros); + let masks = self.context.new_comparison(self.loc, ComparisonOp::NotEquals, cond, zeros); // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make // the & operation work. let then_val = self.bitcast_if_needed(then_val, masks.get_type()); let then_vals = masks & then_val; let minus_ones = vec![self.context.new_rvalue_from_int(element_type, -1); num_units]; - let minus_ones = self.context.new_rvalue_from_vector(None, cond_type, &minus_ones); + let minus_ones = self.context.new_rvalue_from_vector(self.loc, cond_type, &minus_ones); let inverted_masks = masks ^ minus_ones; // NOTE: sometimes, the type of else_val can be different than the type of then_val in // libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND // operation to work. // TODO: remove bitcast now that vector types can be compared? - let else_val = self.context.new_bitcast(None, else_val, then_val.get_type()); + let else_val = self.context.new_bitcast(self.loc, else_val, then_val.get_type()); let else_vals = inverted_masks & else_val; let res = then_vals | else_vals; @@ -1926,15 +1928,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } } -fn difference_or_zero<'gcc>(a: RValue<'gcc>, b: RValue<'gcc>, context: &'gcc Context<'gcc>) -> RValue<'gcc> { +fn difference_or_zero<'gcc>(loc: Option>, a: RValue<'gcc>, b: RValue<'gcc>, context: &'gcc Context<'gcc>) -> RValue<'gcc> { let difference = a - b; - let masks = context.new_comparison(None, ComparisonOp::GreaterThanEquals, b, a); + let masks = context.new_comparison(loc, ComparisonOp::GreaterThanEquals, b, a); // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make // the & operation work. let a_type = a.get_type(); let masks = if masks.get_type() != a_type { - context.new_bitcast(None, masks, a_type) + context.new_bitcast(loc, masks, a_type) } else { masks @@ -1945,7 +1947,7 @@ fn difference_or_zero<'gcc>(a: RValue<'gcc>, b: RValue<'gcc>, context: &'gcc Con impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> { fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> { // Forward to the `get_static` method of `CodegenCx` - self.cx().get_static(def_id).get_address(None) + self.cx().get_static(def_id).get_address(self.loc) } } diff --git a/src/context.rs b/src/context.rs index 5760d96165ddf..9dbb3751d47b4 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,6 @@ use std::cell::{Cell, RefCell}; -use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Type}; +use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::traits::{ BackendTypes, @@ -345,7 +345,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { type Funclet = (); // TODO(antoyo) type DIScope = (); // TODO(antoyo) - type DILocation = (); // TODO(antoyo) + type DILocation = Location<'gcc>; // TODO(antoyo) type DIVariable = (); // TODO(antoyo) } diff --git a/src/debuginfo.rs b/src/debuginfo.rs index d1bfd833cd87f..e01624ce15ea3 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,41 +1,172 @@ -use gccjit::RValue; -use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind}; +use gccjit::{Location, RValue}; +use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods}; -use rustc_middle::mir; +use rustc_index::bit_set::BitSet; +use rustc_index::IndexVec; +use rustc_middle::mir::{Body, self, SourceScope}; use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; -use rustc_span::{SourceFile, Span, Symbol}; +use rustc_session::config::DebugInfo; +use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; use rustc_target::abi::call::FnAbi; use rustc_target::abi::Size; +use rustc_data_structures::sync::Lrc; +use crate::rustc_index::Idx; use std::ops::Range; use crate::builder::Builder; use crate::context::CodegenCx; +pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0; +pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0; + impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( &mut self, _dbg_var: Self::DIVariable, - _scope_metadata: Self::DIScope, - _variable_alloca: Self::Value, + dbg_loc: Self::DILocation, + variable_alloca: Self::Value, _direct_offset: Size, _indirect_offsets: &[Size], _fragment: Option>, ) { - unimplemented!(); + // Not sure if this is correct, probably wrong but still keep it here. + unsafe { + #[cfg(feature = "master")] + variable_alloca.set_location(dbg_loc); + } } fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { // TODO(antoyo): insert reference to gdb debug scripts section global. } - fn set_var_name(&mut self, _value: RValue<'gcc>, _name: &str) { - unimplemented!(); + /// Currently, this function is not yet implemented. It seems that the + /// debug name and the mangled name should both be included in the LValues. + /// Besides, a function to get the rvalue type(m_is_lvalue) should also be included. + fn set_var_name(&mut self, value: RValue<'gcc>, name: &str) { + //unimplemented!(); + } + + fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation) { + self.loc = Some(dbg_loc); + } +} + +pub fn compute_mir_scopes<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + instance: Instance<'tcx>, + mir: &Body<'tcx>, + debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>, +) { + // Find all scopes with variables defined in them. + let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { + let mut vars = BitSet::new_empty(mir.source_scopes.len()); + // FIXME(eddyb) take into account that arguments always have debuginfo, + // irrespective of their name (assuming full debuginfo is enabled). + // NOTE(eddyb) actually, on second thought, those are always in the + // function scope, which always exists. + for var_debug_info in &mir.var_debug_info { + vars.insert(var_debug_info.source_info.scope); + } + Some(vars) + } else { + // Nothing to emit, of course. + None + }; + let mut instantiated = BitSet::new_empty(mir.source_scopes.len()); + // Instantiate all scopes. + for idx in 0..mir.source_scopes.len() { + let scope = SourceScope::new(idx); + make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope); + } + assert!(instantiated.count() == mir.source_scopes.len()); +} + +fn make_mir_scope<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + instance: Instance<'tcx>, + mir: &Body<'tcx>, + variables: &Option>, + debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>, + instantiated: &mut BitSet, + scope: SourceScope, +) { + if instantiated.contains(scope) { + return; + } + + let scope_data = &mir.source_scopes[scope]; + let parent_scope = if let Some(parent) = scope_data.parent_scope { + make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent); + debug_context.scopes[parent] + } else { + // The root is the function itself. + let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); + debug_context.scopes[scope] = DebugScope { + file_start_pos: file.start_pos, + file_end_pos: file.end_position(), + ..debug_context.scopes[scope] + }; + instantiated.insert(scope); + return; + }; + + if let Some(vars) = variables + { + if !vars.contains(scope) + && scope_data.inlined.is_none() { + // Do not create a DIScope if there are no variables defined in this + // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. + debug_context.scopes[scope] = parent_scope; + instantiated.insert(scope); + return; + } } - fn set_dbg_loc(&mut self, _dbg_loc: Self::DILocation) { - unimplemented!(); + let loc = cx.lookup_debug_loc(scope_data.span.lo()); + let dbg_scope = (); + + let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { + // FIXME(eddyb) this doesn't account for the macro-related + // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. + let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); + cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) + }); + let p_inlined_at = parent_scope.inlined_at; + // TODO(tempdragon): dbg_scope: Add support for scope extension here. + inlined_at.or(p_inlined_at); + + debug_context.scopes[scope] = DebugScope { + dbg_scope, + inlined_at, + file_start_pos: loc.0.start_pos, + file_end_pos: loc.0.end_position(), + }; + instantiated.insert(scope); +} + +/// Copied from LLVM backend +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + pub fn lookup_debug_loc(&self, pos: BytePos) -> (Lrc, u32, u32) { + match self.sess().source_map().lookup_line(pos) { + Ok(SourceFileAndLine { sf: file, line }) => { + let line_pos = file.lines()[line]; + + // Use 1-based indexing. + let line = (line + 1) as u32; + let col = (file.relative_position(pos) - line_pos).to_u32() + 1; + (file, + line, + if ! self.sess().target.is_like_msvc { + col } else { + UNKNOWN_COLUMN_NUMBER + } + ) + } + Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER), + } } } @@ -51,13 +182,32 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn create_function_debug_context( &self, - _instance: Instance<'tcx>, - _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _llfn: RValue<'gcc>, - _mir: &mir::Body<'tcx>, + instance: Instance<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + llfn: RValue<'gcc>, + mir: &mir::Body<'tcx>, ) -> Option> { // TODO(antoyo) - None + if self.sess().opts.debuginfo == DebugInfo::None { + return None; + } + + // Initialize fn debug context (including scopes). + let empty_scope = DebugScope { + dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), + inlined_at: None, + file_start_pos: BytePos(0), + file_end_pos: BytePos(0), + }; + let mut fn_debug_context = FunctionDebugContext { + scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes.as_slice()), + inlined_function_scopes: Default::default(), + }; + + // Fill in all the scopes, with the information from the MIR body. + compute_mir_scopes(self, instance, mir, &mut fn_debug_context); + + Some(fn_debug_context) } fn extend_scope_to_file( @@ -65,11 +215,12 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _scope_metadata: Self::DIScope, _file: &SourceFile, ) -> Self::DIScope { - unimplemented!(); + //unimplemented!(); } fn debuginfo_finalize(&self) { - // TODO(antoyo) + // TODO(antoyo): Get the debug flag/predicate to allow optional generation of debuginfo. + self.context.set_debug_info(true) } fn create_dbg_var( @@ -80,7 +231,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _variable_kind: VariableKind, _span: Span, ) -> Self::DIVariable { - unimplemented!(); + () } fn dbg_scope_fn( @@ -89,15 +240,47 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _maybe_definition_llfn: Option>, ) -> Self::DIScope { - unimplemented!(); + //unimplemented!(); } fn dbg_loc( &self, _scope: Self::DIScope, _inlined_at: Option, - _span: Span, + span: Span, ) -> Self::DILocation { - unimplemented!(); + //unimplemented!(); + let pos = span.lo(); + let (file, line, col) = self.lookup_debug_loc(pos); + let loc = match &file.name { + rustc_span::FileName::Real(name) => match name { + rustc_span::RealFileName::LocalPath(name) => { + if let Some(name) = name.to_str() { + self.context + .new_location(name, line as i32, col as i32) + }else{ + Location::null() + } + } + rustc_span::RealFileName::Remapped { + local_path, + virtual_name, + } => if let Some(name) = local_path.as_ref() { + if let Some(name) = name.to_str(){ + self.context.new_location( + name, + line as i32, + col as i32, + ) + } else { + Location::null() + } + }else{ + Location::null() + }, + }, + _ => Location::null(), + }; + loc } } diff --git a/src/int.rs b/src/int.rs index b69e073c4d94d..b0ceacf2ffc20 100644 --- a/src/int.rs +++ b/src/int.rs @@ -195,7 +195,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let a_type = a.get_type(); let b_type = b.get_type(); if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) { - self.context.new_binary_op(None, operation, a_type, a, b) + self.context.new_binary_op(self.loc, operation, a_type, a, b) } else { debug_assert!(a_type.dyncast_array().is_some()); @@ -208,10 +208,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { "u" }; let func_name = format!("__{}{}ti3", sign, operation_name); - let param_a = self.context.new_parameter(None, a_type, "a"); - let param_b = self.context.new_parameter(None, b_type, "b"); - let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false); - self.context.new_call(None, func, &[a, b]) + let param_a = self.context.new_parameter(self.loc, a_type, "a"); + let param_b = self.context.new_parameter(self.loc, b_type, "b"); + let func = self.context.new_function(self.loc, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false); + self.context.new_call(self.loc, func, &[a, b]) } } diff --git a/src/lib.rs b/src/lib.rs index 7f0696740b374..cdb7cbebc1cc5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ extern crate rustc_errors; extern crate rustc_fluent_macro; extern crate rustc_fs_util; extern crate rustc_hir; +extern crate rustc_index; #[cfg(feature="master")] extern crate rustc_interface; extern crate rustc_macros; @@ -174,7 +175,7 @@ impl CodegenBackend for GccCodegenBackend { crate::DEFAULT_LOCALE_RESOURCE } - fn init(&self, sess: &Session) { + fn init(&self, sess: &Session) { #[cfg(feature="master")] { let target_cpu = target_cpu(sess); From 2ffe9d1eefb175addf8c14cc48dd7fcf91b2b008 Mon Sep 17 00:00:00 2001 From: tempdragon <645703113@qq.com> Date: Sat, 24 Feb 2024 19:56:29 +0800 Subject: [PATCH 198/613] feat(int.rs&build.rs): Add location info to arithmetic operators TODO: 1. Clean the unnecessary locations in builder.rs & int.rs 2. Add demangling support 3. Add debug scope support 4. Add vtable support 5. Clean up builder.rs locations --- src/builder.rs | 68 +++++++++------ src/int.rs | 204 +++++++++++++++++++++---------------------- src/intrinsic/mod.rs | 108 +++++++++++------------ 3 files changed, 199 insertions(+), 181 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index fc4c4d86a7d63..c5d3ed8c8a1f2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -26,6 +26,7 @@ use rustc_codegen_ssa::traits::{ use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::mir::Rvalue; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_span::Span; @@ -398,6 +399,16 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> { type DIVariable = as BackendTypes>::DIVariable; } +pub fn set_rval_location<'a, 'gcc, 'tcx>(bx: &mut Builder<'a,'gcc,'tcx>, r:RValue<'gcc>) -> RValue<'gcc> { + if bx.loc.is_some(){ + unsafe { + r.set_location(bx.loc.unwrap()); + } + } + r + +} + impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> { Builder::with_cx(cx, block) @@ -612,7 +623,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): this seems to produce the wrong result. return self.context.new_call(self.loc, fmodf, &[a, b]); } - else if let Some(vector_type) = a_type_unqualified.dyncast_vector() { + if let Some(vector_type) = a_type_unqualified.dyncast_vector() { assert_eq!(a_type_unqualified, b.get_type().unqualified()); let num_units = vector_type.get_num_units(); @@ -630,7 +641,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { assert_eq!(a_type_unqualified, self.cx.double_type); let fmod = self.context.get_builtin_function("fmod"); - return self.context.new_call(self.loc, fmod, &[a, b]); + self.context.new_call(self.loc, fmod, &[a, b]) } fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -652,73 +663,80 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.cx.gcc_or(a, b) + let ret = self.cx.gcc_or(a, b, self.loc); + + if self.loc.is_some() { + unsafe { ret.set_location(self.loc.unwrap()); } + } + ret } fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_xor(a, b) + set_rval_location(self,self.gcc_xor(a, b)) } fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_neg(a) + set_rval_location(self,self.gcc_neg(a)) } fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - self.cx.context.new_unary_op(self.loc, UnaryOp::Minus, a.get_type(), a) + set_rval_location(self,self.cx.context.new_unary_op(self.loc, UnaryOp::Minus, a.get_type(), a)) } fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_not(a) + set_rval_location(self,self.gcc_not(a)) } fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_add(a, b) + set_rval_location(self,self.gcc_add(a, b)) } fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_add(a, b) + set_rval_location(self,self.gcc_add(a, b)) } fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_sub(a, b) + set_rval_location(self,self.gcc_sub(a, b)) } fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // TODO(antoyo): should generate poison value? - self.gcc_sub(a, b) + set_rval_location(self,self.gcc_sub(a, b)) } fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_mul(a, b) + set_rval_location(self,self.gcc_mul(a, b)) } fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.gcc_mul(a, b) + set_rval_location(self,self.gcc_mul(a, b)) } fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. - lhs + rhs + set_rval_location(self,lhs + rhs) } fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. - lhs - rhs + set_rval_location(self,lhs - rhs) } fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. - lhs * rhs + set_rval_location(self,lhs * rhs) } fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. - lhs / rhs + set_rval_location(self,lhs / rhs) } fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. - self.frem(lhs, rhs) + let i = self.frem(lhs, rhs); + set_rval_location(self,i); + i } fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) { @@ -1005,33 +1023,33 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.gcc_float_to_uint_cast(value, dest_ty) + set_rval_location(self,self.gcc_float_to_uint_cast(value, dest_ty)) } fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.gcc_float_to_int_cast(value, dest_ty) + set_rval_location(self,self.gcc_float_to_int_cast(value, dest_ty)) } fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.gcc_uint_to_float_cast(value, dest_ty) + set_rval_location(self,self.gcc_uint_to_float_cast(value, dest_ty)) } fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.gcc_int_to_float_cast(value, dest_ty) + set_rval_location(self,self.gcc_int_to_float_cast(value, dest_ty)) } fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { // TODO(antoyo): make sure it truncates. - self.context.new_cast(self.loc, value, dest_ty) + set_rval_location(self,self.context.new_cast(self.loc, value, dest_ty)) } fn fpext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { - self.context.new_cast(self.loc, value, dest_ty) + set_rval_location(self,self.context.new_cast(self.loc, value, dest_ty)) } fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { let usize_value = self.cx.const_bitcast(value, self.cx.type_isize()); - self.intcast(usize_value, dest_ty, false) + self.intcast(usize_value, dest_ty, false) } fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { diff --git a/src/int.rs b/src/int.rs index b0ceacf2ffc20..fe38d89ff8c3c 100644 --- a/src/int.rs +++ b/src/int.rs @@ -4,7 +4,7 @@ use std::convert::TryFrom; -use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp}; +use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp}; use rustc_middle::ty::{ParamEnv, Ty}; @@ -35,13 +35,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { else { UnaryOp::BitwiseNegate }; - self.cx.context.new_unary_op(None, operation, typ, a) + self.cx.context.new_unary_op(self.loc, operation, typ, a) } else { let element_type = typ.dyncast_array().expect("element type"); self.from_low_high_rvalues(typ, - self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)), - self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)), + self.cx.context.new_unary_op(self.loc, UnaryOp::BitwiseNegate, element_type, self.low(a)), + self.cx.context.new_unary_op(self.loc, UnaryOp::BitwiseNegate, element_type, self.high(a)), ) } } @@ -49,7 +49,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn gcc_neg(&self, a: RValue<'gcc>) -> RValue<'gcc> { let a_type = a.get_type(); if self.is_native_int_type(a_type) || a_type.is_vector() { - self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) + self.cx.context.new_unary_op(self.loc, UnaryOp::Minus, a.get_type(), a) } else { self.gcc_add(self.gcc_not(a), self.gcc_int(a_type, 1)) @@ -57,7 +57,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } pub fn gcc_and(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b) + self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b, self.loc) } pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -69,7 +69,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by a signed number. // TODO(antoyo): cast to unsigned to do a logical shift if that does not work. if a_type.is_signed(self) != b_type.is_signed(self) { - let b = self.context.new_cast(None, b, a_type); + let b = self.context.new_cast(self.loc, b, a_type); a >> b } else { @@ -95,14 +95,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let b0_block = func.new_block("b0"); let actual_else_block = func.new_block("actual_else"); - let result = func.new_local(None, a_type, "shiftResult"); + let result = func.new_local(self.loc, a_type, "shiftResult"); let sixty_four = self.gcc_int(native_int_type, 64); let sixty_three = self.gcc_int(native_int_type, 63); let zero = self.gcc_zero(native_int_type); let b = self.gcc_int_cast(b, native_int_type); let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero); - self.llbb().end_with_conditional(None, condition, then_block, else_block); + self.llbb().end_with_conditional(self.loc, condition, then_block, else_block); let shift_value = self.gcc_sub(b, sixty_four); let high = self.high(a); @@ -114,27 +114,27 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { zero }; let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign); - then_block.add_assignment(None, result, array_value); - then_block.end_with_jump(None, after_block); + then_block.add_assignment(self.loc, result, array_value); + then_block.end_with_jump(self.loc, after_block); let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero); - else_block.end_with_conditional(None, condition, b0_block, actual_else_block); + else_block.end_with_conditional(self.loc, condition, b0_block, actual_else_block); - b0_block.add_assignment(None, result, a); - b0_block.end_with_jump(None, after_block); + b0_block.add_assignment(self.loc, result, a); + b0_block.end_with_jump(self.loc, after_block); let shift_value = self.gcc_sub(sixty_four, b); // NOTE: cast low to its unsigned type in order to perform a logical right shift. let unsigned_type = native_int_type.to_unsigned(&self.cx); - let casted_low = self.context.new_cast(None, self.low(a), unsigned_type); - let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type); - let shifted_low = self.context.new_cast(None, shifted_low, native_int_type); + let casted_low = self.context.new_cast(self.loc, self.low(a), unsigned_type); + let shifted_low = casted_low >> self.context.new_cast(self.loc, b, unsigned_type); + let shifted_low = self.context.new_cast(self.loc, shifted_low, native_int_type); let array_value = self.from_low_high_rvalues(a_type, (high << shift_value) | shifted_low, high >> b, ); - actual_else_block.add_assignment(None, result, array_value); - actual_else_block.end_with_jump(None, after_block); + actual_else_block.add_assignment(self.loc, result, array_value); + actual_else_block.end_with_jump(self.loc, after_block); // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. @@ -152,13 +152,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if a_type.is_vector() { // Vector types need to be bitcast. // TODO(antoyo): perhaps use __builtin_convertvector for vector casting. - b = self.context.new_bitcast(None, b, a.get_type()); + b = self.context.new_bitcast(self.loc, b, a.get_type()); } else { - b = self.context.new_cast(None, b, a.get_type()); + b = self.context.new_cast(self.loc, b, a.get_type()); } } - self.context.new_binary_op(None, operation, a_type, a, b) + self.context.new_binary_op(self.loc, operation, a_type, a, b) } else { debug_assert!(a_type.dyncast_array().is_some()); @@ -172,10 +172,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { (BinaryOp::Minus, false) => "__rust_u128_sub", _ => unreachable!("unexpected additive operation {:?}", operation), }; - let param_a = self.context.new_parameter(None, a_type, "a"); - let param_b = self.context.new_parameter(None, b_type, "b"); - let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false); - self.context.new_call(None, func, &[a, b]) + let param_a = self.context.new_parameter(self.loc, a_type, "a"); + let param_b = self.context.new_parameter(self.loc, b_type, "b"); + let func = self.context.new_function(self.loc, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false); + self.context.new_call(self.loc, func, &[a, b]) } } @@ -335,10 +335,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let intrinsic = self.context.get_builtin_function(&name); let res = self.current_func() // TODO(antoyo): is it correct to use rhs type instead of the parameter typ? - .new_local(None, rhs.get_type(), "binopResult") - .get_address(None); + .new_local(self.loc, rhs.get_type(), "binopResult") + .get_address(self.loc); let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None); - (res.dereference(None).to_rvalue(), overflow) + (res.dereference(self.loc).to_rvalue(), overflow) } pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { @@ -346,10 +346,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let b_type = rhs.get_type(); debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); - let param_a = self.context.new_parameter(None, a_type, "a"); - let param_b = self.context.new_parameter(None, b_type, "b"); - let result_field = self.context.new_field(None, a_type, "result"); - let overflow_field = self.context.new_field(None, self.bool_type, "overflow"); + let param_a = self.context.new_parameter(self.loc, a_type, "a"); + let param_b = self.context.new_parameter(self.loc, b_type, "b"); + let result_field = self.context.new_field(self.loc, a_type, "result"); + let overflow_field = self.context.new_field(self.loc, self.bool_type, "overflow"); let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]); let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap(); @@ -372,23 +372,23 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); - let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]); + let return_type = self.context.new_struct_type(self.loc, "result_overflow", &[result_field, overflow_field]); let result = if indirect { - let return_value = self.current_func().new_local(None, return_type.as_type(), "return_value"); + let return_value = self.current_func().new_local(self.loc, return_type.as_type(), "return_value"); let return_param_type = return_type.as_type().make_pointer(); - let return_param = self.context.new_parameter(None, return_param_type, "return_value"); - let func = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[return_param, param_a, param_b], func_name, false); - self.llbb().add_eval(None, self.context.new_call(None, func, &[return_value.get_address(None), lhs, rhs])); + let return_param = self.context.new_parameter(self.loc, return_param_type, "return_value"); + let func = self.context.new_function(self.loc, FunctionType::Extern, self.type_void(), &[return_param, param_a, param_b], func_name, false); + self.llbb().add_eval(self.loc, self.context.new_call(self.loc, func, &[return_value.get_address(self.loc), lhs, rhs])); return_value.to_rvalue() } else { - let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false); - self.context.new_call(None, func, &[lhs, rhs]) + let func = self.context.new_function(self.loc, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false); + self.context.new_call(self.loc, func, &[lhs, rhs]) }; - let overflow = result.access_field(None, overflow_field); - let int_result = result.access_field(None, result_field); - return (int_result, overflow); + let overflow = result.access_field(self.loc, overflow_field); + let int_result = result.access_field(self.loc, result_field); + (int_result, overflow) } pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> { @@ -397,7 +397,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { // This algorithm is based on compiler-rt's __cmpti2: // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21 - let result = self.current_func().new_local(None, self.int_type, "icmp_result"); + let result = self.current_func().new_local(self.loc, self.int_type, "icmp_result"); let block1 = self.current_func().new_block("block1"); let block2 = self.current_func().new_block("block2"); let block3 = self.current_func().new_block("block3"); @@ -413,35 +413,35 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // the sign is only on high). let unsigned_type = native_int_type.to_unsigned(&self.cx); - let lhs_low = self.context.new_cast(None, self.low(lhs), unsigned_type); - let rhs_low = self.context.new_cast(None, self.low(rhs), unsigned_type); + let lhs_low = self.context.new_cast(self.loc, self.low(lhs), unsigned_type); + let rhs_low = self.context.new_cast(self.loc, self.low(rhs), unsigned_type); - let condition = self.context.new_comparison(None, ComparisonOp::LessThan, self.high(lhs), self.high(rhs)); - self.llbb().end_with_conditional(None, condition, block1, block2); + let condition = self.context.new_comparison(self.loc, ComparisonOp::LessThan, self.high(lhs), self.high(rhs)); + self.llbb().end_with_conditional(self.loc, condition, block1, block2); - block1.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type)); - block1.end_with_jump(None, after); + block1.add_assignment(self.loc, result, self.context.new_rvalue_zero(self.int_type)); + block1.end_with_jump(self.loc, after); - let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs)); - block2.end_with_conditional(None, condition, block3, block4); + let condition = self.context.new_comparison(self.loc, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs)); + block2.end_with_conditional(self.loc, condition, block3, block4); - block3.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2)); - block3.end_with_jump(None, after); + block3.add_assignment(self.loc, result, self.context.new_rvalue_from_int(self.int_type, 2)); + block3.end_with_jump(self.loc, after); - let condition = self.context.new_comparison(None, ComparisonOp::LessThan, lhs_low, rhs_low); - block4.end_with_conditional(None, condition, block5, block6); + let condition = self.context.new_comparison(self.loc, ComparisonOp::LessThan, lhs_low, rhs_low); + block4.end_with_conditional(self.loc, condition, block5, block6); - block5.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type)); - block5.end_with_jump(None, after); + block5.add_assignment(self.loc, result, self.context.new_rvalue_zero(self.int_type)); + block5.end_with_jump(self.loc, after); - let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, lhs_low, rhs_low); - block6.end_with_conditional(None, condition, block7, block8); + let condition = self.context.new_comparison(self.loc, ComparisonOp::GreaterThan, lhs_low, rhs_low); + block6.end_with_conditional(self.loc, condition, block7, block8); - block7.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2)); - block7.end_with_jump(None, after); + block7.add_assignment(self.loc, result, self.context.new_rvalue_from_int(self.int_type, 2)); + block7.end_with_jump(self.loc, after); - block8.add_assignment(None, result, self.context.new_rvalue_one(self.int_type)); - block8.end_with_jump(None, after); + block8.add_assignment(self.loc, result, self.context.new_rvalue_one(self.int_type)); + block8.end_with_jump(self.loc, after); // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. @@ -451,10 +451,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let (op, limit) = match op { IntPredicate::IntEQ => { - return self.context.new_comparison(None, ComparisonOp::Equals, cmp, self.context.new_rvalue_one(self.int_type)); + return self.context.new_comparison(self.loc, ComparisonOp::Equals, cmp, self.context.new_rvalue_one(self.int_type)); }, IntPredicate::IntNE => { - return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type)); + return self.context.new_comparison(self.loc, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type)); }, // TODO(antoyo): cast to u128 for unsigned comparison. See below. IntPredicate::IntUGT => (ComparisonOp::Equals, 2), @@ -466,39 +466,39 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { IntPredicate::IntSLT => (ComparisonOp::Equals, 0), IntPredicate::IntSLE => (ComparisonOp::LessThanEquals, 1), }; - self.context.new_comparison(None, op, cmp, self.context.new_rvalue_from_int(self.int_type, limit)) + self.context.new_comparison(self.loc, op, cmp, self.context.new_rvalue_from_int(self.int_type, limit)) } else if a_type.get_pointee().is_some() && b_type.get_pointee().is_some() { // NOTE: gcc cannot compare pointers to different objects, but rustc does that, so cast them to usize. - lhs = self.context.new_bitcast(None, lhs, self.usize_type); - rhs = self.context.new_bitcast(None, rhs, self.usize_type); - self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + lhs = self.context.new_bitcast(self.loc, lhs, self.usize_type); + rhs = self.context.new_bitcast(self.loc, rhs, self.usize_type); + self.context.new_comparison(self.loc, op.to_gcc_comparison(), lhs, rhs) } else { if a_type != b_type { // NOTE: because libgccjit cannot compare function pointers. if a_type.dyncast_function_ptr_type().is_some() && b_type.dyncast_function_ptr_type().is_some() { - lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); - rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); + lhs = self.context.new_cast(self.loc, lhs, self.usize_type.make_pointer()); + rhs = self.context.new_cast(self.loc, rhs, self.usize_type.make_pointer()); } // NOTE: hack because we try to cast a vector type to the same vector type. else if format!("{:?}", a_type) != format!("{:?}", b_type) { - rhs = self.context.new_cast(None, rhs, a_type); + rhs = self.context.new_cast(self.loc, rhs, a_type); } } match op { IntPredicate::IntUGT | IntPredicate::IntUGE | IntPredicate::IntULT | IntPredicate::IntULE => { if !a_type.is_vector() { let unsigned_type = a_type.to_unsigned(&self.cx); - lhs = self.context.new_cast(None, lhs, unsigned_type); - rhs = self.context.new_cast(None, rhs, unsigned_type); + lhs = self.context.new_cast(self.loc, lhs, unsigned_type); + rhs = self.context.new_cast(self.loc, rhs, unsigned_type); } }, // TODO(antoyo): we probably need to handle signed comparison for unsigned // integers. _ => (), } - self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs) + self.context.new_comparison(self.loc, op.to_gcc_comparison(), lhs, rhs) } } @@ -528,12 +528,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if a_native && b_native { // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number. if a_type.is_unsigned(self) && b_type.is_signed(self) { - let a = self.context.new_cast(None, a, b_type); + let a = self.context.new_cast(self.loc, a, b_type); let result = a << b; - self.context.new_cast(None, result, a_type) + self.context.new_cast(self.loc, result, a_type) } else if a_type.is_signed(self) && b_type.is_unsigned(self) { - let b = self.context.new_cast(None, b, a_type); + let b = self.context.new_cast(self.loc, b, a_type); a << b } else { @@ -557,40 +557,40 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let b0_block = func.new_block("b0"); let actual_else_block = func.new_block("actual_else"); - let result = func.new_local(None, a_type, "shiftResult"); + let result = func.new_local(self.loc, a_type, "shiftResult"); let b = self.gcc_int_cast(b, native_int_type); let sixty_four = self.gcc_int(native_int_type, 64); let zero = self.gcc_zero(native_int_type); let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero); - self.llbb().end_with_conditional(None, condition, then_block, else_block); + self.llbb().end_with_conditional(self.loc, condition, then_block, else_block); let array_value = self.from_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four), ); - then_block.add_assignment(None, result, array_value); - then_block.end_with_jump(None, after_block); + then_block.add_assignment(self.loc, result, array_value); + then_block.end_with_jump(self.loc, after_block); let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero); - else_block.end_with_conditional(None, condition, b0_block, actual_else_block); + else_block.end_with_conditional(self.loc, condition, b0_block, actual_else_block); - b0_block.add_assignment(None, result, a); - b0_block.end_with_jump(None, after_block); + b0_block.add_assignment(self.loc, result, a); + b0_block.end_with_jump(self.loc, after_block); // NOTE: cast low to its unsigned type in order to perform a logical right shift. // TODO(antoyo): adjust this ^ comment. let unsigned_type = native_int_type.to_unsigned(&self.cx); - let casted_low = self.context.new_cast(None, self.low(a), unsigned_type); - let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type); - let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type); + let casted_low = self.context.new_cast(self.loc, self.low(a), unsigned_type); + let shift_value = self.context.new_cast(self.loc, sixty_four - b, unsigned_type); + let high_low = self.context.new_cast(self.loc, casted_low >> shift_value, native_int_type); let array_value = self.from_low_high_rvalues(a_type, self.low(a) << b, (self.high(a) << b) | high_low, ); - actual_else_block.add_assignment(None, result, array_value); - actual_else_block.end_with_jump(None, after_block); + actual_else_block.add_assignment(self.loc, result, array_value); + actual_else_block.end_with_jump(self.loc, after_block); // NOTE: since jumps were added in a place rustc does not expect, the current block in the // state need to be updated. @@ -606,10 +606,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let native_int_type = arg_type.dyncast_array().expect("get element type"); let lsb = self.low(arg); let swapped_lsb = self.gcc_bswap(lsb, width / 2); - let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type); + let swapped_lsb = self.context.new_cast(self.loc, swapped_lsb, native_int_type); let msb = self.high(arg); let swapped_msb = self.gcc_bswap(msb, width / 2); - let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type); + let swapped_msb = self.context.new_cast(self.loc, swapped_msb, native_int_type); // NOTE: we also need to swap the two elements here, in addition to swapping inside // the elements themselves like done above. @@ -625,7 +625,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if param_type != arg_type { arg = self.bitcast(arg, param_type); } - self.cx.context.new_call(None, bswap, &[arg]) + self.cx.context.new_call(self.loc, bswap, &[arg]) } } @@ -700,33 +700,33 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } - fn bitwise_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + fn bitwise_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>, loc: Option>) -> RValue<'gcc> { let a_type = a.get_type(); let b_type = b.get_type(); let a_native = self.is_native_int_type_or_bool(a_type); let b_native = self.is_native_int_type_or_bool(b_type); if a_type.is_vector() && b_type.is_vector() { let b = self.bitcast_if_needed(b, a_type); - self.context.new_binary_op(None, operation, a_type, a, b) + self.context.new_binary_op(loc, operation, a_type, a, b) } else if a_native && b_native { if a_type != b_type { - b = self.context.new_cast(None, b, a_type); + b = self.context.new_cast(loc, b, a_type); } - self.context.new_binary_op(None, operation, a_type, a, b) + self.context.new_binary_op(loc, operation, a_type, a, b) } else { assert!(!a_native && !b_native, "both types should either be native or non-native for or operation"); let native_int_type = a_type.dyncast_array().expect("get element type"); self.from_low_high_rvalues(a_type, - self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)), - self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)), + self.context.new_binary_op(loc, operation, native_int_type, self.low(a), self.low(b)), + self.context.new_binary_op(loc, operation, native_int_type, self.high(a), self.high(b)), ) } } - pub fn gcc_or(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - self.bitwise_operation(BinaryOp::BitwiseOr, a, b) + pub fn gcc_or(&self, a: RValue<'gcc>, b: RValue<'gcc>, loc: Option>) -> RValue<'gcc> { + self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } // TODO(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f162ef831b768..0849c6266f19b 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -640,7 +640,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let new_low = self.gcc_int_cast(reversed_high, typ); let new_high = self.shl(self.gcc_int_cast(reversed_low, typ), sixty_four); - self.gcc_or(new_low, new_high) + self.gcc_or(new_low, new_high, self.loc) }, _ => { panic!("cannot bit reverse with width = {}", width); @@ -685,44 +685,44 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let first_elem = self.context.new_array_access(None, result, zero); let first_value = self.gcc_int_cast(self.context.new_call(None, clzll, &[high]), arg_type); self.llbb() - .add_assignment(None, first_elem, first_value); + .add_assignment(self.loc, first_elem, first_value); - let second_elem = self.context.new_array_access(None, result, one); - let cast = self.gcc_int_cast(self.context.new_call(None, clzll, &[low]), arg_type); + let second_elem = self.context.new_array_access(self.loc, result, one); + let cast = self.gcc_int_cast(self.context.new_call(self.loc, clzll, &[low]), arg_type); let second_value = self.add(cast, sixty_four); self.llbb() - .add_assignment(None, second_elem, second_value); + .add_assignment(self.loc, second_elem, second_value); - let third_elem = self.context.new_array_access(None, result, two); + let third_elem = self.context.new_array_access(self.loc, result, two); let third_value = self.const_uint(arg_type, 128); self.llbb() - .add_assignment(None, third_elem, third_value); + .add_assignment(self.loc, third_elem, third_value); - let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); - let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); + let not_high = self.context.new_unary_op(self.loc, UnaryOp::LogicalNegate, self.u64_type, high); + let not_low = self.context.new_unary_op(self.loc, UnaryOp::LogicalNegate, self.u64_type, low); let not_low_and_not_high = not_low & not_high; let index = not_high + not_low_and_not_high; // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in // gcc. // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the // compilation stage. - let index = self.context.new_cast(None, index, self.i32_type); + let index = self.context.new_cast(self.loc, index, self.i32_type); - let res = self.context.new_array_access(None, result, index); + let res = self.context.new_array_access(self.loc, result, index); return self.gcc_int_cast(res.to_rvalue(), arg_type); } else { let count_leading_zeroes = self.context.get_builtin_function("__builtin_clzll"); - let arg = self.context.new_cast(None, arg, self.ulonglong_type); + let arg = self.context.new_cast(self.loc, arg, self.ulonglong_type); let diff = self.ulonglong_type.get_size() as i64 - arg_type.get_size() as i64; let diff = self.context.new_rvalue_from_long(self.int_type, diff * 8); - let res = self.context.new_call(None, count_leading_zeroes, &[arg]) - diff; - return self.context.new_cast(None, res, arg_type); + let res = self.context.new_call(self.loc, count_leading_zeroes, &[arg]) - diff; + return self.context.new_cast(self.loc, res, arg_type); }; let count_leading_zeroes = self.context.get_builtin_function(count_leading_zeroes); - let res = self.context.new_call(None, count_leading_zeroes, &[arg]); - self.context.new_cast(None, res, arg_type) + let res = self.context.new_call(self.loc, count_leading_zeroes, &[arg]); + self.context.new_cast(self.loc, res, arg_type) } fn count_trailing_zeroes(&mut self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { @@ -766,58 +766,58 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let ctzll = self.context.get_builtin_function("__builtin_ctzll"); - let first_elem = self.context.new_array_access(None, result, zero); - let first_value = self.gcc_int_cast(self.context.new_call(None, ctzll, &[low]), arg_type); + let first_elem = self.context.new_array_access(self.loc, result, zero); + let first_value = self.gcc_int_cast(self.context.new_call(self.loc, ctzll, &[low]), arg_type); self.llbb() - .add_assignment(None, first_elem, first_value); + .add_assignment(self.loc, first_elem, first_value); - let second_elem = self.context.new_array_access(None, result, one); - let second_value = self.gcc_add(self.gcc_int_cast(self.context.new_call(None, ctzll, &[high]), arg_type), sixty_four); + let second_elem = self.context.new_array_access(self.loc, result, one); + let second_value = self.gcc_add(self.gcc_int_cast(self.context.new_call(self.loc, ctzll, &[high]), arg_type), sixty_four); self.llbb() - .add_assignment(None, second_elem, second_value); + .add_assignment(self.loc, second_elem, second_value); - let third_elem = self.context.new_array_access(None, result, two); + let third_elem = self.context.new_array_access(self.loc, result, two); let third_value = self.gcc_int(arg_type, 128); self.llbb() - .add_assignment(None, third_elem, third_value); + .add_assignment(self.loc, third_elem, third_value); - let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); - let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); + let not_low = self.context.new_unary_op(self.loc, UnaryOp::LogicalNegate, self.u64_type, low); + let not_high = self.context.new_unary_op(self.loc, UnaryOp::LogicalNegate, self.u64_type, high); let not_low_and_not_high = not_low & not_high; let index = not_low + not_low_and_not_high; // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in // gcc. // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the // compilation stage. - let index = self.context.new_cast(None, index, self.i32_type); + let index = self.context.new_cast(self.loc, index, self.i32_type); - let res = self.context.new_array_access(None, result, index); + let res = self.context.new_array_access(self.loc, result, index); return self.gcc_int_cast(res.to_rvalue(), result_type); } else { let count_trailing_zeroes = self.context.get_builtin_function("__builtin_ctzll"); let arg_size = arg_type.get_size(); - let casted_arg = self.context.new_cast(None, arg, self.ulonglong_type); + let casted_arg = self.context.new_cast(self.loc, arg, self.ulonglong_type); let byte_diff = self.ulonglong_type.get_size() as i64 - arg_size as i64; let diff = self.context.new_rvalue_from_long(self.int_type, byte_diff * 8); let mask = self.context.new_rvalue_from_long(arg_type, -1); // To get the value with all bits set. - let masked = mask & self.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, arg); - let cond = self.context.new_comparison(None, ComparisonOp::Equals, masked, mask); - let diff = diff * self.context.new_cast(None, cond, self.int_type); - let res = self.context.new_call(None, count_trailing_zeroes, &[casted_arg]) - diff; - return self.context.new_cast(None, res, result_type); + let masked = mask & self.context.new_unary_op(self.loc, UnaryOp::BitwiseNegate, arg_type, arg); + let cond = self.context.new_comparison(self.loc, ComparisonOp::Equals, masked, mask); + let diff = diff * self.context.new_cast(self.loc, cond, self.int_type); + let res = self.context.new_call(self.loc, count_trailing_zeroes, &[casted_arg]) - diff; + return self.context.new_cast(self.loc, res, result_type); }; let count_trailing_zeroes = self.context.get_builtin_function(count_trailing_zeroes); let arg = if arg_type != expected_type { - self.context.new_cast(None, arg, expected_type) + self.context.new_cast(self.loc, arg, expected_type) } else { arg }; - let res = self.context.new_call(None, count_trailing_zeroes, &[arg]); - self.context.new_cast(None, res, result_type) + let res = self.context.new_call(self.loc, count_trailing_zeroes, &[arg]); + self.context.new_cast(self.loc, res, result_type) } fn pop_count(&mut self, value: RValue<'gcc>) -> RValue<'gcc> { @@ -859,8 +859,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let counter = self.current_func().new_local(None, counter_type, "popcount_counter"); let val = self.current_func().new_local(None, value_type, "popcount_value"); let zero = self.gcc_zero(counter_type); - self.llbb().add_assignment(None, counter, zero); - self.llbb().add_assignment(None, val, value); + self.llbb().add_assignment(self.loc, counter, zero); + self.llbb().add_assignment(self.loc, val, value); self.br(loop_head); // check if value isn't zero @@ -874,12 +874,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let one = self.gcc_int(value_type, 1); let sub = self.gcc_sub(val.to_rvalue(), one); let op = self.gcc_and(val.to_rvalue(), sub); - loop_body.add_assignment(None, val, op); + loop_body.add_assignment(self.loc, val, op); // counter += 1 let one = self.gcc_int(counter_type, 1); let op = self.gcc_add(counter.to_rvalue(), one); - loop_body.add_assignment(None, counter, op); + loop_body.add_assignment(self.loc, counter, op); self.br(loop_head); // end of loop @@ -922,7 +922,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if signed { // Based on algorithm from: https://stackoverflow.com/a/56531252/389119 let func = self.current_func.borrow().expect("func"); - let res = func.new_local(None, result_type, "saturating_sum"); + let res = func.new_local(self.loc, result_type, "saturating_sum"); let supports_native_type = self.is_native_int_type(result_type); let overflow = if supports_native_type { @@ -936,7 +936,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => unreachable!(), }; let overflow_func = self.context.get_builtin_function(func_name); - self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None) + self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(self.loc)], None) } else { let func_name = @@ -945,7 +945,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => unreachable!(), }; let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs); - self.llbb().add_assignment(None, res, int_result); + self.llbb().add_assignment(self.loc, res, int_result); overflow }; @@ -958,10 +958,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1)); let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0)); let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1)); - then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type)); - then_block.end_with_jump(None, after_block); + then_block.add_assignment(self.loc, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type)); + then_block.end_with_jump(self.loc, after_block); - self.llbb().end_with_conditional(None, overflow, then_block, after_block); + self.llbb().end_with_conditional(self.loc, overflow, then_block, after_block); // NOTE: since jumps were added in a place rustc does not // expect, the current block in the state need to be updated. @@ -974,7 +974,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let res = self.gcc_add(lhs, rhs); let cond = self.gcc_icmp(IntPredicate::IntULT, res, lhs); let value = self.gcc_neg(self.gcc_int_cast(cond, result_type)); - self.gcc_or(res, value) + self.gcc_or(res, value, self.loc) } } @@ -984,7 +984,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if signed { // Based on algorithm from: https://stackoverflow.com/a/56531252/389119 let func = self.current_func.borrow().expect("func"); - let res = func.new_local(None, result_type, "saturating_diff"); + let res = func.new_local(self.loc, result_type, "saturating_diff"); let supports_native_type = self.is_native_int_type(result_type); let overflow = if supports_native_type { @@ -998,7 +998,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => unreachable!(), }; let overflow_func = self.context.get_builtin_function(func_name); - self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None) + self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(self.loc)], None) } else { let func_name = @@ -1007,7 +1007,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => unreachable!(), }; let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs); - self.llbb().add_assignment(None, res, int_result); + self.llbb().add_assignment(self.loc, res, int_result); overflow }; @@ -1020,10 +1020,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1)); let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0)); let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1)); - then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type)); - then_block.end_with_jump(None, after_block); + then_block.add_assignment(self.loc, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type)); + then_block.end_with_jump(self.loc, after_block); - self.llbb().end_with_conditional(None, overflow, then_block, after_block); + self.llbb().end_with_conditional(self.loc, overflow, then_block, after_block); // NOTE: since jumps were added in a place rustc does not // expect, the current block in the state need to be updated. From 93fa8579c6430d54525e1905eafff4dbcf9b31b0 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 25 Dec 2023 20:53:01 +0000 Subject: [PATCH 199/613] Add asm label support to AST and HIR --- compiler/rustc_ast/src/ast.rs | 5 +- compiler/rustc_ast/src/mut_visit.rs | 1 + compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_lowering/messages.ftl | 3 + compiler/rustc_ast_lowering/src/asm.rs | 27 +++++++-- compiler/rustc_ast_lowering/src/errors.rs | 10 ++++ compiler/rustc_ast_pretty/src/pprust/state.rs | 4 ++ compiler/rustc_builtin_macros/src/asm.rs | 3 + compiler/rustc_codegen_ssa/src/mono_item.rs | 3 +- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir/src/hir.rs | 14 ++++- compiler/rustc_hir/src/intravisit.rs | 1 + .../src/check/intrinsicck.rs | 2 + compiler/rustc_hir_pretty/src/lib.rs | 4 ++ compiler/rustc_hir_typeck/src/expr.rs | 3 + .../rustc_hir_typeck/src/expr_use_visitor.rs | 3 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 + compiler/rustc_monomorphize/src/collector.rs | 3 +- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_passes/src/liveness.rs | 59 +++++++++++++++---- compiler/rustc_passes/src/naked_functions.rs | 3 +- compiler/rustc_resolve/src/late.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + .../clippy_lints/src/loops/never_loop.rs | 3 + .../clippy/clippy_utils/src/hir_utils.rs | 1 + 25 files changed, 142 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3fdb2a2225a58..d0287af9cd33c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2294,6 +2294,9 @@ pub enum InlineAsmOperand { Sym { sym: InlineAsmSym, }, + Label { + block: P, + }, } impl InlineAsmOperand { @@ -2303,7 +2306,7 @@ impl InlineAsmOperand { | Self::Out { reg, .. } | Self::InOut { reg, .. } | Self::SplitInOut { reg, .. } => Some(reg), - Self::Const { .. } | Self::Sym { .. } => None, + Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None, } } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c42c41999732c..c2eddef9fb7f4 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1330,6 +1330,7 @@ pub fn noop_visit_inline_asm(asm: &mut InlineAsm, vis: &mut T) { } InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const), InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym), + InlineAsmOperand::Label { block } => vis.visit_block(block), } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ecf379cc2408a..7fbfe4d97c059 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -885,6 +885,7 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) try_visit!(visitor.visit_anon_const(anon_const)) } InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), + InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), } } V::Result::output() diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index e87cf05713cd3..d91d65497e1c1 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -88,6 +88,9 @@ ast_lowering_invalid_abi_suggestion = did you mean ast_lowering_invalid_asm_template_modifier_const = asm template modifiers are not allowed for `const` arguments +ast_lowering_invalid_asm_template_modifier_label = + asm template modifiers are not allowed for `label` arguments + ast_lowering_invalid_asm_template_modifier_reg_class = invalid asm template modifier for this register class diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index fd717e82d26df..f91183e2cbf2e 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -3,9 +3,9 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringE use super::errors::{ AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported, InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst, - InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub, - InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber, - RegisterConflict, + InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass, + InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister, + InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict, }; use super::LoweringContext; @@ -236,6 +236,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } + InlineAsmOperand::Label { block } => { + if !self.tcx.features().asm_goto { + feature_err( + sess, + sym::asm_goto, + *op_sp, + "label operands for inline assembly are unstable", + ) + .emit(); + } + hir::InlineAsmOperand::Label { block: self.lower_block(block, false) } + } }; (op, self.lower_span(*op_sp)) }) @@ -295,6 +307,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { op_span: op_sp, }); } + hir::InlineAsmOperand::Label { .. } => { + self.dcx().emit_err(InvalidAsmTemplateModifierLabel { + placeholder_span, + op_span: op_sp, + }); + } } } } @@ -334,7 +352,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } - | hir::InlineAsmOperand::SymStatic { .. } => { + | hir::InlineAsmOperand::SymStatic { .. } + | hir::InlineAsmOperand::Label { .. } => { unreachable!("{op:?} is not a register operand"); } }; diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 834409da6750a..76659216d870e 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -262,6 +262,16 @@ pub struct InvalidAsmTemplateModifierSym { pub op_span: Span, } +#[derive(Diagnostic, Clone, Copy)] +#[diag(ast_lowering_invalid_asm_template_modifier_label)] +pub struct InvalidAsmTemplateModifierLabel { + #[primary_span] + #[label(ast_lowering_template_modifier)] + pub placeholder_span: Span, + #[label(ast_lowering_argument)] + pub op_span: Span, +} + #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_register_class_only_clobber)] pub struct RegisterClassOnlyClobber { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7ea0078ea3bb9..8d64ecb24309a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1331,6 +1331,10 @@ impl<'a> State<'a> { s.print_path(&sym.path, true, 0); } } + InlineAsmOperand::Label { block } => { + s.head("label"); + s.print_block(block); + } } } AsmArg::ClobberAbi(abi) => { diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index c5a73c3199579..93eb3a9a43ee3 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -166,6 +166,9 @@ pub fn parse_asm_args<'a>( path: path.clone(), }; ast::InlineAsmOperand::Sym { sym } + } else if !is_global_asm && p.eat_keyword(sym::label) { + let block = p.parse_block()?; + ast::InlineAsmOperand::Label { block } } else if allow_templates { let template = p.parse_expr()?; // If it can't possibly expand to a string, provide diagnostics here to include other diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 295e27691090c..1a4795c0213a1 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -76,7 +76,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Out { .. } | hir::InlineAsmOperand::InOut { .. } - | hir::InlineAsmOperand::SplitInOut { .. } => { + | hir::InlineAsmOperand::SplitInOut { .. } + | hir::InlineAsmOperand::Label { .. } => { span_bug!(*op_sp, "invalid operand type for global_asm!") } }) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 93c183a65ef3e..74ec6a9713f3c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -345,6 +345,8 @@ declare_features! ( (unstable, asm_const, "1.58.0", Some(93332)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), + /// Allows using `label` operands in inline assembly. + (unstable, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)), /// Allows the `may_unwind` option in inline assembly. (unstable, asm_unwind, "1.58.0", Some(93334)), /// Allows users to enforce equality of associated constants `TraitImpl`. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 78e7c636a3e74..2b8cd47bd1fe0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2645,6 +2645,9 @@ pub enum InlineAsmOperand<'hir> { path: QPath<'hir>, def_id: DefId, }, + Label { + block: &'hir Block<'hir>, + }, } impl<'hir> InlineAsmOperand<'hir> { @@ -2654,7 +2657,10 @@ impl<'hir> InlineAsmOperand<'hir> { | Self::Out { reg, .. } | Self::InOut { reg, .. } | Self::SplitInOut { reg, .. } => Some(reg), - Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None, + Self::Const { .. } + | Self::SymFn { .. } + | Self::SymStatic { .. } + | Self::Label { .. } => None, } } @@ -2675,6 +2681,12 @@ pub struct InlineAsm<'hir> { pub line_spans: &'hir [Span], } +impl InlineAsm<'_> { + pub fn contains_label(&self) -> bool { + self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. })) + } +} + /// Represents a parameter in a function header. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Param<'hir> { diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1c38a45d3a32f..278a0a6e6b906 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1290,6 +1290,7 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>( InlineAsmOperand::SymStatic { path, .. } => { try_visit!(visitor.visit_qpath(path, id, *op_sp)); } + InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), } } V::Result::output() diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index d03b02f028da1..9de660407d7aa 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -470,6 +470,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } }; } + // No special checking is needed for labels. + hir::InlineAsmOperand::Label { .. } => {} } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8f8f747339b42..b5bb063c5ed8c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1265,6 +1265,10 @@ impl<'a> State<'a> { s.space(); s.print_qpath(path, true); } + hir::InlineAsmOperand::Label { block } => { + s.head("label"); + s.print_block(block); + } }, AsmArg::Options(opts) => { s.word("options"); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 81440b0562e24..614761c03bd61 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3264,6 +3264,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // be well-formed. hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} hir::InlineAsmOperand::SymStatic { .. } => {} + hir::InlineAsmOperand::Label { block } => { + self.check_block_no_value(block); + } } } if asm.options.contains(ast::InlineAsmOptions::NORETURN) { diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 04fb7bcf4f3b4..ba0383d19b92a 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -293,6 +293,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { | hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } | hir::InlineAsmOperand::SymStatic { .. } => {} + hir::InlineAsmOperand::Label { block } => { + self.walk_block(block); + } } } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 62762168cf420..0e64ed897537e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -656,6 +656,9 @@ impl<'tcx> Cx<'tcx> { hir::InlineAsmOperand::SymStatic { path: _, def_id } => { InlineAsmOperand::SymStatic { def_id } } + hir::InlineAsmOperand::Label { .. } => { + todo!() + } }) .collect(), options: asm.options, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5593de607844d..3ab6c4b9b6a55 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -446,7 +446,8 @@ fn collect_items_rec<'tcx>( hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Out { .. } | hir::InlineAsmOperand::InOut { .. } - | hir::InlineAsmOperand::SplitInOut { .. } => { + | hir::InlineAsmOperand::SplitInOut { .. } + | hir::InlineAsmOperand::Label { .. } => { span_bug!(*op_sp, "invalid operand type for global_asm!") } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1bae5b3224035..9c0020f02d9c2 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -434,7 +434,7 @@ impl<'a> Parser<'a> { } /// Parses a block. No inner attributes are allowed. - pub(super) fn parse_block(&mut self) -> PResult<'a, P> { + pub fn parse_block(&mut self) -> PResult<'a, P> { let (attrs, block) = self.parse_inner_attrs_and_block()?; if let [.., last] = &*attrs { self.error_on_forbidden_inner_attr( diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 487407014d178..e5033e1f51f23 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -86,7 +86,6 @@ use crate::errors; use self::LiveNodeKind::*; use self::VarKind::*; -use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def::*; @@ -416,6 +415,12 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id)); } + // Inline assembly may contain labels. + hir::ExprKind::InlineAsm(asm) if asm.contains_label() => { + self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id)); + intravisit::walk_expr(self, expr); + } + // otherwise, live nodes are not required: hir::ExprKind::Index(..) | hir::ExprKind::Field(..) @@ -1045,20 +1050,53 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ), hir::ExprKind::InlineAsm(asm) => { + // + // (inputs) + // | + // v + // (outputs) + // / \ + // | | + // v v + // (labels)(fallthrough) + // | | + // v v + // ( succ / exit_ln ) + // Handle non-returning asm - let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) { - self.exit_ln - } else { - succ - }; + let mut succ = + if self.typeck_results.expr_ty(expr).is_never() { self.exit_ln } else { succ }; + + // Do a first pass for labels only + if asm.contains_label() { + let ln = self.live_node(expr.hir_id, expr.span); + self.init_from_succ(ln, succ); + for (op, _op_sp) in asm.operands.iter().rev() { + match op { + hir::InlineAsmOperand::Label { block } => { + let label_ln = self.propagate_through_block(block, succ); + self.merge_from_succ(ln, label_ln); + } + hir::InlineAsmOperand::In { .. } + | hir::InlineAsmOperand::Out { .. } + | hir::InlineAsmOperand::InOut { .. } + | hir::InlineAsmOperand::SplitInOut { .. } + | hir::InlineAsmOperand::Const { .. } + | hir::InlineAsmOperand::SymFn { .. } + | hir::InlineAsmOperand::SymStatic { .. } => {} + } + } + succ = ln; + } - // Do a first pass for writing outputs only + // Do a second pass for writing outputs only for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { .. } | hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } - | hir::InlineAsmOperand::SymStatic { .. } => {} + | hir::InlineAsmOperand::SymStatic { .. } + | hir::InlineAsmOperand::Label { .. } => {} hir::InlineAsmOperand::Out { expr, .. } => { if let Some(expr) = expr { succ = self.write_place(expr, succ, ACC_WRITE); @@ -1075,7 +1113,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - // Then do a second pass for inputs + // Then do a third pass for inputs for (op, _op_sp) in asm.operands.iter().rev() { match op { hir::InlineAsmOperand::In { expr, .. } => { @@ -1097,7 +1135,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } - | hir::InlineAsmOperand::SymStatic { .. } => {} + | hir::InlineAsmOperand::SymStatic { .. } + | hir::InlineAsmOperand::Label { .. } => {} } } succ diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 0455d6d4acba3..27c9c1306e6ac 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -237,7 +237,8 @@ impl<'tcx> CheckInlineAssembly<'tcx> { InlineAsmOperand::In { .. } | InlineAsmOperand::Out { .. } | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } => Some(op_sp), + | InlineAsmOperand::SplitInOut { .. } + | InlineAsmOperand::Label { .. } => Some(op_sp), }) .collect(); if !unsupported_operands.is_empty() { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2f4da29133f1b..8b8d99f88165a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1246,6 +1246,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.resolve_anon_const(anon_const, AnonConstKind::InlineConst); } InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym), + InlineAsmOperand::Label { block } => self.visit_block(block), } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 46472a131ff4b..0cfff1623dbd4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -399,6 +399,7 @@ symbols! { asm, asm_const, asm_experimental_arch, + asm_goto, asm_sym, asm_unwind, assert, diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 245a903f99826..65d922f03df3a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -255,6 +255,9 @@ fn never_loop_expr<'tcx>( InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => { NeverLoopResult::Normal }, + InlineAsmOperand::Label { block } => { + never_loop_block(cx, block, local_labels, main_loop_id) + } })), ExprKind::OffsetOf(_, _) | ExprKind::Yield(_, _) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index d50332e82da5b..643852c1c54fb 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -835,6 +835,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_body(anon_const.body); }, InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path), + InlineAsmOperand::Label { block } => self.hash_block(block), } } }, From 040ab7d4b604d9e70bf9c93a1af7146edf0e740e Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 25 Dec 2023 21:19:04 +0000 Subject: [PATCH 200/613] Add asm label support to THIR --- compiler/rustc_middle/src/thir.rs | 3 +++ compiler/rustc_middle/src/thir/visit.rs | 1 + compiler/rustc_mir_build/src/build/expr/into.rs | 3 +++ compiler/rustc_mir_build/src/thir/cx/expr.rs | 4 ++-- compiler/rustc_mir_build/src/thir/print.rs | 6 ++++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index e1e5d68148fe8..f91130ee25820 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -565,6 +565,9 @@ pub enum InlineAsmOperand<'tcx> { SymStatic { def_id: DefId, }, + Label { + block: BlockId, + }, } #[derive(Copy, Clone, Debug, PartialEq, HashStable)] diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 4847a7bea91d7..5952c296fb642 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -162,6 +162,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( | Const { value: _, span: _ } | SymFn { value: _, span: _ } | SymStatic { def_id: _ } => {} + Label { block } => visitor.visit_block(&visitor.thir()[*block]), } } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 2978491d646e8..60614383cc84a 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -455,6 +455,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } + thir::InlineAsmOperand::Label { .. } => { + todo!() + } }) .collect(); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 0e64ed897537e..2318e84292b83 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -656,8 +656,8 @@ impl<'tcx> Cx<'tcx> { hir::InlineAsmOperand::SymStatic { path: _, def_id } => { InlineAsmOperand::SymStatic { def_id } } - hir::InlineAsmOperand::Label { .. } => { - todo!() + hir::InlineAsmOperand::Label { block } => { + InlineAsmOperand::Label { block: self.mirror_block(block) } } }) .collect(), diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 267ea3aa3e12c..d53704f89e79e 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -889,6 +889,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); print_indented!(self, "}", depth_lvl + 1); } + InlineAsmOperand::Label { block } => { + print_indented!(self, "InlineAsmOperand::Block {", depth_lvl); + print_indented!(self, "block:", depth_lvl + 1); + self.print_block(*block, depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } } } } From 7152993aa859819d67b9f01e41e1f389e52043de Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Dec 2023 04:31:56 +0000 Subject: [PATCH 201/613] Use slice.chain(option) for Successors This makes more sense because most cases then second one is unwind target. --- compiler/rustc_middle/src/mir/terminator.rs | 59 ++++++++++----------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 91b7952bec5e8..381db830aea5e 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -336,8 +336,7 @@ pub struct Terminator<'tcx> { } pub type Successors<'a> = impl DoubleEndedIterator + 'a; -pub type SuccessorsMut<'a> = - iter::Chain, slice::IterMut<'a, BasicBlock>>; +pub type SuccessorsMut<'a> = impl DoubleEndedIterator + 'a; impl<'tcx> Terminator<'tcx> { #[inline] @@ -371,24 +370,24 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn successors(&self) -> Successors<'_> { use self::TerminatorKind::*; match *self { - Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } - | Yield { resume: t, drop: Some(ref u), .. } - | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. } - | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. } - | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) } - | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => { - Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()) - } - Goto { target: t } - | Call { target: None, unwind: UnwindAction::Cleanup(t), .. } - | Call { target: Some(t), unwind: _, .. } - | Yield { resume: t, drop: None, .. } - | Drop { target: t, unwind: _, .. } - | Assert { target: t, unwind: _, .. } - | FalseUnwind { real_target: t, unwind: _ } - | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } - | InlineAsm { destination: Some(t), unwind: _, .. } => { - Some(t).into_iter().chain((&[]).into_iter().copied()) + Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } + | Yield { resume: ref t, drop: Some(u), .. } + | Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. } + | Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. } + | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } + | InlineAsm { destination: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } => { + slice::from_ref(t).into_iter().copied().chain(Some(u)) + } + Goto { target: ref t } + | Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. } + | Call { target: Some(ref t), unwind: _, .. } + | Yield { resume: ref t, drop: None, .. } + | Drop { target: ref t, unwind: _, .. } + | Assert { target: ref t, unwind: _, .. } + | FalseUnwind { real_target: ref t, unwind: _ } + | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref t), .. } + | InlineAsm { destination: Some(ref t), unwind: _, .. } => { + slice::from_ref(t).into_iter().copied().chain(None) } UnwindResume | UnwindTerminate(_) @@ -397,14 +396,12 @@ impl<'tcx> TerminatorKind<'tcx> { | Unreachable | Call { target: None, unwind: _, .. } | InlineAsm { destination: None, unwind: _, .. } => { - None.into_iter().chain((&[]).into_iter().copied()) + (&[]).into_iter().copied().chain(None) } - SwitchInt { ref targets, .. } => { - None.into_iter().chain(targets.targets.iter().copied()) + SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None), + FalseEdge { ref real_target, imaginary_target } => { + slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target)) } - FalseEdge { real_target, ref imaginary_target } => Some(real_target) - .into_iter() - .chain(slice::from_ref(imaginary_target).into_iter().copied()), } } @@ -421,7 +418,7 @@ impl<'tcx> TerminatorKind<'tcx> { destination: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. - } => Some(t).into_iter().chain(slice::from_mut(u)), + } => slice::from_mut(t).into_iter().chain(Some(u)), Goto { target: ref mut t } | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. } | Call { target: Some(ref mut t), unwind: _, .. } @@ -431,7 +428,7 @@ impl<'tcx> TerminatorKind<'tcx> { | FalseUnwind { real_target: ref mut t, unwind: _ } | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. } | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => { - Some(t).into_iter().chain(&mut []) + slice::from_mut(t).into_iter().chain(None) } UnwindResume | UnwindTerminate(_) @@ -439,10 +436,10 @@ impl<'tcx> TerminatorKind<'tcx> { | Return | Unreachable | Call { target: None, unwind: _, .. } - | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []), - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets), + | InlineAsm { destination: None, unwind: _, .. } => (&mut []).into_iter().chain(None), + SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None), FalseEdge { ref mut real_target, ref mut imaginary_target } => { - Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) + slice::from_mut(real_target).into_iter().chain(Some(imaginary_target)) } } } From b044aaa905f8a97e67ea72b490ee46d6420c4680 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Dec 2023 15:28:42 +0000 Subject: [PATCH 202/613] Change InlineAsm to allow multiple targets instead --- compiler/rustc_borrowck/src/lib.rs | 2 +- .../src/polonius/loan_invalidations.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- compiler/rustc_codegen_cranelift/src/base.rs | 16 ++++- compiler/rustc_codegen_ssa/src/mir/block.rs | 4 +- compiler/rustc_const_eval/messages.ftl | 3 - .../rustc_const_eval/src/interpret/machine.rs | 6 ++ .../src/interpret/terminator.rs | 12 +--- .../src/transform/validate.rs | 6 +- compiler/rustc_middle/src/mir/mod.rs | 6 +- compiler/rustc_middle/src/mir/pretty.rs | 23 ++++--- compiler/rustc_middle/src/mir/syntax.rs | 7 +- compiler/rustc_middle/src/mir/terminator.rs | 64 ++++++++++--------- compiler/rustc_middle/src/mir/visit.rs | 2 +- .../rustc_mir_build/src/build/expr/into.rs | 6 +- compiler/rustc_mir_build/src/lints.rs | 7 +- .../src/framework/direction.rs | 13 ++-- .../src/framework/graphviz.rs | 4 +- .../src/move_paths/builder.rs | 2 +- .../rustc_mir_transform/src/coverage/graph.rs | 18 ++++-- .../rustc_mir_transform/src/coverage/tests.rs | 5 +- compiler/rustc_mir_transform/src/inline.rs | 4 +- .../rustc_smir/src/rustc_smir/convert/mir.rs | 5 +- 23 files changed, 125 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index dbaa9e5bcfab0..94c1875608387 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -723,7 +723,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 10941cadcbb25..83081f83e5e80 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -161,7 +161,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 75cc28bcab0bc..fecf23ad74a8d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1771,8 +1771,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.assert_iscleanup(body, block_data, real_target, is_cleanup); self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } - TerminatorKind::InlineAsm { destination, unwind, .. } => { - if let Some(target) = destination { + TerminatorKind::InlineAsm { ref targets, unwind, .. } => { + for &target in targets { self.assert_iscleanup(body, block_data, target, is_cleanup); } self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index a7e76fbc128ea..1ce920f3bdb79 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -445,7 +445,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { template, operands, options, - destination, + targets, line_spans: _, unwind: _, } => { @@ -456,13 +456,25 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { ); } + let have_labels = if options.contains(InlineAsmOptions::NORETURN) { + !targets.is_empty() + } else { + targets.len() > 1 + }; + if have_labels { + fx.tcx.dcx().span_fatal( + source_info.span, + "cranelift doesn't support labels in inline assembly.", + ); + } + crate::inline_asm::codegen_inline_asm_terminator( fx, source_info.span, template, operands, *options, - *destination, + targets.get(0).copied(), ); } TerminatorKind::UnwindTerminate(reason) => { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 00007110938e0..6342802bb1960 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1285,7 +1285,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ref operands, options, line_spans, - destination, + ref targets, unwind, } => self.codegen_asm_terminator( helper, @@ -1295,7 +1295,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operands, options, line_spans, - destination, + targets.get(0).copied(), unwind, self.instance, mergeable_succ(), diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index c456e40d7c15b..52ee78570bef5 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -232,9 +232,6 @@ const_eval_non_const_fn_call = const_eval_non_const_impl = impl defined here, but it is not `const` -const_eval_noreturn_asm_returned = - returned from noreturn inline assembly - const_eval_not_enough_caller_args = calling a function with fewer arguments than it requires diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 0106ec425bc50..1d858dd4f5665 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -374,11 +374,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { kind: Option>, ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + /// Evaluate the inline assembly. + /// + /// This should take care of jumping to the next block (one of `targets`) when asm goto + /// is triggered, `targets[0]` when the assembly falls through, or diverge in case of + /// `InlineAsmOptions::NORETURN` being set. fn eval_inline_asm( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _template: &'tcx [InlineAsmTemplatePiece], _operands: &[mir::InlineAsmOperand<'tcx>], _options: InlineAsmOptions, + _targets: &[mir::BasicBlock], ) -> InterpResult<'tcx> { throw_unsup_format!("inline assembly is not supported") } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index e72ace8be3559..9b16d99d82b38 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; -use rustc_ast::ast::InlineAsmOptions; use rustc_middle::{ mir, ty::{ @@ -224,15 +223,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { terminator.kind ), - InlineAsm { template, ref operands, options, destination, .. } => { - M::eval_inline_asm(self, template, operands, options)?; - if options.contains(InlineAsmOptions::NORETURN) { - throw_ub_custom!(fluent::const_eval_noreturn_asm_returned); - } - self.go_to_block( - destination - .expect("InlineAsm terminators without noreturn must have a destination"), - ) + InlineAsm { template, ref operands, options, ref targets, .. } => { + M::eval_inline_asm(self, template, operands, options, targets)?; } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index cc49e8ea247f7..74ba2f6039e86 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -471,9 +471,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.check_edge(location, *real_target, EdgeKind::Normal); self.check_unwind_edge(location, *unwind); } - TerminatorKind::InlineAsm { destination, unwind, .. } => { - if let Some(destination) = destination { - self.check_edge(location, *destination, EdgeKind::Normal); + TerminatorKind::InlineAsm { targets, unwind, .. } => { + for &target in targets { + self.check_edge(location, target, EdgeKind::Normal); } self.check_unwind_edge(location, *unwind); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 3017f912ef027..de18580f61ae9 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1718,13 +1718,13 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(BasicBlockData<'_>, 136); + static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 40); static_assert_size!(SourceScopeData<'_>, 72); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); - static_assert_size!(Terminator<'_>, 104); - static_assert_size!(TerminatorKind<'_>, 88); + static_assert_size!(Terminator<'_>, 112); + static_assert_size!(TerminatorKind<'_>, 96); static_assert_size!(VarDebugInfo<'_>, 88); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5638b575b319c..35058458eed7c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf}; use crate::mir::interpret::ConstAllocation; use super::graphviz::write_mir_fn_graphviz; -use rustc_ast::InlineAsmTemplatePiece; +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::interpret::{ alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, @@ -868,16 +868,19 @@ impl<'tcx> TerminatorKind<'tcx> { vec!["real".into(), "unwind".into()] } FalseUnwind { unwind: _, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { - vec!["return".into(), "unwind".into()] - } - InlineAsm { destination: Some(_), unwind: _, .. } => { - vec!["return".into()] - } - InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => { - vec!["unwind".into()] + InlineAsm { options, ref targets, unwind, .. } => { + let mut vec = Vec::with_capacity(targets.len() + 1); + if !options.contains(InlineAsmOptions::NORETURN) { + vec.push("return".into()); + } + vec.resize(targets.len(), "label".into()); + + if let UnwindAction::Cleanup(_) = unwind { + vec.push("unwind".into()); + } + + vec } - InlineAsm { destination: None, unwind: _, .. } => vec![], } } } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 5c9857b9c53d8..6f62c7186a768 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -793,9 +793,10 @@ pub enum TerminatorKind<'tcx> { /// used to map assembler errors back to the line in the source code. line_spans: &'tcx [Span], - /// Destination block after the inline assembly returns, unless it is - /// diverging (InlineAsmOptions::NORETURN). - destination: Option, + /// Valid targets for the inline assembly. + /// The first element is the fallthrough destination, unless + /// InlineAsmOptions::NORETURN is set. + targets: Vec, /// Action to be taken if the inline assembly unwinds. This is present /// if and only if InlineAsmOptions::MAY_UNWIND is set. diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 381db830aea5e..fa4a494ff0b64 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -374,8 +374,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Yield { resume: ref t, drop: Some(u), .. } | Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. } | Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. } - | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } - | InlineAsm { destination: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } => { + | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => { slice::from_ref(t).into_iter().copied().chain(Some(u)) } Goto { target: ref t } @@ -384,9 +383,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Yield { resume: ref t, drop: None, .. } | Drop { target: ref t, unwind: _, .. } | Assert { target: ref t, unwind: _, .. } - | FalseUnwind { real_target: ref t, unwind: _ } - | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref t), .. } - | InlineAsm { destination: Some(ref t), unwind: _, .. } => { + | FalseUnwind { real_target: ref t, unwind: _ } => { slice::from_ref(t).into_iter().copied().chain(None) } UnwindResume @@ -394,10 +391,11 @@ impl<'tcx> TerminatorKind<'tcx> { | CoroutineDrop | Return | Unreachable - | Call { target: None, unwind: _, .. } - | InlineAsm { destination: None, unwind: _, .. } => { - (&[]).into_iter().copied().chain(None) + | Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None), + InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => { + targets.iter().copied().chain(Some(u)) } + InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None), SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None), FalseEdge { ref real_target, imaginary_target } => { slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target)) @@ -413,21 +411,16 @@ impl<'tcx> TerminatorKind<'tcx> { | Yield { resume: ref mut t, drop: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } - | InlineAsm { - destination: Some(ref mut t), - unwind: UnwindAction::Cleanup(ref mut u), - .. - } => slice::from_mut(t).into_iter().chain(Some(u)), + | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } => { + slice::from_mut(t).into_iter().chain(Some(u)) + } Goto { target: ref mut t } | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. } | Call { target: Some(ref mut t), unwind: _, .. } | Yield { resume: ref mut t, drop: None, .. } | Drop { target: ref mut t, unwind: _, .. } | Assert { target: ref mut t, unwind: _, .. } - | FalseUnwind { real_target: ref mut t, unwind: _ } - | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. } - | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => { + | FalseUnwind { real_target: ref mut t, unwind: _ } => { slice::from_mut(t).into_iter().chain(None) } UnwindResume @@ -435,8 +428,11 @@ impl<'tcx> TerminatorKind<'tcx> { | CoroutineDrop | Return | Unreachable - | Call { target: None, unwind: _, .. } - | InlineAsm { destination: None, unwind: _, .. } => (&mut []).into_iter().chain(None), + | Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None), + InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => { + targets.iter_mut().chain(Some(u)) + } + InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None), SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None), FalseEdge { ref mut real_target, ref mut imaginary_target } => { slice::from_mut(real_target).into_iter().chain(Some(imaginary_target)) @@ -511,7 +507,7 @@ pub enum TerminatorEdges<'mir, 'tcx> { Double(BasicBlock, BasicBlock), /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { - return_: Option, + return_: &'mir [BasicBlock], /// The cleanup block, if it exists. cleanup: Option, place: CallReturnPlaces<'mir, 'tcx>, @@ -575,31 +571,37 @@ impl<'tcx> TerminatorKind<'tcx> { TerminatorEdges::Double(real_target, imaginary_target) } - Yield { resume: target, drop, resume_arg, value: _ } => { + Yield { resume: ref target, drop, resume_arg, value: _ } => { TerminatorEdges::AssignOnReturn { - return_: Some(target), + return_: slice::from_ref(target), cleanup: drop, place: CallReturnPlaces::Yield(resume_arg), } } - Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { - TerminatorEdges::AssignOnReturn { - return_: target, - cleanup: unwind.cleanup_block(), - place: CallReturnPlaces::Call(destination), - } - } + Call { + unwind, + destination, + ref target, + func: _, + args: _, + fn_span: _, + call_source: _, + } => TerminatorEdges::AssignOnReturn { + return_: target.as_ref().map(slice::from_ref).unwrap_or_default(), + cleanup: unwind.cleanup_block(), + place: CallReturnPlaces::Call(destination), + }, InlineAsm { template: _, ref operands, options: _, line_spans: _, - destination, + ref targets, unwind, } => TerminatorEdges::AssignOnReturn { - return_: destination, + return_: targets, cleanup: unwind.cleanup_block(), place: CallReturnPlaces::InlineAsm(operands), }, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 2c5ca82a4cd39..a1418b41e057f 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -565,7 +565,7 @@ macro_rules! make_mir_visitor { operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 60614383cc84a..a49d864701a03 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -474,10 +474,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { operands, options, line_spans, - destination: if options.contains(InlineAsmOptions::NORETURN) { - None + targets: if options.contains(InlineAsmOptions::NORETURN) { + Vec::new() } else { - Some(destination_block) + vec![destination_block] }, unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) { UnwindAction::Continue diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 3f2b7c482a67f..2c817d605af2a 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -199,9 +199,10 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor ControlFlow::Break(NonRecursive), - // A diverging InlineAsm is treated as non-recursing - TerminatorKind::InlineAsm { destination, .. } => { - if destination.is_some() { + // A InlineAsm without targets (diverging and contains no labels) + // is treated as non-recursing. + TerminatorKind::InlineAsm { ref targets, .. } => { + if !targets.is_empty() { ControlFlow::Continue(()) } else { ControlFlow::Break(NonRecursive) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 4c3fadf487b3c..f57e8b8bd6f97 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -242,9 +242,9 @@ impl Direction for Backward { propagate(pred, &tmp); } - mir::TerminatorKind::InlineAsm { - destination: Some(dest), ref operands, .. - } if dest == bb => { + mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. } + if targets.contains(&bb) => + { let mut tmp = exit_state.clone(); analysis.apply_call_return_effect( &mut tmp, @@ -491,9 +491,12 @@ impl Direction for Forward { if let Some(cleanup) = cleanup { propagate(cleanup, exit_state); } - if let Some(return_) = return_ { + + if !return_.is_empty() { analysis.apply_call_return_effect(exit_state, bb, place); - propagate(return_, exit_state); + for &target in return_ { + propagate(target, exit_state); + } } } TerminatorEdges::SwitchInt { targets, discr } => { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 0270e059a5821..a827f6a8dbd9d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -299,7 +299,9 @@ where })?; } - mir::TerminatorKind::InlineAsm { destination: Some(_), ref operands, .. } => { + mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. } + if !targets.is_empty() => + { self.write_row(w, "", "(on successful return)", |this, w, fmt| { let state_on_unwind = this.results.get().clone(); this.results.apply_custom_effect(|analysis, state| { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index c6ec1b5aee454..95f12301395c3 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -491,7 +491,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { ref operands, options: _, line_spans: _, - destination: _, + targets: _, unwind: _, } => { for op in operands { diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index c97192435ce48..ed8c4d8283d98 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -349,12 +349,20 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera | FalseUnwind { real_target: target, .. } | Goto { target } => CoverageSuccessors::Chainable(target), - // These terminators can normally be chained, except when they have no + // A call terminator can normally be chained, except when they have no // successor because they are known to diverge. - Call { target: maybe_target, .. } | InlineAsm { destination: maybe_target, .. } => { - match maybe_target { - Some(target) => CoverageSuccessors::Chainable(target), - None => CoverageSuccessors::NotChainable(&[]), + Call { target: maybe_target, .. } => match maybe_target { + Some(target) => CoverageSuccessors::Chainable(target), + None => CoverageSuccessors::NotChainable(&[]), + }, + + // An inline asm terminator can normally be chained, except when it diverges or uses asm + // goto. + InlineAsm { ref targets, .. } => { + if targets.len() == 1 { + CoverageSuccessors::Chainable(targets[0]) + } else { + CoverageSuccessors::NotChainable(targets) } } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index d9a3c0cb162f3..569998de35e0b 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -88,7 +88,6 @@ impl<'tcx> MockBlocks<'tcx> { | TerminatorKind::FalseEdge { real_target: ref mut target, .. } | TerminatorKind::FalseUnwind { real_target: ref mut target, .. } | TerminatorKind::Goto { ref mut target } - | TerminatorKind::InlineAsm { destination: Some(ref mut target), .. } | TerminatorKind::Yield { resume: ref mut target, .. } => *target = to_block, ref invalid => bug!("Invalid from_block: {:?}", invalid), } @@ -185,10 +184,12 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String { | TerminatorKind::FalseEdge { real_target: target, .. } | TerminatorKind::FalseUnwind { real_target: target, .. } | TerminatorKind::Goto { target } - | TerminatorKind::InlineAsm { destination: Some(target), .. } | TerminatorKind::Yield { resume: target, .. } => { format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), target) } + TerminatorKind::InlineAsm { targets, .. } => { + format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets) + } TerminatorKind::SwitchInt { targets, .. } => { format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets) } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 2009539d4d084..a6382584577ce 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1032,8 +1032,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { { bug!("False unwinds should have been removed before inlining") } - TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => { - if let Some(ref mut tgt) = *destination { + TerminatorKind::InlineAsm { ref mut targets, ref mut unwind, .. } => { + for tgt in targets.iter_mut() { *tgt = self.map_block(*tgt); } *unwind = self.map_unwind(*unwind); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 501d6f7d304ef..92e86cf0ee41e 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -632,14 +632,15 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { operands, options, line_spans, - destination, + targets, unwind, } => TerminatorKind::InlineAsm { template: format!("{template:?}"), operands: operands.iter().map(|operand| operand.stable(tables)).collect(), options: format!("{options:?}"), line_spans: format!("{line_spans:?}"), - destination: destination.map(|d| d.as_usize()), + // FIXME: Figure out how to do labels in SMIR + destination: targets.first().map(|d| d.as_usize()), unwind: unwind.stable(tables), }, mir::TerminatorKind::Yield { .. } From 3b1dd1bfa97aa9775109266f9932027a99362b0d Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Dec 2023 16:07:35 +0000 Subject: [PATCH 203/613] Implement asm goto in MIR and MIR lowering --- compiler/rustc_borrowck/src/lib.rs | 3 +- .../src/polonius/loan_invalidations.rs | 3 +- .../rustc_codegen_cranelift/src/global_asm.rs | 3 +- .../rustc_codegen_cranelift/src/inline_asm.rs | 3 ++ compiler/rustc_codegen_ssa/src/mir/block.rs | 3 ++ compiler/rustc_middle/src/mir/pretty.rs | 3 ++ compiler/rustc_middle/src/mir/syntax.rs | 4 +++ compiler/rustc_middle/src/mir/visit.rs | 3 +- .../rustc_mir_build/src/build/expr/into.rs | 33 ++++++++++++++----- .../src/impls/storage_liveness.rs | 3 +- .../src/move_paths/builder.rs | 3 +- compiler/rustc_mir_transform/src/dest_prop.rs | 3 +- .../rustc_smir/src/rustc_smir/convert/mir.rs | 3 +- 13 files changed, 53 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 94c1875608387..b776643763a7e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -749,7 +749,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 83081f83e5e80..956de1dec9b2b 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -182,7 +182,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> { } InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index da07b66c762ee..44650898de897 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -78,7 +78,8 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, InlineAsmOperand::In { .. } | InlineAsmOperand::Out { .. } | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } => { + | InlineAsmOperand::SplitInOut { .. } + | InlineAsmOperand::Label { .. } => { span_bug!(op_sp, "invalid operand type for global_asm!") } } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 7793b1b70924b..171ee88a11c75 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -129,6 +129,9 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() } } + InlineAsmOperand::Label { .. } => { + span_bug!(span, "asm! label operands are not yet supported"); + } }) .collect::>(); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6342802bb1960..c9a1e7789c27e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1119,6 +1119,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::InlineAsmOperand::SymStatic { def_id } => { InlineAsmOperandRef::SymStatic { def_id } } + mir::InlineAsmOperand::Label { target_index: _ } => { + todo!(); + } }) .collect(); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 35058458eed7c..e058302af312c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -830,6 +830,9 @@ impl<'tcx> TerminatorKind<'tcx> { InlineAsmOperand::SymStatic { def_id } => { write!(fmt, "sym_static {def_id:?}")?; } + InlineAsmOperand::Label { target_index } => { + write!(fmt, "label {target_index}")?; + } } } write!(fmt, ", options({options:?}))") diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 6f62c7186a768..f188923f87618 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -919,6 +919,10 @@ pub enum InlineAsmOperand<'tcx> { SymStatic { def_id: DefId, }, + Label { + /// This represents the index into the `targets` array in `TerminatorKind::InlineAsm`. + target_index: usize, + }, } /// Type for MIR `Assert` terminator error messages. diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index a1418b41e057f..845b17175505d 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -595,7 +595,8 @@ macro_rules! make_mir_visitor { self.visit_constant(value, location); } InlineAsmOperand::Out { place: None, .. } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index a49d864701a03..09e518606e314 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -400,6 +400,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { line_spans, }) => { use rustc_middle::{mir, thir}; + + let destination_block = this.cfg.start_new_block(); + let mut targets = if options.contains(InlineAsmOptions::NORETURN) { + vec![] + } else { + vec![destination_block] + }; + let operands = operands .into_iter() .map(|op| match *op { @@ -455,17 +463,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } - thir::InlineAsmOperand::Label { .. } => { - todo!() + thir::InlineAsmOperand::Label { block } => { + let target = this.cfg.start_new_block(); + let target_index = targets.len(); + targets.push(target); + + let tmp = this.get_unit_temp(); + let target = unpack!(this.ast_block(tmp, target, block, source_info)); + this.cfg.terminate( + target, + source_info, + TerminatorKind::Goto { target: destination_block }, + ); + + mir::InlineAsmOperand::Label { target_index } } }) .collect(); - if !options.contains(InlineAsmOptions::NORETURN) { + if !expr.ty.is_never() { this.cfg.push_assign_unit(block, source_info, destination, this.tcx); } - let destination_block = this.cfg.start_new_block(); this.cfg.terminate( block, source_info, @@ -474,11 +493,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { operands, options, line_spans, - targets: if options.contains(InlineAsmOptions::NORETURN) { - Vec::new() - } else { - vec![destination_block] - }, + targets, unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) { UnwindAction::Continue } else { diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 595c2ff5bf7fa..29169c31263bd 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -271,7 +271,8 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { InlineAsmOperand::In { .. } | InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } => {} + | InlineAsmOperand::SymStatic { .. } + | InlineAsmOperand::Label { .. } => {} } } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 95f12301395c3..db48ecd702bdb 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -515,7 +515,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } InlineAsmOperand::Const { value: _ } | InlineAsmOperand::SymFn { value: _ } - | InlineAsmOperand::SymStatic { def_id: _ } => {} + | InlineAsmOperand::SymStatic { def_id: _ } + | InlineAsmOperand::Label { target_index: _ } => {} } } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 2c8201b1903e6..10fea09531a65 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -648,7 +648,8 @@ impl WriteInfo { } InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } => (), + | InlineAsmOperand::SymStatic { .. } + | InlineAsmOperand::Label { .. } => {} } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 92e86cf0ee41e..003a9a5920018 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -559,7 +559,8 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> { } InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } => (None, None), + | InlineAsmOperand::SymStatic { .. } + | InlineAsmOperand::Label { .. } => (None, None), }; stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") } From 27e6ee102ed359a3744ac1f2dffbfb7a60bd2371 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Dec 2023 04:20:35 +0000 Subject: [PATCH 204/613] Add callbr support to LLVM wrapper --- compiler/rustc_codegen_llvm/src/builder.rs | 52 +++++++++++++++++++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 14 +++++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 25 +++++++++ 3 files changed, 91 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 8cab2a3f27c1b..eda3c583994a0 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1547,6 +1547,58 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } + pub(crate) fn callbr( + &mut self, + llty: &'ll Type, + fn_attrs: Option<&CodegenFnAttrs>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, + llfn: &'ll Value, + args: &[&'ll Value], + default_dest: &'ll BasicBlock, + indirect_dest: &[&'ll BasicBlock], + funclet: Option<&Funclet<'ll>>, + ) -> &'ll Value { + debug!("invoke {:?} with args ({:?})", llfn, args); + + let args = self.check_call("callbr", llty, llfn, args); + let funclet_bundle = funclet.map(|funclet| funclet.bundle()); + let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw); + let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); + if let Some(funclet_bundle) = funclet_bundle { + bundles.push(funclet_bundle); + } + + // Emit CFI pointer type membership test + self.cfi_type_test(fn_attrs, fn_abi, llfn); + + // Emit KCFI operand bundle + let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn); + let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw); + if let Some(kcfi_bundle) = kcfi_bundle { + bundles.push(kcfi_bundle); + } + + let callbr = unsafe { + llvm::LLVMRustBuildCallBr( + self.llbuilder, + llty, + llfn, + default_dest, + indirect_dest.as_ptr(), + indirect_dest.len() as c_uint, + args.as_ptr(), + args.len() as c_uint, + bundles.as_ptr(), + bundles.len() as c_uint, + UNNAMED, + ) + }; + if let Some(fn_abi) = fn_abi { + fn_abi.apply_attrs_callsite(self, callbr); + } + callbr + } + // Emits CFI pointer type membership tests. fn cfi_type_test( &mut self, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index dbf35e5f49952..22c67436d3619 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1617,6 +1617,20 @@ extern "C" { Name: *const c_char, ) -> &'a Value; + pub fn LLVMRustBuildCallBr<'a>( + B: &Builder<'a>, + Ty: &'a Type, + Fn: &'a Value, + DefaultDest: &'a BasicBlock, + IndirectDests: *const &'a BasicBlock, + NumIndirectDests: c_uint, + Args: *const &'a Value, + NumArgs: c_uint, + OpBundles: *const &OperandBundleDef<'a>, + NumOpBundles: c_uint, + Name: *const c_char, + ) -> &'a Value; + pub fn LLVMRustSetFastMath(Instr: &Value); pub fn LLVMRustSetAlgebraicMath(Instr: &Value); pub fn LLVMRustSetAllowReassoc(Instr: &Value); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index af2353fbb19c5..63714de1fc64d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1539,6 +1539,31 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, Name)); } +extern "C" LLVMValueRef +LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMBasicBlockRef DefaultDest, + LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests, + LLVMValueRef *Args, unsigned NumArgs, + OperandBundleDef **OpBundles, unsigned NumOpBundles, + const char *Name) { + Value *Callee = unwrap(Fn); + FunctionType *FTy = unwrap(Ty); + + // FIXME: Is there a way around this? + std::vector IndirectDestsUnwrapped; + IndirectDestsUnwrapped.reserve(NumIndirectDests); + for (unsigned i = 0; i < NumIndirectDests; ++i) { + IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i])); + } + + return wrap(unwrap(B)->CreateCallBr( + FTy, Callee, unwrap(DefaultDest), + ArrayRef(IndirectDestsUnwrapped), + ArrayRef(unwrap(Args), NumArgs), + ArrayRef(*OpBundles, NumOpBundles), + Name)); +} + extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) { auto Point = unwrap(BB)->getFirstInsertionPt(); From 5e4fd6bc2301a8e267d044a526ffb77c1a6c35d7 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 27 Dec 2023 04:08:04 +0000 Subject: [PATCH 205/613] Implement asm goto for LLVM and GCC backend --- compiler/rustc_codegen_gcc/src/asm.rs | 31 ++++++++++++++-- compiler/rustc_codegen_llvm/src/asm.rs | 29 +++++++++------ compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 ++ compiler/rustc_codegen_ssa/src/mir/block.rs | 38 +++++++++++++++----- compiler/rustc_codegen_ssa/src/traits/asm.rs | 6 +++- 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 78e8e32b97299..07edd26e27a42 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -107,7 +107,7 @@ enum ConstraintOrRegister { impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, dest: Option, _catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>) { if options.contains(InlineAsmOptions::MAY_UNWIND) { self.sess().dcx() .create_err(UnwindingInlineAsm { span: span[0] }) @@ -126,6 +126,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // added to `outputs.len()` let mut inputs = vec![]; + // GCC index of a label equals its position in the array added to + // `outputs.len() + inputs.len()`. + let mut labels = vec![]; + // Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _` let mut clobbers = vec![]; @@ -269,6 +273,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // some targets to add a leading underscore (Mach-O). constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len(); } + + InlineAsmOperandRef::Label { label } => { + labels.push(label); + } } } @@ -368,6 +376,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { .. } => { // processed in the previous pass } + + InlineAsmOperandRef::Label { .. } => { + // processed in the previous pass + } } } @@ -454,6 +466,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { ref string } => { template_str.push_str(string); } + + InlineAsmOperandRef::Label { label } => { + let label_gcc_index = labels.iter() + .position(|&l| l == label) + .expect("wrong rust index"); + let gcc_index = label_gcc_index + outputs.len() + inputs.len(); + push_to_template(Some('l'), gcc_index); + } } } } @@ -466,7 +486,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // 4. Generate Extended Asm block let block = self.llbb(); - let extended_asm = block.add_extended_asm(None, &template_str); + let extended_asm = if let Some(dest) = dest { + assert!(!labels.is_empty()); + block.end_with_extended_asm_goto(None, &template_str, &labels, Some(dest)) + } else { + block.add_extended_asm(None, &template_str) + }; for op in &outputs { extended_asm.add_output_operand(None, &op.to_constraint(), op.tmp_var); @@ -494,7 +519,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { if !options.contains(InlineAsmOptions::NOSTACK) { // TODO(@Commeownist): figure out how to align stack } - if options.contains(InlineAsmOptions::NORETURN) { + if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) { let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable"); let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) }; self.call(self.type_void(), None, None, builtin_unreachable, &[], None); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index a413466093bed..f5d0b3c465729 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -28,7 +28,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, - dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, + dest: Option, + catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -165,6 +166,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } // Build the template string + let mut labels = vec![]; let mut template_str = String::new(); for piece in template { match *piece { @@ -205,6 +207,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // Only emit the raw symbol name template_str.push_str(&format!("${{{}:c}}", op_idx[&operand_idx])); } + InlineAsmOperandRef::Label { label } => { + template_str.push_str(&format!("${{{}:l}}", constraints.len())); + constraints.push("!i".to_owned()); + labels.push(label); + } } } } @@ -292,12 +299,14 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { &constraints.join(","), &inputs, output_type, + &labels, volatile, alignstack, dialect, line_spans, options.contains(InlineAsmOptions::MAY_UNWIND), - dest_catch_funclet, + dest, + catch_funclet, ) .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed")); @@ -317,7 +326,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); // Switch to the 'normal' basic block if we did an `invoke` instead of a `call` - if let Some((dest, _, _)) = dest_catch_funclet { + if let Some(dest) = dest { self.switch_to_block(dest); } @@ -415,16 +424,14 @@ pub(crate) fn inline_asm_call<'ll>( cons: &str, inputs: &[&'ll Value], output: &'ll llvm::Type, + labels: &[&'ll llvm::BasicBlock], volatile: bool, alignstack: bool, dia: llvm::AsmDialect, line_spans: &[Span], unwind: bool, - dest_catch_funclet: Option<( - &'ll llvm::BasicBlock, - &'ll llvm::BasicBlock, - Option<&Funclet<'ll>>, - )>, + dest: Option<&'ll llvm::BasicBlock>, + catch_funclet: Option<(&'ll llvm::BasicBlock, Option<&Funclet<'ll>>)>, ) -> Option<&'ll Value> { let volatile = if volatile { llvm::True } else { llvm::False }; let alignstack = if alignstack { llvm::True } else { llvm::False }; @@ -457,8 +464,10 @@ pub(crate) fn inline_asm_call<'ll>( can_throw, ); - let call = if let Some((dest, catch, funclet)) = dest_catch_funclet { - bx.invoke(fty, None, None, v, inputs, dest, catch, funclet) + let call = if !labels.is_empty() { + bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None) + } else if let Some((catch, funclet)) = catch_funclet { + bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet) } else { bx.call(fty, None, None, v, inputs, None) }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 23e6f054a7c1e..ee76038800fd3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -377,12 +377,14 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { constraint, inputs, self.type_void(), + &[], true, false, llvm::AsmDialect::Att, &[span], false, None, + None, ) .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`")); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c9a1e7789c27e..2eba489cbfbf8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Unreachable => None, }; - if let Some(cleanup) = unwind_target { + if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) { let ret_llbb = if let Some(target) = destination { fx.llbb(target) } else { @@ -277,11 +277,29 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { options, line_spans, instance, - Some((ret_llbb, cleanup, self.funclet(fx))), + Some(ret_llbb), + None, + ); + MergingSucc::False + } else if let Some(cleanup) = unwind_target { + let ret_llbb = if let Some(target) = destination { + fx.llbb(target) + } else { + fx.unreachable_block() + }; + + bx.codegen_inline_asm( + template, + operands, + options, + line_spans, + instance, + Some(ret_llbb), + Some((cleanup, self.funclet(fx))), ); MergingSucc::False } else { - bx.codegen_inline_asm(template, operands, options, line_spans, instance, None); + bx.codegen_inline_asm(template, operands, options, line_spans, instance, None, None); if let Some(target) = destination { self.funclet_br(fx, bx, target, mergeable_succ) @@ -1067,7 +1085,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operands: &[mir::InlineAsmOperand<'tcx>], options: ast::InlineAsmOptions, line_spans: &[Span], - destination: Option, + targets: &[mir::BasicBlock], unwind: mir::UnwindAction, instance: Instance<'_>, mergeable_succ: bool, @@ -1119,8 +1137,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::InlineAsmOperand::SymStatic { def_id } => { InlineAsmOperandRef::SymStatic { def_id } } - mir::InlineAsmOperand::Label { target_index: _ } => { - todo!(); + mir::InlineAsmOperand::Label { target_index } => { + InlineAsmOperandRef::Label { label: self.llbb(targets[target_index]) } } }) .collect(); @@ -1132,7 +1150,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &operands, options, line_spans, - destination, + if options.contains(InlineAsmOptions::NORETURN) { + None + } else { + targets.get(0).copied() + }, unwind, instance, mergeable_succ, @@ -1298,7 +1320,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { operands, options, line_spans, - targets.get(0).copied(), + targets, unwind, self.instance, mergeable_succ(), diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index c2ae74b18d81e..8d67b626bbdb5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -33,6 +33,9 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { SymStatic { def_id: DefId, }, + Label { + label: B::BasicBlock, + }, } #[derive(Debug)] @@ -51,7 +54,8 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, - dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, + dest: Option, + catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>, ); } From 5e4e3d790bb5e53b31abf58fd0e2be557c28d496 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Dec 2023 04:44:01 +0000 Subject: [PATCH 206/613] Ensure asm noreturn works with labels --- compiler/rustc_hir_typeck/src/expr.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 614761c03bd61..ba74476c36dc7 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3243,6 +3243,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { + let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN); + for (op, _op_sp) in asm.operands { match op { hir::InlineAsmOperand::In { expr, .. } => { @@ -3265,15 +3267,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} hir::InlineAsmOperand::SymStatic { .. } => {} hir::InlineAsmOperand::Label { block } => { - self.check_block_no_value(block); + let previous_diverges = self.diverges.get(); + + // The label blocks should have unit return value or diverge. + let ty = + self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit)); + if !ty.is_never() { + self.demand_suptype(block.span, self.tcx.types.unit, ty); + diverge = false; + } + + // We need this to avoid false unreachable warning when a label diverges. + self.diverges.set(previous_diverges); } } } - if asm.options.contains(ast::InlineAsmOptions::NORETURN) { - self.tcx.types.never - } else { - Ty::new_unit(self.tcx) - } + + if diverge { self.tcx.types.never } else { self.tcx.types.unit } } fn check_offset_of( From 31f078ea9941ce89f1f5ab5fb1239bbbddfe4d49 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Dec 2023 04:44:22 +0000 Subject: [PATCH 207/613] Forbid asm unwind to work with labels --- compiler/rustc_builtin_macros/messages.ftl | 2 ++ compiler/rustc_builtin_macros/src/asm.rs | 7 +++++++ compiler/rustc_builtin_macros/src/errors.rs | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index dda466b026d91..32e065ada51b1 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -19,6 +19,8 @@ builtin_macros_asm_expected_other = expected operand, {$is_global_asm -> builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names +builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option + builtin_macros_asm_modifier_invalid = asm template modifier must be a single character builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 93eb3a9a43ee3..85f009f7e63cd 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -245,6 +245,7 @@ pub fn parse_asm_args<'a>( let mut have_real_output = false; let mut outputs_sp = vec![]; let mut regclass_outputs = vec![]; + let mut labels_sp = vec![]; for (op, op_sp) in &args.operands { match op { ast::InlineAsmOperand::Out { reg, expr, .. } @@ -262,6 +263,9 @@ pub fn parse_asm_args<'a>( regclass_outputs.push(*op_sp); } } + ast::InlineAsmOperand::Label { .. } => { + labels_sp.push(*op_sp); + } _ => {} } } @@ -273,6 +277,9 @@ pub fn parse_asm_args<'a>( // Bail out now since this is likely to confuse MIR return Err(err); } + if args.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() { + dcx.emit_err(errors::AsmMayUnwind { labels_sp }); + } if args.clobber_abis.len() > 0 { if is_global_asm { diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index f304a37be854b..51f7fcd628bc0 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -787,6 +787,13 @@ pub(crate) struct AsmNoReturn { pub(crate) outputs_sp: Vec, } +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_mayunwind)] +pub(crate) struct AsmMayUnwind { + #[primary_span] + pub(crate) labels_sp: Vec, +} + #[derive(Diagnostic)] #[diag(builtin_macros_global_asm_clobber_abi)] pub(crate) struct GlobalAsmClobberAbi { From 4677a71369f690b5aecf9380cf12074792f09a3f Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Wed, 27 Dec 2023 22:57:17 +0000 Subject: [PATCH 208/613] Add tests for asm goto --- tests/codegen/asm-goto.rs | 51 ++++++++ tests/ui/asm/parse-error.rs | 2 + tests/ui/asm/parse-error.stderr | 16 ++- tests/ui/asm/x86_64/bad-options.rs | 4 + tests/ui/asm/x86_64/bad-options.stderr | 38 +++--- tests/ui/asm/x86_64/goto.mirunsafeck.stderr | 23 ++++ tests/ui/asm/x86_64/goto.rs | 111 ++++++++++++++++++ tests/ui/asm/x86_64/goto.thirunsafeck.stderr | 23 ++++ .../ui/feature-gates/feature-gate-asm_goto.rs | 10 ++ .../feature-gate-asm_goto.stderr | 13 ++ 10 files changed, 270 insertions(+), 21 deletions(-) create mode 100644 tests/codegen/asm-goto.rs create mode 100644 tests/ui/asm/x86_64/goto.mirunsafeck.stderr create mode 100644 tests/ui/asm/x86_64/goto.rs create mode 100644 tests/ui/asm/x86_64/goto.thirunsafeck.stderr create mode 100644 tests/ui/feature-gates/feature-gate-asm_goto.rs create mode 100644 tests/ui/feature-gates/feature-gate-asm_goto.stderr diff --git a/tests/codegen/asm-goto.rs b/tests/codegen/asm-goto.rs new file mode 100644 index 0000000000000..e522d0da5b405 --- /dev/null +++ b/tests/codegen/asm-goto.rs @@ -0,0 +1,51 @@ +//@ compile-flags: -O +//@ only-x86_64 + +#![crate_type = "rlib"] +#![feature(asm_goto)] + +use std::arch::asm; + +#[no_mangle] +pub extern "C" fn panicky() {} + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + println!(); + } +} + +// CHECK-LABEL: @asm_goto +#[no_mangle] +pub unsafe fn asm_goto() { + // CHECK: callbr void asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]] + asm!("jmp {}", label {}); +} + +// CHECK-LABEL: @asm_goto_with_outputs +#[no_mangle] +pub unsafe fn asm_goto_with_outputs() -> u64 { + let out: u64; + // CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]] + asm!("{} /* {} */", out(reg) out, label { return 1; }); + // CHECK: [[JUMPBB]]: + // CHECK-NEXT: [[RET:%.+]] = phi i64 [ [[RES]], %[[FALLTHROUGHBB]] ], [ 1, %start ] + // CHECK-NEXT: ret i64 [[RET]] + out +} + +// CHECK-LABEL: @asm_goto_noreturn +#[no_mangle] +pub unsafe fn asm_goto_noreturn() -> u64 { + let out: u64; + // CHECK: callbr void asm sideeffect alignstack inteldialect " + // CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]] + asm!("jmp {}", label { return 1; }, options(noreturn)); + // CHECK: [[JUMPBB]]: + // CHECK-NEXT: ret i64 1 + out +} diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs index 6f32293511bf6..a0251c6763ba4 100644 --- a/tests/ui/asm/parse-error.rs +++ b/tests/ui/asm/parse-error.rs @@ -142,3 +142,5 @@ global_asm!(format!("{{{}}}", 0), const FOO); //~^ ERROR asm template must be a string literal global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); //~^ ERROR asm template must be a string literal +global_asm!("{}", label {}); +//~^ ERROR expected operand, options, or additional template string diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr index 075d28e176ad8..80ee5191dbbe9 100644 --- a/tests/ui/asm/parse-error.stderr +++ b/tests/ui/asm/parse-error.stderr @@ -176,17 +176,17 @@ LL | asm!("{a}", a = const foo, a = const bar); | = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"` -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""` +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""` --> $DIR/parse-error.rs:82:29 | LL | asm!("", options(), ""); - | ^^ expected one of 9 possible tokens + | ^^ expected one of 10 possible tokens -error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"` +error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"` --> $DIR/parse-error.rs:84:33 | LL | asm!("{}", in(reg) foo, "{}", out(reg) foo); - | ^^^^ expected one of 9 possible tokens + | ^^^^ expected one of 10 possible tokens error: asm template must be a string literal --> $DIR/parse-error.rs:86:14 @@ -362,6 +362,12 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR); | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) +error: expected operand, options, or additional template string + --> $DIR/parse-error.rs:145:19 + | +LL | global_asm!("{}", label {}); + | ^^^^^^^^ expected operand, options, or additional template string + error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:39:37 | @@ -407,6 +413,6 @@ LL | let mut bar = 0; LL | asm!("{a}", a = const foo, a = const bar); | ^^^ non-constant value -error: aborting due to 63 previous errors +error: aborting due to 64 previous errors For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs index a6d5022ecf130..f9cc13cfc5a8b 100644 --- a/tests/ui/asm/x86_64/bad-options.rs +++ b/tests/ui/asm/x86_64/bad-options.rs @@ -1,5 +1,7 @@ //@ only-x86_64 +#![feature(asm_unwind, asm_goto)] + use std::arch::{asm, global_asm}; fn main() { @@ -14,6 +16,8 @@ fn main() { //~^ ERROR asm with the `pure` option must have at least one output asm!("{}", out(reg) foo, options(noreturn)); //~^ ERROR asm outputs are not allowed with the `noreturn` option + asm!("{}", label {}, options(may_unwind)); + //~^ ERROR asm labels are not allowed with the `may_unwind` option } unsafe { diff --git a/tests/ui/asm/x86_64/bad-options.stderr b/tests/ui/asm/x86_64/bad-options.stderr index e2351840eef21..aa167e7913c3e 100644 --- a/tests/ui/asm/x86_64/bad-options.stderr +++ b/tests/ui/asm/x86_64/bad-options.stderr @@ -1,35 +1,41 @@ error: the `nomem` and `readonly` options are mutually exclusive - --> $DIR/bad-options.rs:8:18 + --> $DIR/bad-options.rs:10:18 | LL | asm!("", options(nomem, readonly)); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: the `pure` and `noreturn` options are mutually exclusive - --> $DIR/bad-options.rs:10:18 + --> $DIR/bad-options.rs:12:18 | LL | asm!("", options(pure, nomem, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm with the `pure` option must have at least one output - --> $DIR/bad-options.rs:10:18 + --> $DIR/bad-options.rs:12:18 | LL | asm!("", options(pure, nomem, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm with the `pure` option must have at least one output - --> $DIR/bad-options.rs:13:33 + --> $DIR/bad-options.rs:15:33 | LL | asm!("{}", in(reg) foo, options(pure, nomem)); | ^^^^^^^^^^^^^^^^^^^^ error: asm outputs are not allowed with the `noreturn` option - --> $DIR/bad-options.rs:15:20 + --> $DIR/bad-options.rs:17:20 | LL | asm!("{}", out(reg) foo, options(noreturn)); | ^^^^^^^^^^^^ +error: asm labels are not allowed with the `may_unwind` option + --> $DIR/bad-options.rs:19:20 + | +LL | asm!("{}", label {}, options(may_unwind)); + | ^^^^^^^^ + error: asm with `clobber_abi` must specify explicit registers for outputs - --> $DIR/bad-options.rs:22:20 + --> $DIR/bad-options.rs:26:20 | LL | asm!("{}", out(reg) foo, clobber_abi("C")); | ^^^^^^^^^^^^ ---------------- clobber_abi @@ -37,7 +43,7 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C")); | generic outputs error: asm with `clobber_abi` must specify explicit registers for outputs - --> $DIR/bad-options.rs:24:20 + --> $DIR/bad-options.rs:28:20 | LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | ^^^^^^^^^^^^ ---------------- ---------------- clobber_abi @@ -46,43 +52,43 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | generic outputs error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` - --> $DIR/bad-options.rs:31:25 + --> $DIR/bad-options.rs:35:25 | LL | global_asm!("", options(nomem)); | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` - --> $DIR/bad-options.rs:33:25 + --> $DIR/bad-options.rs:37:25 | LL | global_asm!("", options(readonly)); | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` - --> $DIR/bad-options.rs:35:25 + --> $DIR/bad-options.rs:39:25 | LL | global_asm!("", options(noreturn)); | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `pure` - --> $DIR/bad-options.rs:37:25 + --> $DIR/bad-options.rs:41:25 | LL | global_asm!("", options(pure)); | ^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` - --> $DIR/bad-options.rs:39:25 + --> $DIR/bad-options.rs:43:25 | LL | global_asm!("", options(nostack)); | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` - --> $DIR/bad-options.rs:41:25 + --> $DIR/bad-options.rs:45:25 | LL | global_asm!("", options(preserves_flags)); | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: invalid ABI for `clobber_abi` - --> $DIR/bad-options.rs:20:18 + --> $DIR/bad-options.rs:24:18 | LL | asm!("", clobber_abi("foo")); | ^^^^^^^^^^^^^^^^^^ @@ -90,12 +96,12 @@ LL | asm!("", clobber_abi("foo")); = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64` error: `C` ABI specified multiple times - --> $DIR/bad-options.rs:24:52 + --> $DIR/bad-options.rs:28:52 | LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | ---------------- ^^^^^^^^^^^^^^^^ | | | previously specified here -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/asm/x86_64/goto.mirunsafeck.stderr b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr new file mode 100644 index 0000000000000..fe189c14f0a7c --- /dev/null +++ b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr @@ -0,0 +1,23 @@ +warning: unreachable statement + --> $DIR/goto.rs:99:9 + | +LL | / asm!( +LL | | "jmp {}", +LL | | label { +LL | | return; +LL | | }, +LL | | options(noreturn) +LL | | ); + | |_________- any code following this expression is unreachable +LL | unreachable!(); + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/goto.rs:89:8 + | +LL | #[warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs new file mode 100644 index 0000000000000..6a567efbb2c7e --- /dev/null +++ b/tests/ui/asm/x86_64/goto.rs @@ -0,0 +1,111 @@ +//@ only-x86_64 +//@ run-pass +//@ needs-asm-support +//@ revisions: mirunsafeck thirunsafeck +//@ [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![deny(unreachable_code)] +#![feature(asm_goto)] + +use std::arch::asm; + +fn goto_fallthough() { + unsafe { + asm!( + "/* {} */", + label { + unreachable!(); + } + ) + } +} + +fn goto_jump() { + unsafe { + let mut value = false; + asm!( + "jmp {}", + label { + value = true; + } + ); + assert!(value); + } +} + +// asm goto with outputs cause miscompilation in LLVM. UB can be triggered +// when outputs are used inside the label block when optimisation is enabled. +// See: https://github.com/llvm/llvm-project/issues/74483 +/* +fn goto_out_fallthrough() { + unsafe { + let mut out: usize; + asm!( + "lea {}, [{} + 1]", + "/* {} */", + out(reg) out, + in(reg) 0x12345678usize, + label { + unreachable!(); + } + ); + assert_eq!(out, 0x12345679); + } +} + +fn goto_out_jump() { + unsafe { + let mut value = false; + let mut out: usize; + asm!( + "lea {}, [{} + 1]", + "jmp {}", + out(reg) out, + in(reg) 0x12345678usize, + label { + value = true; + assert_eq!(out, 0x12345679); + } + ); + assert!(value); + } +} +*/ + +fn goto_noreturn() { + unsafe { + let a; + asm!( + "jmp {}", + label { + a = 1; + }, + options(noreturn) + ); + assert_eq!(a, 1); + } +} + +#[warn(unreachable_code)] +fn goto_noreturn_diverge() { + unsafe { + asm!( + "jmp {}", + label { + return; + }, + options(noreturn) + ); + unreachable!(); + //~^ WARN unreachable statement + } +} + +fn main() { + goto_fallthough(); + goto_jump(); + // goto_out_fallthrough(); + // goto_out_jump(); + goto_noreturn(); + goto_noreturn_diverge(); +} diff --git a/tests/ui/asm/x86_64/goto.thirunsafeck.stderr b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr new file mode 100644 index 0000000000000..fe189c14f0a7c --- /dev/null +++ b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr @@ -0,0 +1,23 @@ +warning: unreachable statement + --> $DIR/goto.rs:99:9 + | +LL | / asm!( +LL | | "jmp {}", +LL | | label { +LL | | return; +LL | | }, +LL | | options(noreturn) +LL | | ); + | |_________- any code following this expression is unreachable +LL | unreachable!(); + | ^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/goto.rs:89:8 + | +LL | #[warn(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.rs b/tests/ui/feature-gates/feature-gate-asm_goto.rs new file mode 100644 index 0000000000000..beac4590349f6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_goto.rs @@ -0,0 +1,10 @@ +//@ only-x86_64 + +use std::arch::asm; + +fn main() { + unsafe { + asm!("jmp {}", label {}); + //~^ ERROR label operands for inline assembly are unstable + } +} diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.stderr b/tests/ui/feature-gates/feature-gate-asm_goto.stderr new file mode 100644 index 0000000000000..62fd1a320d3c0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-asm_goto.stderr @@ -0,0 +1,13 @@ +error[E0658]: label operands for inline assembly are unstable + --> $DIR/feature-gate-asm_goto.rs:7:24 + | +LL | asm!("jmp {}", label {}); + | ^^^^^^^^ + | + = note: see issue #119364 for more information + = help: add `#![feature(asm_goto)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 84bc9e9e369ba23a244d9a6b8c047e6f1e0d6e7a Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 28 Dec 2023 18:57:15 +0000 Subject: [PATCH 209/613] Add asm-goto to unstable book --- .../src/language-features/asm-goto.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/asm-goto.md diff --git a/src/doc/unstable-book/src/language-features/asm-goto.md b/src/doc/unstable-book/src/language-features/asm-goto.md new file mode 100644 index 0000000000000..a9ad5e837448a --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-goto.md @@ -0,0 +1,24 @@ +# `asm_goto` + +The tracking issue for this feature is: [#119364] + +[#119364]: https://github.com/rust-lang/rust/issues/119364 + +------------------------ + +This feature adds a `label ` operand type to `asm!`. + +Example: +```rust,ignore (partial-example, x86-only) + +unsafe { + asm!( + "jmp {}", + label { + println!("Jumped from asm!"); + } + ); +} +``` + +The block must have unit type. From 626a5f589208d544537f411724f35e6b841790e4 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 24 Feb 2024 17:12:25 +0000 Subject: [PATCH 210/613] Add assertions and clarify asm-goto with noreturn --- compiler/rustc_codegen_llvm/src/asm.rs | 1 + compiler/rustc_codegen_ssa/src/mir/block.rs | 1 + src/doc/unstable-book/src/language-features/asm-goto.md | 8 +++++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index f5d0b3c465729..74539d4d49570 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -465,6 +465,7 @@ pub(crate) fn inline_asm_call<'ll>( ); let call = if !labels.is_empty() { + assert!(catch_funclet.is_none()); bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None) } else if let Some((catch, funclet)) = catch_funclet { bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 2eba489cbfbf8..8a2f91c082e27 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -265,6 +265,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { }; if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) { + assert!(unwind_target.is_none()); let ret_llbb = if let Some(target) = destination { fx.llbb(target) } else { diff --git a/src/doc/unstable-book/src/language-features/asm-goto.md b/src/doc/unstable-book/src/language-features/asm-goto.md index a9ad5e837448a..d72eb7c0c6ef1 100644 --- a/src/doc/unstable-book/src/language-features/asm-goto.md +++ b/src/doc/unstable-book/src/language-features/asm-goto.md @@ -21,4 +21,10 @@ unsafe { } ``` -The block must have unit type. +The block must have unit type or diverge. + +When `label ` is used together with `noreturn` option, it means that the +assembly will not fallthrough. It's allowed to jump to a label within the +assembly. In this case, the entire `asm!` expression will have an unit type as +opposed to diverging, if not all label blocks diverge. The `asm!` expression +still diverges if `noreturn` option is used and all label blocks diverge. From 9bb11094783654fdbe5ea91d3a126fbbf79f5ade Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 23 Feb 2024 18:26:39 +0100 Subject: [PATCH 211/613] remove platform-intrinsics ABI; make SIMD intrinsics be regular intrinsics --- example/float-minmax-pass.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/float-minmax-pass.rs b/example/float-minmax-pass.rs index 80a2776ca1e2f..eebd77083ec64 100644 --- a/example/float-minmax-pass.rs +++ b/example/float-minmax-pass.rs @@ -4,14 +4,14 @@ // Test that the simd_f{min,max} intrinsics produce the correct results. -#![feature(repr_simd, platform_intrinsics)] +#![feature(repr_simd, intrinsics)] #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] struct f32x4(pub f32, pub f32, pub f32, pub f32); -extern "platform-intrinsic" { +extern "intrinsic" { fn simd_fmin(x: T, y: T) -> T; fn simd_fmax(x: T, y: T) -> T; } From 08e4eafa491fc5f3e25fe78ffdb79b5f63e37f8a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 23 Feb 2024 18:36:24 +0100 Subject: [PATCH 212/613] fix use of platform_intrinsics in tests --- example/float-minmax-pass.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/example/float-minmax-pass.rs b/example/float-minmax-pass.rs index eebd77083ec64..a71217a554b57 100644 --- a/example/float-minmax-pass.rs +++ b/example/float-minmax-pass.rs @@ -4,17 +4,14 @@ // Test that the simd_f{min,max} intrinsics produce the correct results. -#![feature(repr_simd, intrinsics)] +#![feature(repr_simd, core_intrinsics)] #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] struct f32x4(pub f32, pub f32, pub f32, pub f32); -extern "intrinsic" { - fn simd_fmin(x: T, y: T) -> T; - fn simd_fmax(x: T, y: T) -> T; -} +use std::intrinsics::simd::*; fn main() { let x = f32x4(1.0, 2.0, 3.0, 4.0); From fcb86c871f5062b12925afc77935166dccf30ce4 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 20 Feb 2024 16:09:49 -0300 Subject: [PATCH 213/613] Cranelift: Don't use raw-dylib in std --- .../0029-stdlib-rawdylib-processprng.patch | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 patches/0029-stdlib-rawdylib-processprng.patch diff --git a/patches/0029-stdlib-rawdylib-processprng.patch b/patches/0029-stdlib-rawdylib-processprng.patch new file mode 100644 index 0000000000000..6af11e54d88af --- /dev/null +++ b/patches/0029-stdlib-rawdylib-processprng.patch @@ -0,0 +1,47 @@ +From 9f65e742ba3e41474e6126c6c4469c48eaa6ca7e Mon Sep 17 00:00:00 2001 +From: Chris Denton +Date: Tue, 20 Feb 2024 16:01:40 -0300 +Subject: [PATCH] Don't use raw-dylib in std + +--- + library/std/src/sys/pal/windows/c.rs | 2 +- + library/std/src/sys/pal/windows/rand.rs | 3 +-- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs +index ad8e01bfa9b..9ca8e4c16ce 100644 +--- a/library/std/src/sys/pal/windows/c.rs ++++ b/library/std/src/sys/pal/windows/c.rs +@@ -323,7 +323,7 @@ pub unsafe fn NtWriteFile( + + // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library. + cfg_if::cfg_if! { +-if #[cfg(not(target_vendor = "win7"))] { ++if #[cfg(any())] { + #[cfg(target_arch = "x86")] + #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")] + extern "system" { +diff --git a/library/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs +index e427546222a..f2fe42a4d51 100644 +--- a/library/std/src/sys/pal/windows/rand.rs ++++ b/library/std/src/sys/pal/windows/rand.rs +@@ -2,7 +2,7 @@ + use core::mem; + use core::ptr; + +-#[cfg(not(target_vendor = "win7"))] ++#[cfg(any())] + #[inline] + pub fn hashmap_random_keys() -> (u64, u64) { + let mut v = (0, 0); +@@ -13,7 +13,6 @@ pub fn hashmap_random_keys() -> (u64, u64) { + v + } + +-#[cfg(target_vendor = "win7")] + pub fn hashmap_random_keys() -> (u64, u64) { + use crate::ffi::c_void; + use crate::io; +-- +2.42.0.windows.2 + From f142476cf3f0c0c2296c82836fd4c7c86e20d0db Mon Sep 17 00:00:00 2001 From: David Thomas Date: Sun, 25 Feb 2024 14:09:30 +0000 Subject: [PATCH 214/613] Fix Hash impl --- library/core/src/any.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index adc45038148e8..a4252d0c9e03c 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -662,7 +662,7 @@ impl hash::Hash for TypeId { // - It is correct to do so -- only hashing a subset of `self` is still // with an `Eq` implementation that considers the entire value, as // ours does. - self.t.0.hash(state); + self.t.1.hash(state); } } From 66e475794d27f58d3fa6928c0c8858c42302379e Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:22:09 +0100 Subject: [PATCH 215/613] Add `ast::ExprKind::Dummy` --- clippy_utils/src/ast_utils.rs | 1 + clippy_utils/src/sugg.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 0467a8a65709a..81a26a12009d1 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -144,6 +144,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Paren(l), _) => eq_expr(l, r), (_, Paren(r)) => eq_expr(l, r), (Err, Err) => true, + (Dummy, _) | (_, Dummy) => unreachable!("comparing `ExprKind::Dummy`"), (Try(l), Try(r)) | (Await(l, _), Await(r, _)) => eq_expr(l, r), (Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)), (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)), diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index b355e66b7b12a..7b1b0388b29f3 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -222,7 +222,8 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::Await(..) - | ast::ExprKind::Err => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), + | ast::ExprKind::Err + | ast::ExprKind::Dummy => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( AssocOp::DotDot, lhs.as_ref().map_or("".into(), |lhs| { From ef2039effc824936a673cda3ae17ec926e686656 Mon Sep 17 00:00:00 2001 From: Lieselotte <52315535+she3py@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:22:11 +0100 Subject: [PATCH 216/613] Add `ErrorGuaranteed` to `ast::ExprKind::Err` --- clippy_utils/src/ast_utils.rs | 2 +- clippy_utils/src/sugg.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 81a26a12009d1..c52a4e0d8b7c7 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -143,7 +143,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { match (&l.kind, &r.kind) { (Paren(l), _) => eq_expr(l, r), (_, Paren(r)) => eq_expr(l, r), - (Err, Err) => true, + (Err(_), Err(_)) => true, (Dummy, _) | (_, Dummy) => unreachable!("comparing `ExprKind::Dummy`"), (Try(l), Try(r)) | (Await(l, _), Await(r, _)) => eq_expr(l, r), (Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)), diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 7b1b0388b29f3..1f6446b8746e6 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -222,7 +222,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::Await(..) - | ast::ExprKind::Err + | ast::ExprKind::Err(_) | ast::ExprKind::Dummy => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( AssocOp::DotDot, From b921a34f1738a615c17db513868b6c5219f32893 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 25 Feb 2024 23:47:10 -0800 Subject: [PATCH 217/613] Fix stable feature name and stabilization version of Read for &Stdin --- library/std/src/io/stdio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index e929eaa639696..6920281f24bf2 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -445,7 +445,7 @@ impl Read for Stdin { } } -#[stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "read_shared_stdin", since = "CURRENT_RUSTC_VERSION")] impl Read for &Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) From b18280f9d5d07ff1a1b5352924c383c1ed3024e9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 25 Feb 2024 23:50:00 -0800 Subject: [PATCH 218/613] Fill in Read::read_buf for &Stdin --- library/std/src/io/stdio.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 6920281f24bf2..19ed03056a2f9 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -450,6 +450,9 @@ impl Read for &Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.lock().read(buf) } + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + self.lock().read_buf(buf) + } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.lock().read_vectored(bufs) } From 65f778976177ca797912218db16be178cd9d0a74 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Feb 2024 18:51:22 +0100 Subject: [PATCH 219/613] rename 'try' intrinsic to 'catch_unwind' --- src/intrinsics/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 199d5df29e7d0..84269ec294263 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -23,7 +23,7 @@ use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::GenericArgsRef; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{sym, Symbol}; pub(crate) use self::llvm::codegen_llvm_intrinsic_call; use crate::prelude::*; @@ -1132,7 +1132,7 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, val); } - kw::Try => { + sym::catch_unwind => { intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic); let f = f.load_scalar(fx); let data = data.load_scalar(fx); From a06a87b37dfc4aa9e0043d72b16df8051f92e98c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Feb 2024 18:51:22 +0100 Subject: [PATCH 220/613] rename 'try' intrinsic to 'catch_unwind' --- src/intrinsic/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f162ef831b768..d43f5d74757ae 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature="master")] use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; -use rustc_span::{Span, Symbol, symbol::kw, sym}; +use rustc_span::{Span, Symbol, sym}; use rustc_target::abi::HasDataLayout; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::PanicStrategy; @@ -129,7 +129,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let res = self.context.new_call(None, builtin, &[a]); self.icmp(IntPredicate::IntEQ, res, self.const_i32(0)) } - kw::Try => { + sym::catch_unwind => { try_intrinsic( self, args[0].immediate(), From 7e6dccc47d257727c8135ec0d933155d42463e0e Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 26 Feb 2024 11:26:13 -0300 Subject: [PATCH 221/613] Win10: Use GetSystemTimePreciseAsFileTime directly --- library/std/src/sys/pal/windows/c.rs | 1 + library/std/src/sys/pal/windows/c/bindings.txt | 1 + library/std/src/sys/pal/windows/c/windows_sys.rs | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index b007796722baf..0f9754b22b7e1 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -346,6 +346,7 @@ compat_fn_with_fallback! { // >= Win8 / Server 2012 // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime + #[cfg(target_vendor = "win7")] pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () { GetSystemTimeAsFileTime(lpsystemtimeasfiletime) } diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index ab2a8caf5dfd9..5be7bee62f63b 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2475,6 +2475,7 @@ Windows.Win32.System.Pipes.PIPE_WAIT Windows.Win32.System.SystemInformation.GetSystemDirectoryW Windows.Win32.System.SystemInformation.GetSystemInfo Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime +Windows.Win32.System.SystemInformation.GetSystemTimePreciseAsFileTime Windows.Win32.System.SystemInformation.GetWindowsDirectoryW Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE Windows.Win32.System.SystemInformation.SYSTEM_INFO diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 8eb779373f7e4..b18792849b8f9 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -345,6 +345,10 @@ extern "system" { pub fn GetSystemTimeAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> (); } #[link(name = "kernel32")] +extern "system" { + pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> (); +} +#[link(name = "kernel32")] extern "system" { pub fn GetTempPathW(nbufferlength: u32, lpbuffer: PWSTR) -> u32; } From 7f34119c1a6ec425f549e12f1490555acda74c65 Mon Sep 17 00:00:00 2001 From: 823984418 <823984418@qq.com> Date: Mon, 26 Feb 2024 22:37:04 +0800 Subject: [PATCH 222/613] remove useless lifetime of ArchiveBuilder --- src/archive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/archive.rs b/src/archive.rs index 11fa074f5ac79..73ff0c37b6656 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -10,7 +10,7 @@ use rustc_session::cstore::DllImport; pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { - fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) } From c460cf173736323fca63a4e1e6554f3a749b6691 Mon Sep 17 00:00:00 2001 From: 823984418 <823984418@qq.com> Date: Mon, 26 Feb 2024 22:37:04 +0800 Subject: [PATCH 223/613] remove useless lifetime of ArchiveBuilder --- src/archive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/archive.rs b/src/archive.rs index 5a29bc18def54..414d3db1c51a1 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -8,7 +8,7 @@ use rustc_session::Session; pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { - fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) } From eb40adbd4604e86a1b0bd3c89d71cec3d2a7d077 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 26 Feb 2024 12:01:55 -0300 Subject: [PATCH 224/613] Add shim for GetSystemTimePreciseAsFileTime This is exactly the same as GetSystemTimeAsFileTime except that it promises maximum precision. --- src/tools/miri/src/shims/time.rs | 5 +++-- src/tools/miri/src/shims/windows/foreign_items.rs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 13ce9d119bc3b..4535bcf6dfedd 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -110,12 +110,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { #[allow(non_snake_case, clippy::arithmetic_side_effects)] fn GetSystemTimeAsFileTime( &mut self, + shim_name: &str, LPFILETIME_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - this.assert_target_os("windows", "GetSystemTimeAsFileTime"); - this.check_no_isolation("`GetSystemTimeAsFileTime`")?; + this.assert_target_os("windows", shim_name); + this.check_no_isolation(shim_name)?; let filetime = this.deref_pointer_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?; diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index fdd7fc5fad4e8..15ddd8a584699 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -246,11 +246,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Time related shims - "GetSystemTimeAsFileTime" => { + "GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => { #[allow(non_snake_case)] let [LPFILETIME] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.GetSystemTimeAsFileTime(LPFILETIME)?; + this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?; } "QueryPerformanceCounter" => { #[allow(non_snake_case)] From 05a6f65d81978fa9db4fec8c6a54bd894c9eb74d Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Fri, 16 Feb 2024 09:32:55 +0100 Subject: [PATCH 225/613] Update a test to support Symbol Mangling V0 --- tests/codegen/debuginfo-inline-callsite-location.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs index 833e8c0df912c..f690c9c0937ff 100644 --- a/tests/codegen/debuginfo-inline-callsite-location.rs +++ b/tests/codegen/debuginfo-inline-callsite-location.rs @@ -4,9 +4,9 @@ // can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail // calls to panic. -// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @{{[A-Za-z0-9_]+4core6option13unwrap_failed}} // CHECK-SAME: !dbg ![[#first_dbg:]] -// CHECK: tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E +// CHECK: tail call void @{{[A-Za-z0-9_]+4core6option13unwrap_failed}} // CHECK-SAME: !dbg ![[#second_dbg:]] // CHECK-DAG: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap" From d85642e6e80c448f8e3bf0797d381d434f472496 Mon Sep 17 00:00:00 2001 From: "Christopher B. Speir" Date: Sat, 24 Feb 2024 20:10:29 -0600 Subject: [PATCH 226/613] Alphabetize configuration options and lints in Clippy doc --- CHANGELOG.md | 110 ++-- book/src/lint_configuration.md | 884 ++++++++++++++++----------------- clippy_config/src/conf.rs | 6 +- clippy_config/src/metadata.rs | 4 +- 4 files changed, 504 insertions(+), 500 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26dce1f926572..e2b78c89dda6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5815,74 +5815,74 @@ Released 2018-09-13 [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset +[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates +[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments +[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes +[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement +[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero +[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests +[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests +[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args +[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings +[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests +[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception +[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests +[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles +[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates +[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars +[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts +[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports [`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed [`arithmetic-side-effects-allowed-binary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-binary [`arithmetic-side-effects-allowed-unary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-unary +[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold [`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api -[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv +[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types +[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish +[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold -[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold +[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros +[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods [`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names -[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline -[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline +[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types [`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents -[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold -[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold -[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold -[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack +[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send +[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow +[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames [`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold -[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold [`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold -[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold +[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold +[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold +[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability +[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold -[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit +[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else +[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools +[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size +[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools +[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length +[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds +[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold +[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items +[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv [`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit -[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold -[`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold +[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior +[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline +[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline +[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold [`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold -[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold -[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds -[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools -[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools -[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports -[`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros -[`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods -[`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types -[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions -[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive -[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else -[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish [`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces -[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames -[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts -[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send -[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length -[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types -[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size -[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests -[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests -[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests -[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests -[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold -[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability -[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args +[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold [`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const -[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items -[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold +[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack +[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold +[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold +[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit +[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold [`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size -[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception -[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars -[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold -[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement -[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes -[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings -[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments -[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates -[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles -[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates -[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow -[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items -[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior -[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero -[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports +[`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions +[`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive +[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold +[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold +[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 214a60d3bfdf7..a985346b3c05f 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -10,455 +10,505 @@ and lints affected. --- -## `arithmetic-side-effects-allowed` -Suppress checking of the passed type names in all types of operations. - -If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. +## `absolute-paths-allowed-crates` +Which crates to allow absolute paths from -#### Example +**Default Value:** `[]` -```toml -arithmetic-side-effects-allowed = ["SomeType", "AnotherType"] -``` +--- +**Affected lints:** +* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) -#### Noteworthy -A type, say `SomeType`, listed in this configuration has the same behavior of -`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. +## `absolute-paths-max-segments` +The maximum number of segments a path can have before being linted, anything above this will +be linted. -**Default Value:** `[]` +**Default Value:** `2` --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) -## `arithmetic-side-effects-allowed-binary` -Suppress checking of the passed type pair names in binary operations like addition or -multiplication. +## `accept-comment-above-attributes` +Whether to accept a safety comment to be placed above the attributes for the `unsafe` block -Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless -of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`. +**Default Value:** `true` -Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as -`["AnotherType", "SomeType"]`. +--- +**Affected lints:** +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) -#### Example -```toml -arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] -``` +## `accept-comment-above-statement` +Whether to accept a safety comment to be placed above the statement containing the `unsafe` block -**Default Value:** `[]` +**Default Value:** `true` --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) -## `arithmetic-side-effects-allowed-unary` -Suppress checking of the passed type names in unary operations like "negation" (`-`). +## `allow-comparison-to-zero` +Don't lint when comparing the result of a modulo operation to zero. -#### Example +**Default Value:** `true` -```toml -arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] -``` +--- +**Affected lints:** +* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic) -**Default Value:** `[]` + +## `allow-dbg-in-tests` +Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` + +**Default Value:** `false` --- **Affected lints:** -* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) +* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) -## `avoid-breaking-exported-api` -Suppress lints whenever the suggested change would cause breakage for other crates. +## `allow-expect-in-tests` +Whether `expect` should be allowed in test functions or `#[cfg(test)]` -**Default Value:** `true` +**Default Value:** `false` --- **Affected lints:** -* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) -* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) -* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) -* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) -* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) -* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) -* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) -* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) -* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) -* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) +* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) -## `msrv` -The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` +## `allow-mixed-uninlined-format-args` +Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` + +**Default Value:** `true` --- **Affected lints:** -* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) -* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) -* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) -* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) -* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) -* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) -* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) -* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) -* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) -* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) -* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) -* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) -* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) -* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) -* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) -* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) -* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) -* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) -* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) -* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) -* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) -* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) -* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) -* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) -* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) -* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) -* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) * [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) -* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) -* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) -* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) -* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) -* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) -* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) -* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) -* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) -* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) -* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) -* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) -* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) -* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) -* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) -* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) -* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) -* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) -* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) -## `cognitive-complexity-threshold` -The maximum cognitive complexity a function can have +## `allow-one-hash-in-raw-strings` +Whether to allow `r#""#` when `r""` can be used -**Default Value:** `25` +**Default Value:** `false` --- **Affected lints:** -* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) +* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) -## `excessive-nesting-threshold` -The maximum amount of nesting a block can reside in +## `allow-print-in-tests` +Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` -**Default Value:** `0` +**Default Value:** `false` --- **Affected lints:** -* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) +* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) +* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) -## `disallowed-names` -The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value -`".."` can be used as part of the list to indicate that the configured values should be appended to the -default configuration of Clippy. By default, any configuration will replace the default value. +## `allow-private-module-inception` +Whether to allow module inception if it's not public. -**Default Value:** `["foo", "baz", "quux"]` +**Default Value:** `false` --- **Affected lints:** -* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) +* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) -## `semicolon-inside-block-ignore-singleline` -Whether to lint only if it's multiline. +## `allow-unwrap-in-tests` +Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` **Default Value:** `false` --- **Affected lints:** -* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) +* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) -## `semicolon-outside-block-ignore-multiline` -Whether to lint only if it's singleline. +## `allowed-dotfiles` +Additional dotfiles (files or directories starting with a dot) to allow -**Default Value:** `false` +**Default Value:** `[]` --- **Affected lints:** -* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) +* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) -## `doc-valid-idents` -The list of words this lint should not consider as identifiers needing ticks. The value -`".."` can be used as part of the list to indicate, that the configured values should be appended to the -default configuration of Clippy. By default, any configuration will replace the default value. For example: -* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. -* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. +## `allowed-duplicate-crates` +A list of crate names to allow duplicates of -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `[]` --- **Affected lints:** -* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) +* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions) -## `too-many-arguments-threshold` -The maximum number of argument a function or method can have +## `allowed-idents-below-min-chars` +Allowed names below the minimum allowed characters. The value `".."` can be used as part of +the list to indicate, that the configured values should be appended to the default +configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `7` +**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]` --- **Affected lints:** -* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) -## `type-complexity-threshold` -The maximum complexity a type can have +## `allowed-scripts` +The list of unicode scripts allowed to be used in the scope. -**Default Value:** `250` +**Default Value:** `["Latin"]` --- **Affected lints:** -* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) +* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) -## `single-char-binding-names-threshold` -The maximum number of single char bindings a scope may have +## `allowed-wildcard-imports` +List of path segments allowed to have wildcard imports. -**Default Value:** `4` +#### Example + +```toml +allowed-wildcard-imports = [ "utils", "common" ] +``` + +#### Noteworthy + +1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`. +2. Paths with any segment that containing the word 'prelude' +are already allowed by default. + +**Default Value:** `[]` --- **Affected lints:** -* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) -## `too-large-for-stack` -The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap +## `arithmetic-side-effects-allowed` +Suppress checking of the passed type names in all types of operations. -**Default Value:** `200` +If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead. + +#### Example + +```toml +arithmetic-side-effects-allowed = ["SomeType", "AnotherType"] +``` + +#### Noteworthy + +A type, say `SomeType`, listed in this configuration has the same behavior of +`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. + +**Default Value:** `[]` --- **Affected lints:** -* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) -* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) -## `enum-variant-name-threshold` -The minimum number of enum variants for the lints about variant names to trigger +## `arithmetic-side-effects-allowed-binary` +Suppress checking of the passed type pair names in binary operations like addition or +multiplication. -**Default Value:** `3` +Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless +of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`. + +Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as +`["AnotherType", "SomeType"]`. + +#### Example + +```toml +arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]] +``` + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) + + +## `arithmetic-side-effects-allowed-unary` +Suppress checking of the passed type names in unary operations like "negation" (`-`). + +#### Example + +```toml +arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] +``` + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects) + + +## `array-size-threshold` +The maximum allowed size for arrays on the stack + +**Default Value:** `512000` --- **Affected lints:** +* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) +* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) + + +## `avoid-breaking-exported-api` +Suppress lints whenever the suggested change would cause breakage for other crates. + +**Default Value:** `true` + +--- +**Affected lints:** +* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection) * [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist) +* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option) +* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer) +* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex) +* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation) +* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +* [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps) +* [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention) -## `struct-field-name-threshold` -The minimum number of struct fields for the lints about field names to trigger +## `await-holding-invalid-types` -**Default Value:** `3` + +**Default Value:** `[]` --- **Affected lints:** -* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names) +* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) -## `enum-variant-size-threshold` -The maximum size of an enum's variant to avoid box suggestion +## `cargo-ignore-publish` +For internal testing only, ignores the current `publish` settings in the Cargo manifest. -**Default Value:** `200` +**Default Value:** `false` --- **Affected lints:** -* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) +* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata) -## `verbose-bit-mask-threshold` -The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' +## `check-private-items` +Whether to also run the listed lints on private items. -**Default Value:** `1` +**Default Value:** `false` --- **Affected lints:** -* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) +* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) +* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc) +* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) +* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc) -## `literal-representation-threshold` -The lower bound for linting decimal literals +## `cognitive-complexity-threshold` +The maximum cognitive complexity a function can have -**Default Value:** `16384` +**Default Value:** `25` --- **Affected lints:** -* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) +* [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity) -## `trivial-copy-size-limit` -The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by -reference. By default there is no limit +## `disallowed-macros` +The list of disallowed macros, written as fully qualified paths. + +**Default Value:** `[]` --- **Affected lints:** -* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) +* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) -## `pass-by-value-size-limit` -The minimum size (in bytes) to consider a type for passing by reference instead of by value. +## `disallowed-methods` +The list of disallowed methods, written as fully qualified paths. -**Default Value:** `256` +**Default Value:** `[]` --- **Affected lints:** -* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) +* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) -## `too-many-lines-threshold` -The maximum number of lines a function or method can have +## `disallowed-names` +The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value +`".."` can be used as part of the list to indicate that the configured values should be appended to the +default configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `100` +**Default Value:** `["foo", "baz", "quux"]` --- **Affected lints:** -* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) +* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names) -## `array-size-threshold` -The maximum allowed size for arrays on the stack +## `disallowed-types` +The list of disallowed types, written as fully qualified paths. -**Default Value:** `512000` +**Default Value:** `[]` --- **Affected lints:** -* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays) -* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays) +* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) -## `stack-size-threshold` -The maximum allowed stack size for functions in bytes +## `doc-valid-idents` +The list of words this lint should not consider as identifiers needing ticks. The value +`".."` can be used as part of the list to indicate, that the configured values should be appended to the +default configuration of Clippy. By default, any configuration will replace the default value. For example: +* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. +* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `512000` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** -* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) +* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown) -## `vec-box-size-threshold` -The size of the boxed type in bytes, where boxing in a `Vec` is allowed +## `enable-raw-pointer-heuristic-for-send` +Whether to apply the raw pointer heuristic to determine if a type is `Send`. -**Default Value:** `4096` +**Default Value:** `true` --- **Affected lints:** -* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) +* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) -## `max-trait-bounds` -The maximum number of bounds a trait can have to be linted +## `enforce-iter-loop-reborrow` +Whether to recommend using implicit into iter for reborrowed values. -**Default Value:** `3` +#### Example +```no_run +let mut vec = vec![1, 2, 3]; +let rmvec = &mut vec; +for _ in rmvec.iter() {} +for _ in rmvec.iter_mut() {} +``` + +Use instead: +```no_run +let mut vec = vec![1, 2, 3]; +let rmvec = &mut vec; +for _ in &*rmvec {} +for _ in &mut *rmvec {} +``` + +**Default Value:** `false` --- **Affected lints:** -* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop) -## `max-struct-bools` -The maximum number of bool fields a struct can have +## `enforced-import-renames` +The list of imports to always rename, a fully qualified path followed by the rename. -**Default Value:** `3` +**Default Value:** `[]` --- **Affected lints:** -* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) +* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) -## `max-fn-params-bools` -The maximum number of bool parameters a function can have +## `enum-variant-name-threshold` +The minimum number of enum variants for the lints about variant names to trigger **Default Value:** `3` --- **Affected lints:** -* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) +* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names) -## `warn-on-all-wildcard-imports` -Whether to allow certain wildcard imports (prelude, super in tests). +## `enum-variant-size-threshold` +The maximum size of an enum's variant to avoid box suggestion -**Default Value:** `false` +**Default Value:** `200` --- **Affected lints:** -* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant) -## `disallowed-macros` -The list of disallowed macros, written as fully qualified paths. +## `excessive-nesting-threshold` +The maximum amount of nesting a block can reside in -**Default Value:** `[]` +**Default Value:** `0` --- **Affected lints:** -* [`disallowed_macros`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros) +* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting) -## `disallowed-methods` -The list of disallowed methods, written as fully qualified paths. +## `future-size-threshold` +The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint -**Default Value:** `[]` +**Default Value:** `16384` --- **Affected lints:** -* [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods) +* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) -## `disallowed-types` -The list of disallowed types, written as fully qualified paths. +## `ignore-interior-mutability` +A list of paths to types that should be treated like `Arc`, i.e. ignored but +for the generic parameters for determining interior mutability -**Default Value:** `[]` +**Default Value:** `["bytes::Bytes"]` --- **Affected lints:** -* [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types) +* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) +* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) -## `unreadable-literal-lint-fractions` -Should the fraction of a decimal be linted to include separators. +## `large-error-threshold` +The maximum size of the `Err`-variant in a `Result` returned from a function -**Default Value:** `true` +**Default Value:** `128` --- **Affected lints:** -* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) +* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) -## `upper-case-acronyms-aggressive` -Enables verbose mode. Triggers if there is more than one uppercase char next to each other +## `literal-representation-threshold` +The lower bound for linting decimal literals -**Default Value:** `false` +**Default Value:** `16384` --- **Affected lints:** -* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) +* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation) ## `matches-for-let-else` @@ -472,163 +522,219 @@ be filtering for common types. * [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) -## `cargo-ignore-publish` -For internal testing only, ignores the current `publish` settings in the Cargo manifest. +## `max-fn-params-bools` +The maximum number of bool parameters a function can have -**Default Value:** `false` +**Default Value:** `3` --- **Affected lints:** -* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata) - +* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools) -## `standard-macro-braces` -Enforce the named macros always use the braces specified. -A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro -could be used with a full path two `MacroMatcher`s have to be added one with the full path -`crate_name::macro_name` and one with just the macro name. +## `max-include-file-size` +The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes -**Default Value:** `[]` +**Default Value:** `1000000` --- **Affected lints:** -* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) +* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) -## `enforced-import-renames` -The list of imports to always rename, a fully qualified path followed by the rename. +## `max-struct-bools` +The maximum number of bool fields a struct can have -**Default Value:** `[]` +**Default Value:** `3` --- **Affected lints:** -* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames) +* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools) -## `allowed-scripts` -The list of unicode scripts allowed to be used in the scope. +## `max-suggested-slice-pattern-length` +When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in +the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. +For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. -**Default Value:** `["Latin"]` +**Default Value:** `3` --- **Affected lints:** -* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) -## `enable-raw-pointer-heuristic-for-send` -Whether to apply the raw pointer heuristic to determine if a type is `Send`. +## `max-trait-bounds` +The maximum number of bounds a trait can have to be linted -**Default Value:** `true` +**Default Value:** `3` --- **Affected lints:** -* [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) -## `max-suggested-slice-pattern-length` -When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in -the slice pattern that is suggested. If more elements are necessary, the lint is suppressed. -For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements. +## `min-ident-chars-threshold` +Minimum chars an ident can have, anything below or equal to this will be linted. -**Default Value:** `3` +**Default Value:** `1` --- **Affected lints:** -* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) -## `await-holding-invalid-types` +## `missing-docs-in-crate-items` +Whether to **only** check for missing documentation in items visible within the current +crate. For example, `pub(crate)` items. +**Default Value:** `false` -**Default Value:** `[]` +--- +**Affected lints:** +* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) + + +## `msrv` +The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` --- **Affected lints:** -* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type) +* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range) +* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant) +* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr) +* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) +* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) +* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) +* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) +* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) +* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) +* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect) +* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next) +* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into) +* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none) +* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice) +* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) +* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits) +* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) +* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp) +* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) +* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check) +* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) +* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive) +* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains) +* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid) +* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain) +* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) +* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) +* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) +* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) +* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) +* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) +* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro) +* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default) +* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn) +* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow) +* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) +* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) +* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) +* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) +* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) +* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current) +* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind) +* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref) +* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions) +* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds) +* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction) +* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations) +* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns) +* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self) -## `max-include-file-size` -The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes +## `pass-by-value-size-limit` +The minimum size (in bytes) to consider a type for passing by reference instead of by value. -**Default Value:** `1000000` +**Default Value:** `256` --- **Affected lints:** -* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file) +* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value) -## `allow-expect-in-tests` -Whether `expect` should be allowed in test functions or `#[cfg(test)]` +## `pub-underscore-fields-behavior` +Lint "public" fields in a struct that are prefixed with an underscore based on their +exported visibility, or whether they are marked as "pub". -**Default Value:** `false` +**Default Value:** `"PubliclyExported"` --- **Affected lints:** -* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used) +* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) -## `allow-unwrap-in-tests` -Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` +## `semicolon-inside-block-ignore-singleline` +Whether to lint only if it's multiline. **Default Value:** `false` --- **Affected lints:** -* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used) +* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block) -## `allow-dbg-in-tests` -Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` +## `semicolon-outside-block-ignore-multiline` +Whether to lint only if it's singleline. **Default Value:** `false` --- **Affected lints:** -* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro) +* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block) -## `allow-print-in-tests` -Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` +## `single-char-binding-names-threshold` +The maximum number of single char bindings a scope may have -**Default Value:** `false` +**Default Value:** `4` --- **Affected lints:** -* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout) -* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr) +* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names) -## `large-error-threshold` -The maximum size of the `Err`-variant in a `Result` returned from a function +## `stack-size-threshold` +The maximum allowed stack size for functions in bytes -**Default Value:** `128` +**Default Value:** `512000` --- **Affected lints:** -* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err) +* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames) -## `ignore-interior-mutability` -A list of paths to types that should be treated like `Arc`, i.e. ignored but -for the generic parameters for determining interior mutability +## `standard-macro-braces` +Enforce the named macros always use the braces specified. -**Default Value:** `["bytes::Bytes"]` +A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro +could be used with a full path two `MacroMatcher`s have to be added one with the full path +`crate_name::macro_name` and one with just the macro name. + +**Default Value:** `[]` --- **Affected lints:** -* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) -* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond) +* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces) -## `allow-mixed-uninlined-format-args` -Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)` +## `struct-field-name-threshold` +The minimum number of struct fields for the lints about field names to trigger -**Default Value:** `true` +**Default Value:** `3` --- **Affected lints:** -* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args) +* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names) ## `suppress-restriction-lint-in-const` @@ -645,217 +751,111 @@ if no suggestion can be made. * [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing) -## `missing-docs-in-crate-items` -Whether to **only** check for missing documentation in items visible within the current -crate. For example, `pub(crate)` items. - -**Default Value:** `false` - ---- -**Affected lints:** -* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items) - - -## `future-size-threshold` -The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint +## `too-large-for-stack` +The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap -**Default Value:** `16384` +**Default Value:** `200` --- **Affected lints:** -* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures) +* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local) +* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec) -## `unnecessary-box-size` -The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint +## `too-many-arguments-threshold` +The maximum number of argument a function or method can have -**Default Value:** `128` +**Default Value:** `7` --- **Affected lints:** -* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) +* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments) -## `allow-private-module-inception` -Whether to allow module inception if it's not public. +## `too-many-lines-threshold` +The maximum number of lines a function or method can have -**Default Value:** `false` +**Default Value:** `100` --- **Affected lints:** -* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) - +* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines) -## `allowed-idents-below-min-chars` -Allowed names below the minimum allowed characters. The value `".."` can be used as part of -the list to indicate, that the configured values should be appended to the default -configuration of Clippy. By default, any configuration will replace the default value. -**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]` +## `trivial-copy-size-limit` +The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by +reference. By default there is no limit --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref) -## `min-ident-chars-threshold` -Minimum chars an ident can have, anything below or equal to this will be linted. +## `type-complexity-threshold` +The maximum complexity a type can have -**Default Value:** `1` +**Default Value:** `250` --- **Affected lints:** -* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars) +* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity) -## `accept-comment-above-statement` -Whether to accept a safety comment to be placed above the statement containing the `unsafe` block +## `unnecessary-box-size` +The byte size a `T` in `Box` can have, below which it triggers the `clippy::unnecessary_box` lint -**Default Value:** `true` +**Default Value:** `128` --- **Affected lints:** -* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns) -## `accept-comment-above-attributes` -Whether to accept a safety comment to be placed above the attributes for the `unsafe` block +## `unreadable-literal-lint-fractions` +Should the fraction of a decimal be linted to include separators. **Default Value:** `true` --- **Affected lints:** -* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks) +* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal) -## `allow-one-hash-in-raw-strings` -Whether to allow `r#""#` when `r""` can be used +## `upper-case-acronyms-aggressive` +Enables verbose mode. Triggers if there is more than one uppercase char next to each other **Default Value:** `false` --- **Affected lints:** -* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) - - -## `absolute-paths-max-segments` -The maximum number of segments a path can have before being linted, anything above this will -be linted. - -**Default Value:** `2` - ---- -**Affected lints:** -* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) - - -## `absolute-paths-allowed-crates` -Which crates to allow absolute paths from - -**Default Value:** `[]` - ---- -**Affected lints:** -* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths) - - -## `allowed-dotfiles` -Additional dotfiles (files or directories starting with a dot) to allow - -**Default Value:** `[]` - ---- -**Affected lints:** -* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext) +* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms) -## `allowed-duplicate-crates` -A list of crate names to allow duplicates of +## `vec-box-size-threshold` +The size of the boxed type in bytes, where boxing in a `Vec` is allowed -**Default Value:** `[]` +**Default Value:** `4096` --- **Affected lints:** -* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions) - - -## `enforce-iter-loop-reborrow` -Whether to recommend using implicit into iter for reborrowed values. +* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box) -#### Example -```no_run -let mut vec = vec![1, 2, 3]; -let rmvec = &mut vec; -for _ in rmvec.iter() {} -for _ in rmvec.iter_mut() {} -``` -Use instead: -```no_run -let mut vec = vec![1, 2, 3]; -let rmvec = &mut vec; -for _ in &*rmvec {} -for _ in &mut *rmvec {} -``` +## `verbose-bit-mask-threshold` +The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros' -**Default Value:** `false` +**Default Value:** `1` --- **Affected lints:** -* [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop) +* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask) -## `check-private-items` -Whether to also run the listed lints on private items. +## `warn-on-all-wildcard-imports` +Whether to allow certain wildcard imports (prelude, super in tests). **Default Value:** `false` ---- -**Affected lints:** -* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc) -* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc) -* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc) -* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc) - - -## `pub-underscore-fields-behavior` -Lint "public" fields in a struct that are prefixed with an underscore based on their -exported visibility, or whether they are marked as "pub". - -**Default Value:** `"PubliclyExported"` - ---- -**Affected lints:** -* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) - - -## `allow-comparison-to-zero` -Don't lint when comparing the result of a modulo operation to zero. - -**Default Value:** `true` - ---- -**Affected lints:** -* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic) - - -## `allowed-wildcard-imports` -List of path segments allowed to have wildcard imports. - -#### Example - -```toml -allowed-wildcard-imports = [ "utils", "common" ] -``` - -#### Noteworthy - -1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`. -2. Paths with any segment that containing the word 'prelude' -are already allowed by default. - -**Default Value:** `[]` - --- **Affected lints:** * [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index b781259ad9695..673b6328b3901 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -193,7 +193,7 @@ macro_rules! define_Conf { } pub fn get_configuration_metadata() -> Vec { - vec![ + let mut sorted = vec![ $( { let deprecation_reason = wrap_option!($($dep)?); @@ -206,7 +206,9 @@ macro_rules! define_Conf { ) }, )+ - ] + ]; + sorted.sort_by(|a, b| a.name.cmp(&b.name)); + sorted } }; } diff --git a/clippy_config/src/metadata.rs b/clippy_config/src/metadata.rs index 3ba2796e18d3c..400887185e8cf 100644 --- a/clippy_config/src/metadata.rs +++ b/clippy_config/src/metadata.rs @@ -26,9 +26,11 @@ impl ClippyConfiguration { doc_comment: &'static str, deprecation_reason: Option<&'static str>, ) -> Self { - let (lints, doc) = parse_config_field_doc(doc_comment) + let (mut lints, doc) = parse_config_field_doc(doc_comment) .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string())); + lints.sort(); + Self { name: to_kebab(name), lints, From aed59f0a510b4e47496d871051026c885bccc3a1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Feb 2024 18:12:12 +0100 Subject: [PATCH 227/613] Add `clone-gcc` command --- build_system/src/clone_gcc.rs | 79 +++++++++++++++++++++++++++++++++++ build_system/src/config.rs | 13 ++++-- build_system/src/main.rs | 19 +++++---- build_system/src/prepare.rs | 4 +- build_system/src/test.rs | 17 +++----- build_system/src/utils.rs | 57 +++++++++++++++++++------ 6 files changed, 153 insertions(+), 36 deletions(-) create mode 100644 build_system/src/clone_gcc.rs diff --git a/build_system/src/clone_gcc.rs b/build_system/src/clone_gcc.rs new file mode 100644 index 0000000000000..aee46afaeb040 --- /dev/null +++ b/build_system/src/clone_gcc.rs @@ -0,0 +1,79 @@ +use crate::config::ConfigInfo; +use crate::utils::{git_clone, run_command_with_output}; + +use std::path::{Path, PathBuf}; + +fn show_usage() { + println!( + r#" +`clone-gcc` command help: + + --out-path : Location where the GCC repository will be cloned (default: `./gcc`)"# + ); + ConfigInfo::show_usage(); + println!(" --help : Show this help"); +} + +#[derive(Default)] +struct Args { + out_path: PathBuf, + config_info: ConfigInfo, +} + +impl Args { + fn new() -> Result, String> { + let mut command_args = Self::default(); + + let mut out_path = None; + + // We skip binary name and the `clone-gcc` command. + let mut args = std::env::args().skip(2); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--out-path" => match args.next() { + Some(path) if !path.is_empty() => out_path = Some(path), + _ => { + return Err("Expected an argument after `--out-path`, found nothing".into()) + } + }, + "--help" => { + show_usage(); + return Ok(None); + } + arg => { + if !command_args.config_info.parse_argument(arg, &mut args)? { + return Err(format!("Unknown option {}", arg)); + } + } + } + } + command_args.out_path = match out_path { + Some(p) => p.into(), + None => PathBuf::from("./gcc"), + }; + return Ok(Some(command_args)); + } +} + +pub fn run() -> Result<(), String> { + let Some(args) = Args::new()? else { + return Ok(()); + }; + + let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?; + if result.ran_clone { + let gcc_commit = args.config_info.get_gcc_commit()?; + println!("Checking out GCC commit `{}`...", gcc_commit); + run_command_with_output( + &[&"git", &"checkout", &gcc_commit], + Some(Path::new(&result.repo_dir)), + )?; + } else { + println!( + "There is already a GCC folder in `{}`, leaving things as is...", + args.out_path.display() + ); + } + Ok(()) +} diff --git a/build_system/src/config.rs b/build_system/src/config.rs index f6f039370180c..c633ee57d4a34 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -192,9 +192,7 @@ impl ConfigInfo { command } - fn download_gccjit_if_needed(&mut self) -> Result<(), String> { - let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit"); - + pub fn get_gcc_commit(&self) -> Result { let commit_hash_file = self.compute_path("libgccjit.version"); let content = fs::read_to_string(&commit_hash_file).map_err(|_| { format!( @@ -212,7 +210,14 @@ impl ConfigInfo { commit, )); } - let output_dir = output_dir.join(commit); + Ok(commit.to_string()) + } + + fn download_gccjit_if_needed(&mut self) -> Result<(), String> { + let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit"); + let commit = self.get_gcc_commit()?; + + let output_dir = output_dir.join(&commit); if !output_dir.is_dir() { std::fs::create_dir_all(&output_dir).map_err(|err| { format!( diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 18dc4b21a9623..48ffbc7a9075a 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -4,6 +4,7 @@ use std::process; mod build; mod cargo; mod clean; +mod clone_gcc; mod config; mod info; mod prepare; @@ -27,19 +28,21 @@ fn usage() { "\ Available commands for build_system: - cargo : Run cargo command - clean : Run clean command - prepare : Run prepare command - build : Run build command - test : Run test command - info: : Run info command - --help : Show this message" + cargo : Run cargo command + clean : Run clean command + prepare : Run prepare command + build : Run build command + test : Run test command + info : Run info command + clone-gcc : Run clone-gcc command + --help : Show this message" ); } pub enum Command { Cargo, Clean, + CloneGcc, Prepare, Build, Test, @@ -58,6 +61,7 @@ fn main() { Some("build") => Command::Build, Some("test") => Command::Test, Some("info") => Command::Info, + Some("clone-gcc") => Command::CloneGcc, Some("--help") => { usage(); process::exit(0); @@ -77,6 +81,7 @@ fn main() { Command::Build => build::run(), Command::Test => test::run(), Command::Info => info::run(), + Command::CloneGcc => clone_gcc::run(), } { eprintln!("Command failed to run: {e}"); process::exit(1); diff --git a/build_system/src/prepare.rs b/build_system/src/prepare.rs index 66f440f53553a..4ea334ad8b907 100644 --- a/build_system/src/prepare.rs +++ b/build_system/src/prepare.rs @@ -1,6 +1,6 @@ use crate::rustc_info::get_rustc_path; use crate::utils::{ - cargo_install, git_clone, remove_file, run_command, run_command_with_output, walk_dir, + cargo_install, git_clone_root_dir, remove_file, run_command, run_command_with_output, walk_dir, }; use std::fs; @@ -152,7 +152,7 @@ fn clone_and_setup(repo_url: &str, checkout_commit: &str, extra: Option) - where F: Fn(&Path) -> Result<(), String>, { - let clone_result = git_clone(repo_url, Some(&Path::new(crate::BUILD_DIR)), false)?; + let clone_result = git_clone_root_dir(repo_url, &Path::new(crate::BUILD_DIR), false)?; if !clone_result.ran_clone { println!("`{}` has already been cloned", clone_result.repo_name); } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 17b1868502aa6..470bb2431d563 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,7 +1,7 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ - get_toolchain, git_clone, remove_file, run_command, run_command_with_env, + get_toolchain, git_clone, git_clone_root_dir, remove_file, run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir, }; @@ -487,15 +487,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { ); let rust_dir_path = Path::new(crate::BUILD_DIR).join("rust"); // If the repository was already cloned, command will fail, so doesn't matter. - let _ = run_command_with_output_and_env( - &[ - &"git", - &"clone", - &"https://github.com/rust-lang/rust.git", - &rust_dir_path, - ], - None, - Some(env), + let _ = git_clone( + "https://github.com/rust-lang/rust.git", + Some(&rust_dir_path), + false, ); let rust_dir: Option<&Path> = Some(&rust_dir_path); run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?; @@ -720,7 +715,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let run_tests = |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { for project in iter { - let clone_result = git_clone(project, Some(projects_path), true)?; + let clone_result = git_clone_root_dir(project, projects_path, true)?; let repo_path = Path::new(&clone_result.repo_dir); run_cargo_command(&[&"build", &"--release"], Some(repo_path), env, args)?; run_cargo_command(&[&"test"], Some(repo_path), env, args)?; diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 33dcd9ef7005f..56f1abaf19844 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, ExitStatus, Output}; fn get_command_inner( @@ -254,20 +254,12 @@ pub struct CloneResult { pub repo_dir: String, } -pub fn git_clone( +fn git_clone_inner( to_clone: &str, - dest: Option<&Path>, + dest: &Path, shallow_clone: bool, + repo_name: String, ) -> Result { - let repo_name = to_clone.split('/').last().unwrap(); - let repo_name = match repo_name.strip_suffix(".git") { - Some(n) => n.to_string(), - None => repo_name.to_string(), - }; - - let dest = dest - .map(|dest| dest.join(&repo_name)) - .unwrap_or_else(|| Path::new(&repo_name).into()); if dest.is_dir() { return Ok(CloneResult { ran_clone: false, @@ -289,6 +281,47 @@ pub fn git_clone( }) } +fn get_repo_name(url: &str) -> String { + let repo_name = url.split('/').last().unwrap(); + match repo_name.strip_suffix(".git") { + Some(n) => n.to_string(), + None => repo_name.to_string(), + } +} + +pub fn git_clone( + to_clone: &str, + dest: Option<&Path>, + shallow_clone: bool, +) -> Result { + let repo_name = get_repo_name(to_clone); + let tmp: PathBuf; + + let dest = match dest { + Some(dest) => dest, + None => { + tmp = repo_name.clone().into(); + &tmp + } + }; + git_clone_inner(to_clone, dest, shallow_clone, repo_name) +} + +pub fn git_clone_root_dir( + to_clone: &str, + dest_parent_dir: &Path, + shallow_clone: bool, +) -> Result { + let repo_name = get_repo_name(to_clone); + + git_clone_inner( + to_clone, + &dest_parent_dir.join(&repo_name), + shallow_clone, + repo_name, + ) +} + pub fn walk_dir(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String> where P: AsRef, From 7d086c72f72ca64e57c52110eef6ae50eab484fd Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Fri, 23 Feb 2024 23:23:35 -0500 Subject: [PATCH 228/613] always use gep inbounds i8 (ptradd) for field offsets --- src/type_of.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/type_of.rs b/src/type_of.rs index 25149b8020162..e327051ca1d58 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -151,7 +151,6 @@ pub trait LayoutGccExt<'tcx> { fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>; fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc>; - fn gcc_field_index(&self, index: usize) -> u64; fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option; } @@ -304,24 +303,6 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { self.scalar_gcc_type_at(cx, scalar, offset) } - fn gcc_field_index(&self, index: usize) -> u64 { - match self.abi { - Abi::Scalar(_) | Abi::ScalarPair(..) => { - bug!("TyAndLayout::gcc_field_index({:?}): not applicable", self) - } - _ => {} - } - match self.fields { - FieldsShape::Primitive | FieldsShape::Union(_) => { - bug!("TyAndLayout::gcc_field_index({:?}): not applicable", self) - } - - FieldsShape::Array { .. } => index as u64, - - FieldsShape::Arbitrary { .. } => 1 + (self.fields.memory_index(index) as u64) * 2, - } - } - fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option { if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) { return pointee; @@ -351,10 +332,6 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { layout.is_gcc_scalar_pair() } - fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 { - layout.gcc_field_index(index) - } - fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, _immediate: bool) -> Type<'gcc> { layout.scalar_pair_element_gcc_type(self, index) } From 19a648218feee406b7ed50c8ef722adba71f4029 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 24 Feb 2024 01:46:30 -0500 Subject: [PATCH 229/613] remove struct_gep, use manual layout calculations for va_arg --- src/builder.rs | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 7e2139866f49e..bae0cc3655df6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -834,10 +834,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { let b_offset = a.size(self).align_to(b.align(self).abi); - let pair_type = place.layout.gcc_type(self); let mut load = |i, scalar: &abi::Scalar, align| { - let llptr = self.struct_gep(pair_type, place.llval, i as u64); + let llptr = if i == 0 { + place.llval + } else { + self.inbounds_gep( + self.type_i8(), + place.llval, + &[self.const_usize(b_offset.bytes())], + ) + }; let llty = place.layout.scalar_pair_element_gcc_type(self, i); let load = self.load(llty, llptr, align); scalar_load_metadata(self, load, scalar); @@ -971,33 +978,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { result.get_address(None) } - fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) -> RValue<'gcc> { - // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays. - assert_eq!(idx as usize as u64, idx); - let value = ptr.dereference(None).to_rvalue(); - - if value_type.dyncast_array().is_some() { - let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - let element = self.context.new_array_access(None, value, index); - element.get_address(None) - } - else if let Some(vector_type) = value_type.dyncast_vector() { - let array_type = vector_type.get_element_type().make_pointer(); - let array = self.bitcast(ptr, array_type); - let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); - let element = self.context.new_array_access(None, array, index); - element.get_address(None) - } - else if let Some(struct_type) = value_type.is_struct() { - // NOTE: due to opaque pointers now being used, we need to bitcast here. - let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer()); - ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None) - } - else { - panic!("Unexpected type {:?}", value_type); - } - } - /* Casts */ fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { // TODO(antoyo): check that it indeed truncate the value. From 70346fe2a455c754d93994922cbfaa9393c0002b Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 24 Feb 2024 02:01:41 -0500 Subject: [PATCH 230/613] introduce and use ptradd/inbounds_ptradd instead of gep --- src/builder.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index bae0cc3655df6..71a0a4c2e96f2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -839,11 +839,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let llptr = if i == 0 { place.llval } else { - self.inbounds_gep( - self.type_i8(), - place.llval, - &[self.const_usize(b_offset.bytes())], - ) + self.inbounds_ptradd(place.llval, self.const_usize(b_offset.bytes())) }; let llty = place.layout.scalar_pair_element_gcc_type(self, i); let load = self.load(llty, llptr, align); From d013b5a4620cffc1643bf540b0bad3a1d1a63991 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 12 Jan 2024 14:22:06 +0100 Subject: [PATCH 231/613] Stabilize the `#[diagnostic]` namespace and `#[diagnostic::on_unimplemented]` attribute This PR stabilizes the `#[diagnostic]` attribute namespace and a minimal option of the `#[diagnostic::on_unimplemented]` attribute. The `#[diagnostic]` attribute namespace is meant to provide a home for attributes that allow users to influence error messages emitted by the compiler. The compiler is not guaranteed to use any of this hints, however it should accept any (non-)existing attribute in this namespace and potentially emit lint-warnings for unused attributes and options. This is meant to allow discarding certain attributes/options in the future to allow fundamental changes to the compiler without the need to keep then non-meaningful options working. The `#[diagnostic::on_unimplemented]` attribute is allowed to appear on a trait definition. This allows crate authors to hint the compiler to emit a specific error message if a certain trait is not implemented. For the `#[diagnostic::on_unimplemented]` attribute the following options are implemented: * `message` which provides the text for the top level error message * `label` which provides the text for the label shown inline in the broken code in the error message * `note` which provides additional notes. The `note` option can appear several times, which results in several note messages being emitted. If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. All three options accept a text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. For any non-existing argument a lint warning is generated. Tracking issue: #111996 --- compiler/rustc_ast_passes/src/feature_gate.rs | 8 -- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - library/core/src/lib.rs | 2 +- .../language-features/diagnostic-namespace.md | 84 ------------------- .../existing_proc_macros.rs | 1 - .../feature-gate-diagnostic_namespace.rs | 13 --- .../feature-gate-diagnostic_namespace.stderr | 37 -------- .../non_existing_attributes_accepted.rs | 1 - .../non_existing_attributes_accepted.stderr | 4 +- .../on_unimplemented/auxiliary/other.rs | 2 - ...options_of_the_internal_rustc_attribute.rs | 2 - ...ons_of_the_internal_rustc_attribute.stderr | 74 ++++++++-------- ...o_not_fail_parsing_on_invalid_options_1.rs | 2 - ...t_fail_parsing_on_invalid_options_1.stderr | 54 ++++++------ ...eature-gate-diagnostic_on_unimplemented.rs | 7 -- ...re-gate-diagnostic_on_unimplemented.stderr | 13 --- ...ed_options_and_continue_to_use_fallback.rs | 2 - ...ptions_and_continue_to_use_fallback.stderr | 14 ++-- .../on_unimplemented/multiple_notes.rs | 2 - .../on_unimplemented/multiple_notes.stderr | 12 +-- .../on_unimplemented_simple.rs | 2 - .../on_unimplemented_simple.stderr | 6 +- .../report_warning_on_duplicated_options.rs | 2 - ...eport_warning_on_duplicated_options.stderr | 14 ++-- .../ui/diagnostic_namespace/requires_path.rs | 2 - .../diagnostic_namespace/requires_path.stderr | 2 +- 27 files changed, 93 insertions(+), 273 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/diagnostic-namespace.md delete mode 100644 tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs delete mode 100644 tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr delete mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs delete mode 100644 tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1b0dd9acc3782..7dd1c35f7d685 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -203,14 +203,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } } - if !attr.is_doc_comment() - && let [seg, _] = attr.get_normal_item().path.segments.as_slice() - && seg.ident.name == sym::diagnostic - && !self.features.diagnostic_namespace - { - let msg = "`#[diagnostic]` attribute name space is experimental"; - gate!(self, diagnostic_namespace, seg.ident.span, msg); - } // Emit errors for non-staged-api crates. if !self.features.staged_api { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1b2993dabdb83..7e5197f16f91e 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -146,6 +146,8 @@ declare_features! ( (accepted, derive_default_enum, "1.62.0", Some(86985)), /// Allows the use of destructuring assignments. (accepted, destructuring_assignment, "1.59.0", Some(71126)), + /// Allows using the `#[diagnostic]` attribute tool namespace + (accepted, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(111996)), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146)), /// Allows `..` in tuple (struct) patterns. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 53254d567ccf2..19ad38b6e9f57 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -434,8 +434,6 @@ declare_features! ( (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. (unstable, deprecated_suggestion, "1.61.0", Some(94785)), - /// Allows using the `#[diagnostic]` attribute tool namespace - (unstable, diagnostic_namespace, "1.73.0", Some(111996)), /// Controls errors in trait implementations. (unstable, do_not_recommend, "1.67.0", Some(51992)), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7b735d48bdfce..0f7885769c267 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -202,6 +202,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(diagnostic_namespace))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] @@ -223,7 +224,6 @@ #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] -#![feature(diagnostic_namespace)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] diff --git a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md deleted file mode 100644 index 7c46811a27ab8..0000000000000 --- a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md +++ /dev/null @@ -1,84 +0,0 @@ -# `diagnostic_namespace` - -The tracking issue for this feature is: [#111996] - -[#111996]: https://github.com/rust-lang/rust/issues/111996 - ------------------------- - -The `diagnostic_namespace` feature permits customization of compilation errors. - -## diagnostic::on_unimplemented - -With [#114452] support for `diagnostic::on_unimplemented` was added. - -When used on a trait declaration, the following options are available: - -* `message` to customize the primary error message -* `note` to add a customized note message to an error message -* `label` to customize the label part of the error message - -The attribute will hint to the compiler to use these in error messages: -```rust -// some library -#![feature(diagnostic_namespace)] - -#[diagnostic::on_unimplemented( - message = "cannot insert element", - label = "cannot be put into a table", - note = "see for more information about the Table api" -)] -pub trait Element { - // ... -} -``` - -```rust,compile_fail,E0277 -# #![feature(diagnostic_namespace)] -# -# #[diagnostic::on_unimplemented( -# message = "cannot insert element", -# label = "cannot be put into a table", -# note = "see for more information about the Table api" -# )] -# pub trait Element { -# // ... -# } -# struct Table; -# impl Table { -# fn insert(&self, element: T) { -# // .. -# } -# } -# fn main() { -# let table = Table; -# let element = (); -// user code -table.insert(element); -# } -``` - -```text -error[E0277]: cannot insert element - --> src/main.rs:24:18 - | -24 | table.insert(element); - | ------ ^^^^^^^ cannot be put into a table - | | - | required by a bound introduced by this call - | - = help: the trait `Element` is not implemented for `` - = note: see for more information about the Table api -note: required by a bound in `Table::insert` - --> src/main.rs:15:18 - | -15 | fn insert(&self, element: T) { - | ^^^^^^^ required by this bound in `Table::insert` - -For more information about this error, try `rustc --explain E0277`. -``` - -See [RFC 3368] for more information. - -[#114452]: https://github.com/rust-lang/rust/pull/114452 -[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md diff --git a/tests/ui/diagnostic_namespace/existing_proc_macros.rs b/tests/ui/diagnostic_namespace/existing_proc_macros.rs index 2bc58aea8fc2c..014ec46f1b981 100644 --- a/tests/ui/diagnostic_namespace/existing_proc_macros.rs +++ b/tests/ui/diagnostic_namespace/existing_proc_macros.rs @@ -1,4 +1,3 @@ -#![feature(diagnostic_namespace)] //@ check-pass //@ aux-build:proc-macro-helper.rs diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs deleted file mode 100644 index b08e291621fdc..0000000000000 --- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[diagnostic::non_existing_attribute] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -pub trait Bar { -} - -#[diagnostic::non_existing_attribute(with_option = "foo")] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes] -struct Foo; - -fn main() { -} diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr deleted file mode 100644 index 38424c13d8613..0000000000000 --- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_namespace.rs:1:3 - | -LL | #[diagnostic::non_existing_attribute] - | ^^^^^^^^^^ - | - = note: see issue #111996 for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_namespace.rs:7:3 - | -LL | #[diagnostic::non_existing_attribute(with_option = "foo")] - | ^^^^^^^^^^ - | - = note: see issue #111996 for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -warning: unknown diagnostic attribute - --> $DIR/feature-gate-diagnostic_namespace.rs:1:15 - | -LL | #[diagnostic::non_existing_attribute] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default - -warning: unknown diagnostic attribute - --> $DIR/feature-gate-diagnostic_namespace.rs:7:15 - | -LL | #[diagnostic::non_existing_attribute(with_option = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors; 2 warnings emitted - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs index 95465701bf858..f6957b1448d18 100644 --- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs +++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs @@ -1,4 +1,3 @@ -#![feature(diagnostic_namespace)] //@ check-pass #[diagnostic::non_existing_attribute] //~^WARN unknown diagnostic attribute diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr index 753077b365e8f..c073ec9b103f6 100644 --- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr +++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr @@ -1,5 +1,5 @@ warning: unknown diagnostic attribute - --> $DIR/non_existing_attributes_accepted.rs:3:15 + --> $DIR/non_existing_attributes_accepted.rs:2:15 | LL | #[diagnostic::non_existing_attribute] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::non_existing_attribute] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: unknown diagnostic attribute - --> $DIR/non_existing_attributes_accepted.rs:8:15 + --> $DIR/non_existing_attributes_accepted.rs:7:15 | LL | #[diagnostic::non_existing_attribute(with_option = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs index 884bab2800a5b..512ef6330e5ec 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( message = "Message", note = "Note", diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs index eb985c062f3dd..30a85ff21992d 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( on(_Self = "&str"), //~^WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr index 75a701f0b5f65..e34b917f67e10 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1 | LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5 | LL | on(_Self = "&str"), | ^^^^^^^^^^^^^^^^^^ invalid option found here @@ -15,7 +15,7 @@ LL | on(_Self = "&str"), = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5 | LL | parent_label = "in this scope", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -23,7 +23,7 @@ LL | parent_label = "in this scope", = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5 | LL | append_const_msg | ^^^^^^^^^^^^^^^^ invalid option found here @@ -31,7 +31,7 @@ LL | append_const_msg = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32 | LL | #[diagnostic::on_unimplemented = "Message"] | ^^^^^^^^^^^ invalid option found here @@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "Message"] = help: only `message`, `note` and `label` are allowed as options warning: there is no parameter `from_desugaring` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `direct` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `cause` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `integral` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `integer` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `float` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `_Self` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `crate_local` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `Trait` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: there is no parameter `ItemContext` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = help: expect either a generic argument name or `{Self}` as format argument warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5 | LL | on(_Self = "&str"), | ^^^^^^^^^^^^^^^^^^ invalid option found here @@ -128,7 +128,7 @@ LL | on(_Self = "&str"), = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5 | LL | parent_label = "in this scope", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -137,7 +137,7 @@ LL | parent_label = "in this scope", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5 | LL | append_const_msg | ^^^^^^^^^^^^^^^^ invalid option found here @@ -146,7 +146,7 @@ LL | append_const_msg = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: trait has `()` and `i32` as params - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:15 | LL | takes_foo(()); | --------- ^^ trait has `()` and `i32` as params @@ -156,18 +156,18 @@ LL | takes_foo(()); = help: the trait `Foo` is not implemented for `()` = note: trait has `()` and `i32` as params help: this trait has no implementations, consider adding one - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:1 | LL | trait Foo {} | ^^^^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^^^^^^ required by this bound in `takes_foo` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32 | LL | #[diagnostic::on_unimplemented = "Message"] | ^^^^^^^^^^^ invalid option found here @@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented = "Message"] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `(): Bar` is not satisfied - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15 | LL | takes_bar(()); | --------- ^^ the trait `Bar` is not implemented for `()` @@ -185,13 +185,13 @@ LL | takes_bar(()); | = help: the trait `Bar` is implemented for `i32` note: required by a bound in `takes_bar` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:22 | LL | fn takes_bar(_: impl Bar) {} | ^^^ required by this bound in `takes_bar` warning: there is no parameter `from_desugaring` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -200,7 +200,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `direct` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `cause` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `integral` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -227,7 +227,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `integer` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5 | LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -236,7 +236,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `float` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -245,7 +245,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `_Self` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -254,7 +254,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `crate_local` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `Trait` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -272,7 +272,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: there is no parameter `ItemContext` on trait `Baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5 | LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -281,7 +281,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer} - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 | LL | takes_baz(()); | --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext} @@ -290,12 +290,12 @@ LL | takes_baz(()); | = help: the trait `Baz` is not implemented for `()` help: this trait has no implementations, consider adding one - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:1 | LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `takes_baz` - --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22 + --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22 | LL | fn takes_baz(_: impl Baz) {} | ^^^ required by this bound in `takes_baz` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs index 12fe988170ac1..b4234066bb19a 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(unsupported = "foo")] //~^WARN malformed `on_unimplemented` attribute //~|WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr index 11263580b15e2..dc0c194823696 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr @@ -1,5 +1,5 @@ warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1 | LL | #[diagnostic::on_unimplemented(message = "Baz")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Baz")] = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32 | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -31,7 +31,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = help: only `message`, `note` and `label` are allowed as options warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:32 | LL | #[diagnostic::on_unimplemented = "boom"] | ^^^^^^^^ invalid option found here @@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "boom"] = help: only `message`, `note` and `label` are allowed as options warning: missing options for `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | #[diagnostic::on_unimplemented] = help: at least one of the `message`, `note` and `label` options are expected warning: there is no parameter `DoesNotExist` on trait `Test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32 | LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] = help: expect either a generic argument name or `{Self}` as format argument warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32 | LL | #[diagnostic::on_unimplemented(unsupported = "foo")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -64,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:14 | LL | take_foo(1_i32); | -------- ^^^^^ the trait `Foo` is not implemented for `i32` @@ -72,18 +72,18 @@ LL | take_foo(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:4:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `take_foo` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:21 | LL | fn take_foo(_: impl Foo) {} | ^^^ required by this bound in `take_foo` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -92,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 | LL | take_baz(1_i32); | -------- ^^^^^ the trait `Baz` is not implemented for `i32` @@ -100,18 +100,18 @@ LL | take_baz(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:13:1 | LL | trait Baz {} | ^^^^^^^^^ note: required by a bound in `take_baz` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:21 | LL | fn take_baz(_: impl Baz) {} | ^^^ required by this bound in `take_baz` warning: malformed `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50 | LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -120,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Boom - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:15 | LL | take_boom(1_i32); | --------- ^^^^^ the trait `Boom` is not implemented for `i32` @@ -128,18 +128,18 @@ LL | take_boom(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:18:1 | LL | trait Boom {} | ^^^^^^^^^^ note: required by a bound in `take_boom` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:22 | LL | fn take_boom(_: impl Boom) {} | ^^^^ required by this bound in `take_boom` warning: missing options for `on_unimplemented` attribute - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +148,7 @@ LL | #[diagnostic::on_unimplemented] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `i32: Whatever` is not satisfied - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:19 | LL | take_whatever(1_i32); | ------------- ^^^^^ the trait `Whatever` is not implemented for `i32` @@ -156,18 +156,18 @@ LL | take_whatever(1_i32); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:27:1 | LL | trait Whatever {} | ^^^^^^^^^^^^^^ note: required by a bound in `take_whatever` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:26 | LL | fn take_whatever(_: impl Whatever) {} | ^^^^^^^^ required by this bound in `take_whatever` warning: there is no parameter `DoesNotExist` on trait `Test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32 | LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {DoesNotExist} - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:15 | LL | take_test(()); | --------- ^^ the trait `Test` is not implemented for `()` @@ -184,12 +184,12 @@ LL | take_test(()); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:1 | LL | trait Test {} | ^^^^^^^^^^ note: required by a bound in `take_test` - --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22 + --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 | LL | fn take_test(_: impl Test) {} | ^^^^ required by this bound in `take_test` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs deleted file mode 100644 index 609a840c118c6..0000000000000 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[diagnostic::on_unimplemented(message = "Foo")] -//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658] -pub trait Bar { -} - -fn main() { -} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr deleted file mode 100644 index 719322fa0f55e..0000000000000 --- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: `#[diagnostic]` attribute name space is experimental - --> $DIR/feature-gate-diagnostic_on_unimplemented.rs:1:3 - | -LL | #[diagnostic::on_unimplemented(message = "Foo")] - | ^^^^^^^^^^ - | - = note: see issue #111996 for more information - = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs index 0893f29c4a3b4..5b25fb234bc52 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( if(Self = "()"), //~^WARN malformed `on_unimplemented` attribute diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr index e00846da77be5..56d125e20e5c4 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr @@ -1,5 +1,5 @@ warning: malformed `on_unimplemented` attribute - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5 | LL | if(Self = "()"), | ^^^^^^^^^^^^^^^ invalid option found here @@ -8,7 +8,7 @@ LL | if(Self = "()"), = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `message` is ignored due to previous definition of `message` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32 | LL | message = "custom message", | -------------------------- `message` is first declared here @@ -17,7 +17,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")] | ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here warning: malformed `on_unimplemented` attribute - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5 | LL | if(Self = "()"), | ^^^^^^^^^^^^^^^ invalid option found here @@ -26,7 +26,7 @@ LL | if(Self = "()"), = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: `message` is ignored due to previous definition of `message` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32 | LL | message = "custom message", | -------------------------- `message` is first declared here @@ -37,7 +37,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")] = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: custom message - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:20:15 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:18:15 | LL | takes_foo(()); | --------- ^^ fallback label @@ -48,12 +48,12 @@ LL | takes_foo(()); = note: custom note = note: fallback note help: this trait has no implementations, consider adding one - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:1 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:17:22 + --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs index 34cdb99c754b1..a5982f6492ca5 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr index c72321d4617f0..93a0d0b3f4132 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr @@ -1,5 +1,5 @@ error[E0277]: Foo - --> $DIR/multiple_notes.rs:14:15 + --> $DIR/multiple_notes.rs:12:15 | LL | takes_foo(()); | --------- ^^ Bar @@ -10,18 +10,18 @@ LL | takes_foo(()); = note: Baz = note: Boom help: this trait has no implementations, consider adding one - --> $DIR/multiple_notes.rs:4:1 + --> $DIR/multiple_notes.rs:2:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/multiple_notes.rs:10:22 + --> $DIR/multiple_notes.rs:8:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` error[E0277]: Bar - --> $DIR/multiple_notes.rs:16:15 + --> $DIR/multiple_notes.rs:14:15 | LL | takes_bar(()); | --------- ^^ Foo @@ -32,12 +32,12 @@ LL | takes_bar(()); = note: Baz = note: Baz2 help: this trait has no implementations, consider adding one - --> $DIR/multiple_notes.rs:8:1 + --> $DIR/multiple_notes.rs:6:1 | LL | trait Bar {} | ^^^^^^^^^ note: required by a bound in `takes_bar` - --> $DIR/multiple_notes.rs:11:22 + --> $DIR/multiple_notes.rs:9:22 | LL | fn takes_bar(_: impl Bar) {} | ^^^ required by this bound in `takes_bar` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs index 797edbc9ec564..7ca0312775964 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz")] trait Foo {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr index de57f7044bffe..6b17f40c6dd16 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr @@ -1,5 +1,5 @@ error[E0277]: Foo - --> $DIR/on_unimplemented_simple.rs:9:15 + --> $DIR/on_unimplemented_simple.rs:7:15 | LL | takes_foo(()); | --------- ^^ Bar @@ -9,12 +9,12 @@ LL | takes_foo(()); = help: the trait `Foo` is not implemented for `()` = note: Baz help: this trait has no implementations, consider adding one - --> $DIR/on_unimplemented_simple.rs:4:1 + --> $DIR/on_unimplemented_simple.rs:2:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/on_unimplemented_simple.rs:6:22 + --> $DIR/on_unimplemented_simple.rs:4:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs index a7becd2f88f6d..8c0b81504177f 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic::on_unimplemented( message = "first message", label = "first label", diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr index d30754dcf10d0..43ab6bf25a1a2 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr @@ -1,5 +1,5 @@ warning: `message` is ignored due to previous definition of `message` - --> $DIR/report_warning_on_duplicated_options.rs:9:5 + --> $DIR/report_warning_on_duplicated_options.rs:7:5 | LL | message = "first message", | ------------------------- `message` is first declared here @@ -10,7 +10,7 @@ LL | message = "second message", = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: `label` is ignored due to previous definition of `label` - --> $DIR/report_warning_on_duplicated_options.rs:12:5 + --> $DIR/report_warning_on_duplicated_options.rs:10:5 | LL | label = "first label", | --------------------- `label` is first declared here @@ -19,7 +19,7 @@ LL | label = "second label", | ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here warning: `message` is ignored due to previous definition of `message` - --> $DIR/report_warning_on_duplicated_options.rs:9:5 + --> $DIR/report_warning_on_duplicated_options.rs:7:5 | LL | message = "first message", | ------------------------- `message` is first declared here @@ -30,7 +30,7 @@ LL | message = "second message", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: `label` is ignored due to previous definition of `label` - --> $DIR/report_warning_on_duplicated_options.rs:12:5 + --> $DIR/report_warning_on_duplicated_options.rs:10:5 | LL | label = "first label", | --------------------- `label` is first declared here @@ -41,7 +41,7 @@ LL | label = "second label", = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: first message - --> $DIR/report_warning_on_duplicated_options.rs:23:15 + --> $DIR/report_warning_on_duplicated_options.rs:21:15 | LL | takes_foo(()); | --------- ^^ first label @@ -52,12 +52,12 @@ LL | takes_foo(()); = note: custom note = note: second note help: this trait has no implementations, consider adding one - --> $DIR/report_warning_on_duplicated_options.rs:17:1 + --> $DIR/report_warning_on_duplicated_options.rs:15:1 | LL | trait Foo {} | ^^^^^^^^^ note: required by a bound in `takes_foo` - --> $DIR/report_warning_on_duplicated_options.rs:20:22 + --> $DIR/report_warning_on_duplicated_options.rs:18:22 | LL | fn takes_foo(_: impl Foo) {} | ^^^ required by this bound in `takes_foo` diff --git a/tests/ui/diagnostic_namespace/requires_path.rs b/tests/ui/diagnostic_namespace/requires_path.rs index e8d6ca73ad0cf..4f3a1319cafff 100644 --- a/tests/ui/diagnostic_namespace/requires_path.rs +++ b/tests/ui/diagnostic_namespace/requires_path.rs @@ -1,5 +1,3 @@ -#![feature(diagnostic_namespace)] - #[diagnostic] //~^ERROR cannot find attribute `diagnostic` in this scope pub struct Bar; diff --git a/tests/ui/diagnostic_namespace/requires_path.stderr b/tests/ui/diagnostic_namespace/requires_path.stderr index 5d07d3a22d50e..e02aacac8c1a7 100644 --- a/tests/ui/diagnostic_namespace/requires_path.stderr +++ b/tests/ui/diagnostic_namespace/requires_path.stderr @@ -1,5 +1,5 @@ error: cannot find attribute `diagnostic` in this scope - --> $DIR/requires_path.rs:3:3 + --> $DIR/requires_path.rs:1:3 | LL | #[diagnostic] | ^^^^^^^^^^ From ce4ae41605f8a049afee8b013121496aa9950e9f Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:21:05 +0800 Subject: [PATCH 232/613] internal: simplify the process of inserting spaces after mut --- .../ide-assists/src/handlers/inline_call.rs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 11b22b65205b8..7531dd5c035de 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -415,24 +415,16 @@ fn inline( let expr: &ast::Expr = expr; let mut insert_let_stmt = || { - let param_ty = match param_ty { - None => None, - Some(param_ty) => { - if sema.hir_file_for(param_ty.syntax()).is_macro() { - if let Some(param_ty) = - ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) - { - Some(param_ty) - } else { - Some(param_ty.clone_for_update()) - } - } else { - Some(param_ty.clone_for_update()) - } + let param_ty = param_ty.clone().map(|param_ty| { + if sema.hir_file_for(param_ty.syntax()).is_macro() { + ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) + .unwrap_or_else(|| param_ty) + } else { + param_ty } - }; - let ty: Option = - sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); + }); + + let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); let is_self = param .name(sema.db) From 48966268fcf560d8c132edea3b1028fa177d78b8 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:22:17 +0800 Subject: [PATCH 233/613] fix: use 4 spaces for indentation in macro expansion --- .../src/syntax_helpers/insert_whitespace_into_node.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs index 0b0fc6693526f..97b6d4a572a21 100644 --- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs +++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs @@ -20,7 +20,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { let after = Position::after; let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| { - (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent))) + (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent))) }; let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| { (pos(token.clone()), make::tokens::single_space()) @@ -41,7 +41,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { if indent > 0 { mods.push(( Position::after(node.clone()), - make::tokens::whitespace(&" ".repeat(2 * indent)), + make::tokens::whitespace(&" ".repeat(4 * indent)), )); } if node.parent().is_some() { @@ -91,10 +91,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { LIFETIME_IDENT if is_next(is_text, true) => { mods.push(do_ws(after, tok)); } - MUT_KW if is_next(|it| it == SELF_KW, false) => { - mods.push(do_ws(after, tok)); - } - AS_KW | DYN_KW | IMPL_KW | CONST_KW => { + AS_KW | DYN_KW | IMPL_KW | CONST_KW | MUT_KW => { mods.push(do_ws(after, tok)); } T![;] if is_next(|it| it != R_CURLY, true) => { From ec5236f3a8f9ea29abe36e173d9b087f5ede629c Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 12:23:15 +0800 Subject: [PATCH 234/613] test: use 4 spaces for indetation in macro expansion --- .../ide-assists/src/handlers/inline_call.rs | 8 +-- .../ide-assists/src/handlers/inline_macro.rs | 10 ++-- crates/ide/src/expand_macro.rs | 58 +++++++++---------- crates/ide/src/hover/tests.rs | 6 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 7531dd5c035de..ab19779f4e843 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -1348,8 +1348,8 @@ macro_rules! define_foo { define_foo!(); fn bar() -> u32 { { - let x = 0; - x + let x = 0; + x } } "#, @@ -1662,7 +1662,7 @@ fn main() { let a: A = A{}; let b = { let a = a; - a as A + a as A }; } "#, @@ -1781,7 +1781,7 @@ fn _hash2(self_: &u64, state: &mut u64) { { let inner_self_: &u64 = &self_; let state: &mut u64 = state; - _write_u64(state, *inner_self_) + _write_u64(state, *inner_self_) }; } "#, diff --git a/crates/ide-assists/src/handlers/inline_macro.rs b/crates/ide-assists/src/handlers/inline_macro.rs index 0c9e971dd23ca..4708be616964f 100644 --- a/crates/ide-assists/src/handlers/inline_macro.rs +++ b/crates/ide-assists/src/handlers/inline_macro.rs @@ -288,11 +288,11 @@ macro_rules! foo { } fn main() { cfg_if!{ - if #[cfg(test)]{ - 1; - }else { - 1; - } + if #[cfg(test)]{ + 1; + }else { + 1; + } }; } "#, diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 17c701ad03591..9eb5a9db6250e 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -308,8 +308,8 @@ f$0oo!(); expect![[r#" foo! fn some_thing() -> u32 { - let a = 0; - a+10 + let a = 0; + a+10 }"#]], ); } @@ -342,13 +342,13 @@ fn main() { expect![[r#" match_ast! { - if let Some(it) = ast::TraitDef::cast(container.clone()){} - else if let Some(it) = ast::ImplDef::cast(container.clone()){} - else { - { - continue + if let Some(it) = ast::TraitDef::cast(container.clone()){} + else if let Some(it) = ast::ImplDef::cast(container.clone()){} + else { + { + continue + } } - } }"#]], ); } @@ -397,12 +397,12 @@ fn main() { expect![[r#" foo! { - macro_rules! bar { - () => { - 42 + macro_rules! bar { + () => { + 42 + } } - } - 42 + 42 }"#]], ); } @@ -482,16 +482,16 @@ struct Foo {} expect![[r#" Clone impl < >$crate::clone::Clone for Foo< >where { - fn clone(&self) -> Self { - match self { - Foo{} - => Foo{} - , + fn clone(&self) -> Self { + match self { + Foo{} + => Foo{} + , - } - } + } + } - }"#]], + }"#]], ); } @@ -534,16 +534,16 @@ struct Foo {} expect![[r#" Clone impl < >$crate::clone::Clone for Foo< >where { - fn clone(&self) -> Self { - match self { - Foo{} - => Foo{} - , + fn clone(&self) -> Self { + match self { + Foo{} + => Foo{} + , - } - } + } + } - }"#]], + }"#]], ); } } diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ead4f91595f0e..7ecfdfb1942f5 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -6341,8 +6341,8 @@ fn main() { $0V; } ```rust pub const V: i8 = { - let e = 123; - f(e) + let e = 123; + f(e) } ``` "#]], @@ -6368,7 +6368,7 @@ fn main() { $0V; } ```rust pub static V: i8 = { - let e = 123; + let e = 123; } ``` "#]], From 76b86b24bd38e53ee8a3555608339803ecb5cbb9 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 27 Feb 2024 13:54:52 +0800 Subject: [PATCH 235/613] fix: clippy and format --- crates/ide-assists/src/handlers/inline_call.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index ab19779f4e843..9c4f3bb93708c 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -417,8 +417,7 @@ fn inline( let mut insert_let_stmt = || { let param_ty = param_ty.clone().map(|param_ty| { if sema.hir_file_for(param_ty.syntax()).is_macro() { - ast::Type::cast(insert_ws_into(param_ty.syntax().clone())) - .unwrap_or_else(|| param_ty) + ast::Type::cast(insert_ws_into(param_ty.syntax().clone())).unwrap_or(param_ty) } else { param_ty } From 03bb7908b964fd461b2ba277dcf4c04608b083ef Mon Sep 17 00:00:00 2001 From: Ethiraric Date: Tue, 27 Feb 2024 11:41:38 +0100 Subject: [PATCH 236/613] [`map_entry`]: Check insert expression for map use The lint makes sure that the map is not used (borrowed) before the call to `insert`. Since the lint creates a mutable borrow on the map with the `Entry`, it wouldn't be possible to replace such code with `Entry`. However, expressions up to the `insert` call are checked, but not expressions for the arguments of the `insert` call itself. This commit fixes that. Fixes #11935 --- clippy_lints/src/entry.rs | 55 +++++++++++++++++++++++++++++++++++++-- tests/ui/entry.fixed | 11 ++++++++ tests/ui/entry.rs | 11 ++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 0b4bc375df0d9..de6073c272360 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -214,12 +214,31 @@ impl MapType { } } +/// Details on an expression checking whether a map contains a key. +/// +/// For instance, with the following: +/// ```ignore +/// !!!self.the_map.contains_key("the_key") +/// ``` +/// +/// - `negated` will be set to `true` (the 3 `!` negate the condition) +/// - `map` will be the `self.the_map` expression +/// - `key` will be the `"the_key"` expression struct ContainsExpr<'tcx> { + /// Whether the check for `contains_key` was negated. negated: bool, + /// The map on which the check is performed. map: &'tcx Expr<'tcx>, + /// The key that is checked to be contained. key: &'tcx Expr<'tcx>, + /// The context of the whole condition expression. call_ctxt: SyntaxContext, } + +/// Inspect the given expression and return details about the `contains_key` check. +/// +/// If the given expression is not a `contains_key` check against a `BTreeMap` or a `HashMap`, +/// return `None`. fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(MapType, ContainsExpr<'tcx>)> { let mut negated = false; let expr = peel_hir_expr_while(expr, |e| match e.kind { @@ -229,6 +248,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio }, _ => None, }); + match expr.kind { ExprKind::MethodCall( _, @@ -261,11 +281,28 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio } } +/// Details on an expression inserting a key into a map. +/// +/// For instance, on the following: +/// ```ignore +/// self.the_map.insert("the_key", 3 + 4); +/// ``` +/// +/// - `map` will be the `self.the_map` expression +/// - `key` will be the `"the_key"` expression +/// - `value` will be the `3 + 4` expression struct InsertExpr<'tcx> { + /// The map into which the insertion is performed. map: &'tcx Expr<'tcx>, + /// The key at which to insert. key: &'tcx Expr<'tcx>, + /// The value to insert. value: &'tcx Expr<'tcx>, } + +/// Inspect the given expression and return details about the `insert` call. +/// +/// If the given expression is not an `insert` call into a `BTreeMap` or a `HashMap`, return `None`. fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option> { if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind { let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?; @@ -298,7 +335,7 @@ struct Insertion<'tcx> { value: &'tcx Expr<'tcx>, } -/// This visitor needs to do a multiple things: +/// This visitor needs to do multiple things: /// * Find all usages of the map. An insertion can only be made before any other usages of the map. /// * Determine if there's an insertion using the same key. There's no need for the entry api /// otherwise. @@ -346,7 +383,7 @@ impl<'tcx> InsertSearcher<'_, 'tcx> { res } - /// Visits an expression which is not itself in a tail position, but other sibling expressions + /// Visit an expression which is not itself in a tail position, but other sibling expressions /// may be. e.g. if conditions fn visit_non_tail_expr(&mut self, e: &'tcx Expr<'_>) { let in_tail_pos = self.in_tail_pos; @@ -354,6 +391,19 @@ impl<'tcx> InsertSearcher<'_, 'tcx> { self.visit_expr(e); self.in_tail_pos = in_tail_pos; } + + /// Visit the key and value expression of an insert expression. + /// There may not be uses of the map in either of those two either. + fn visit_insert_expr_arguments(&mut self, e: &InsertExpr<'tcx>) { + let in_tail_pos = self.in_tail_pos; + let allow_insert_closure = self.allow_insert_closure; + let is_single_insert = self.is_single_insert; + walk_expr(self, e.key); + walk_expr(self, e.value); + self.in_tail_pos = in_tail_pos; + self.allow_insert_closure = allow_insert_closure; + self.is_single_insert = is_single_insert; + } } impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { @@ -425,6 +475,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { match try_parse_insert(self.cx, expr) { Some(insert_expr) if SpanlessEq::new(self.cx).eq_expr(self.map, insert_expr.map) => { + self.visit_insert_expr_arguments(&insert_expr); // Multiple inserts, inserts with a different key, and inserts from a macro can't use the entry api. if self.is_map_used || !SpanlessEq::new(self.cx).eq_expr(self.key, insert_expr.key) diff --git a/tests/ui/entry.fixed b/tests/ui/entry.fixed index 4099fe7e1393e..71ec13f461060 100644 --- a/tests/ui/entry.fixed +++ b/tests/ui/entry.fixed @@ -165,4 +165,15 @@ pub fn issue_10331() { } } +/// Issue 11935 +/// Do not suggest using entries if the map is used inside the `insert` expression. +pub fn issue_11935() { + let mut counts: HashMap = HashMap::new(); + if !counts.contains_key(&1) { + counts.insert(1, 1); + } else { + counts.insert(1, counts.get(&1).unwrap() + 1); + } +} + fn main() {} diff --git a/tests/ui/entry.rs b/tests/ui/entry.rs index 409be0aa06019..86092b7c055a7 100644 --- a/tests/ui/entry.rs +++ b/tests/ui/entry.rs @@ -169,4 +169,15 @@ pub fn issue_10331() { } } +/// Issue 11935 +/// Do not suggest using entries if the map is used inside the `insert` expression. +pub fn issue_11935() { + let mut counts: HashMap = HashMap::new(); + if !counts.contains_key(&1) { + counts.insert(1, 1); + } else { + counts.insert(1, counts.get(&1).unwrap() + 1); + } +} + fn main() {} From 9f4a58f6162c66c76ce16e2ecbe3e757d6fbb6db Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Feb 2024 12:25:04 +0100 Subject: [PATCH 237/613] Add new `mixed_attributes_style` lint --- CHANGELOG.md | 1 + clippy_lints/src/attrs.rs | 55 ++++++++++++++++++++++++++++++ clippy_lints/src/declared_lints.rs | 1 + 3 files changed, 57 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b01742deb05..20fc17df3c489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5423,6 +5423,7 @@ Released 2018-09-13 [`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop [`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes +[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression [`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index f2937d51340b8..d3ca4d3380656 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -485,6 +485,33 @@ declare_clippy_lint! { "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`" } +declare_clippy_lint! { + /// ### What it does + /// Checks that an item has only one kind of attributes. + /// + /// ### Why is this bad? + /// Having both kinds of attributes makes it more complicated to read code. + /// + /// ### Example + /// ```no_run + /// #[cfg(linux)] + /// pub fn foo() { + /// #![cfg(windows)] + /// } + /// ``` + /// Use instead: + /// ```no_run + /// #[cfg(linux)] + /// #[cfg(windows)] + /// pub fn foo() { + /// } + /// ``` + #[clippy::version = "1.78.0"] + pub MIXED_ATTRIBUTES_STYLE, + suspicious, + "item has both inner and outer attributes" +} + declare_lint_pass!(Attributes => [ ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, @@ -849,11 +876,13 @@ impl_lint_pass!(EarlyAttributes => [ MAYBE_MISUSED_CFG, DEPRECATED_CLIPPY_CFG_ATTR, UNNECESSARY_CLIPPY_CFG, + MIXED_ATTRIBUTES_STYLE, ]); impl EarlyLintPass for EarlyAttributes { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) { check_empty_line_after_outer_attr(cx, item); + check_mixed_attributes(cx, item); } fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { @@ -867,6 +896,32 @@ impl EarlyLintPass for EarlyAttributes { extract_msrv_attr!(EarlyContext); } +fn check_mixed_attributes(cx: &EarlyContext<'_>, item: &rustc_ast::Item) { + let mut has_outer = false; + let mut has_inner = false; + + for attr in &item.attrs { + if attr.span.from_expansion() { + continue; + } + match attr.style { + AttrStyle::Inner => has_inner = true, + AttrStyle::Outer => has_outer = true, + } + } + if !has_outer || !has_inner { + return; + } + let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion()); + let span = attrs_iter.next().unwrap().span; + span_lint( + cx, + MIXED_ATTRIBUTES_STYLE, + span.with_hi(attrs_iter.last().unwrap().span.hi()), + "item has both inner and outer attributes", + ); +} + /// Check for empty lines after outer attributes. /// /// Attributes and documentation comments are both considered outer attributes diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index fb3ae2457e3c4..a453386154d97 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -58,6 +58,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::INLINE_ALWAYS_INFO, crate::attrs::MAYBE_MISUSED_CFG_INFO, crate::attrs::MISMATCHED_TARGET_OS_INFO, + crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO, crate::attrs::NON_MINIMAL_CFG_INFO, crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO, crate::attrs::UNNECESSARY_CLIPPY_CFG_INFO, From 28738234acfd10c12d0400dc75940f3d35821113 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Feb 2024 12:25:28 +0100 Subject: [PATCH 238/613] Add ui test for `mixed_attributes_style` --- tests/ui/mixed_attributes_style.rs | 39 ++++++++++++++++++++++++++ tests/ui/mixed_attributes_style.stderr | 30 ++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/ui/mixed_attributes_style.rs create mode 100644 tests/ui/mixed_attributes_style.stderr diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs new file mode 100644 index 0000000000000..ad93e3019fa65 --- /dev/null +++ b/tests/ui/mixed_attributes_style.rs @@ -0,0 +1,39 @@ +#![warn(clippy::mixed_attributes_style)] + +#[allow(unused)] //~ ERROR: item has both inner and outer attributes +fn foo1() { + #![allow(unused)] +} + +#[allow(unused)] +#[allow(unused)] +fn foo2() {} + +fn foo3() { + #![allow(unused)] + #![allow(unused)] +} + +/// linux +//~^ ERROR: item has both inner and outer attributes +fn foo4() { + //! windows +} + +/// linux +/// windows +fn foo5() {} + +fn foo6() { + //! linux + //! windows +} + +#[allow(unused)] //~ ERROR: item has both inner and outer attributes +mod bar { + #![allow(unused)] +} + +fn main() { + // test code goes here +} diff --git a/tests/ui/mixed_attributes_style.stderr b/tests/ui/mixed_attributes_style.stderr new file mode 100644 index 0000000000000..d1d5cd3f47f31 --- /dev/null +++ b/tests/ui/mixed_attributes_style.stderr @@ -0,0 +1,30 @@ +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:3:1 + | +LL | / #[allow(unused)] +LL | | fn foo1() { +LL | | #![allow(unused)] + | |_____________________^ + | + = note: `-D clippy::mixed-attributes-style` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]` + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:17:1 + | +LL | / /// linux +LL | | +LL | | fn foo4() { +LL | | //! windows + | |_______________^ + +error: item has both inner and outer attributes + --> tests/ui/mixed_attributes_style.rs:32:1 + | +LL | / #[allow(unused)] +LL | | mod bar { +LL | | #![allow(unused)] + | |_____________________^ + +error: aborting due to 3 previous errors + From f30138623bd9a078698328a32785780cee379e8d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Feb 2024 11:18:27 +0100 Subject: [PATCH 239/613] Update ui tests --- tests/ui/empty_docs.rs | 2 ++ tests/ui/empty_docs.stderr | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/ui/empty_docs.rs b/tests/ui/empty_docs.rs index c47a603e71b43..272fab7d5ca1a 100644 --- a/tests/ui/empty_docs.rs +++ b/tests/ui/empty_docs.rs @@ -1,5 +1,7 @@ #![allow(unused)] #![warn(clippy::empty_docs)] +#![allow(clippy::mixed_attributes_style)] + mod outer { //! diff --git a/tests/ui/empty_docs.stderr b/tests/ui/empty_docs.stderr index 3f1d071fb13ce..f12aead6aa75e 100644 --- a/tests/ui/empty_docs.stderr +++ b/tests/ui/empty_docs.stderr @@ -1,5 +1,5 @@ error: empty doc comment - --> tests/ui/empty_docs.rs:4:5 + --> tests/ui/empty_docs.rs:6:5 | LL | //! | ^^^ @@ -9,7 +9,7 @@ LL | //! = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]` error: empty doc comment - --> tests/ui/empty_docs.rs:12:5 + --> tests/ui/empty_docs.rs:14:5 | LL | /// | ^^^ @@ -17,7 +17,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:14:9 + --> tests/ui/empty_docs.rs:16:9 | LL | /// | ^^^ @@ -25,7 +25,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:25:5 + --> tests/ui/empty_docs.rs:27:5 | LL | #[doc = ""] | ^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:28:5 + --> tests/ui/empty_docs.rs:30:5 | LL | / #[doc = ""] LL | | #[doc = ""] @@ -42,7 +42,7 @@ LL | | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:35:5 + --> tests/ui/empty_docs.rs:37:5 | LL | /// | ^^^ @@ -50,7 +50,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:48:13 + --> tests/ui/empty_docs.rs:50:13 | LL | /*! */ | ^^^^^^ @@ -58,7 +58,7 @@ LL | /*! */ = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:56:13 + --> tests/ui/empty_docs.rs:58:13 | LL | /// | ^^^ @@ -66,7 +66,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:64:9 + --> tests/ui/empty_docs.rs:66:9 | LL | /// | ^^^ From 7be6e2178e89dad8b619742c566fdee948414acc Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 27 Feb 2024 15:25:18 +0100 Subject: [PATCH 240/613] Merge commit '10136170fe9ed01e46aeb4f4479175b79eb0e3c7' into clippy-subtree-update --- .github/driver.sh | 4 +- CHANGELOG.md | 5 + Cargo.toml | 6 +- book/src/configuration.md | 50 +- book/src/development/emitting_lints.md | 10 +- book/src/development/writing_tests.md | 6 +- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 4 +- clippy_config/src/lib.rs | 2 +- clippy_dev/Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/asm_syntax.rs | 37 +- clippy_lints/src/attrs.rs | 221 +++++++- clippy_lints/src/blocks_in_conditions.rs | 17 +- clippy_lints/src/booleans.rs | 110 ++++ clippy_lints/src/box_default.rs | 71 ++- .../src/casts/cast_possible_truncation.rs | 3 +- clippy_lints/src/casts/cast_sign_loss.rs | 310 ++++++++--- clippy_lints/src/casts/ref_as_ptr.rs | 12 +- clippy_lints/src/casts/unnecessary_cast.rs | 5 +- clippy_lints/src/collection_is_never_read.rs | 8 +- clippy_lints/src/declared_lints.rs | 5 + clippy_lints/src/dereference.rs | 8 +- clippy_lints/src/disallowed_macros.rs | 84 ++- clippy_lints/src/doc/mod.rs | 61 ++- clippy_lints/src/drop_forget_ref.rs | 5 +- clippy_lints/src/format_args.rs | 511 +++++++++--------- clippy_lints/src/format_impl.rs | 203 +++---- clippy_lints/src/implied_bounds_in_impls.rs | 242 +++++---- clippy_lints/src/incompatible_msrv.rs | 18 +- clippy_lints/src/index_refutable_slice.rs | 4 +- clippy_lints/src/indexing_slicing.rs | 1 + clippy_lints/src/item_name_repetitions.rs | 1 - .../src/iter_not_returning_iterator.rs | 5 +- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/loops/infinite_loop.rs | 11 +- clippy_lints/src/manual_is_ascii_check.rs | 2 +- clippy_lints/src/matches/match_same_arms.rs | 66 ++- clippy_lints/src/matches/needless_match.rs | 62 +-- clippy_lints/src/matches/redundant_guards.rs | 12 +- .../matches/significant_drop_in_scrutinee.rs | 7 +- clippy_lints/src/mem_replace.rs | 6 +- ...se_sensitive_file_extension_comparisons.rs | 1 + clippy_lints/src/methods/clone_on_copy.rs | 7 +- clippy_lints/src/methods/filter_map.rs | 2 +- clippy_lints/src/methods/mod.rs | 54 +- clippy_lints/src/methods/needless_collect.rs | 184 ++++--- .../src/methods/read_line_without_trim.rs | 95 +++- .../unnecessary_fallible_conversions.rs | 141 +++-- .../src/methods/unnecessary_get_then_check.rs | 85 +++ .../src/methods/unnecessary_to_owned.rs | 98 +++- clippy_lints/src/min_ident_chars.rs | 46 +- clippy_lints/src/multiple_bound_locations.rs | 84 +++ clippy_lints/src/needless_bool.rs | 7 +- clippy_lints/src/needless_pass_by_ref_mut.rs | 5 +- clippy_lints/src/new_without_default.rs | 4 - clippy_lints/src/no_effect.rs | 13 +- clippy_lints/src/non_canonical_impls.rs | 4 +- clippy_lints/src/non_expressive_names.rs | 146 ++--- clippy_lints/src/only_used_in_recursion.rs | 16 +- .../src/operators/double_comparison.rs | 1 - clippy_lints/src/operators/op_ref.rs | 2 +- clippy_lints/src/pub_underscore_fields.rs | 10 +- clippy_lints/src/question_mark.rs | 14 +- clippy_lints/src/redundant_closure_call.rs | 10 +- clippy_lints/src/same_name_method.rs | 36 +- clippy_lints/src/single_call_fn.rs | 130 +++-- .../src/slow_vector_initialization.rs | 2 +- clippy_lints/src/strlen_on_c_strings.rs | 8 +- clippy_lints/src/to_string_trait_impl.rs | 3 + clippy_lints/src/tuple_array_conversions.rs | 5 +- .../src/undocumented_unsafe_blocks.rs | 200 ++++--- clippy_lints/src/unit_types/let_unit_value.rs | 3 +- clippy_lints/src/unused_unit.rs | 1 + .../internal_lints/metadata_collector.rs | 2 - clippy_lints/src/vec.rs | 211 ++++---- clippy_utils/Cargo.toml | 2 +- clippy_utils/src/ast_utils.rs | 8 +- clippy_utils/src/diagnostics.rs | 10 +- clippy_utils/src/hir_utils.rs | 5 +- clippy_utils/src/lib.rs | 13 +- clippy_utils/src/paths.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 6 +- declare_clippy_lint/Cargo.toml | 2 +- lintcheck/src/main.rs | 6 +- rust-toolchain | 2 +- src/driver.rs | 2 + tests/compile-test.rs | 39 +- .../multiple_config_files/warn/Cargo.stderr | 2 +- .../check_clippy_version_attribute.stderr | 10 +- tests/ui-internal/check_formulation.stderr | 4 +- .../collapsible_span_lint_calls.stderr | 12 +- .../default_deprecation_reason.stderr | 4 +- tests/ui-internal/default_lint.stderr | 4 +- tests/ui-internal/disallow_span_lint.stderr | 4 +- .../interning_defined_symbol.stderr | 10 +- .../ui-internal/invalid_msrv_attr_impl.stderr | 6 +- tests/ui-internal/invalid_paths.stderr | 6 +- .../ui-internal/lint_without_lint_pass.stderr | 4 +- tests/ui-internal/outer_expn_data.stderr | 4 +- tests/ui-internal/unnecessary_def_path.stderr | 32 +- ...unnecessary_def_path_hardcoded_path.stderr | 6 +- .../ui-internal/unnecessary_symbol_str.stderr | 12 +- .../absolute_paths.allow_crates.stderr | 8 +- .../absolute_paths.disallow_crates.stderr | 22 +- .../uninlined_format_args.stderr | 12 +- .../arithmetic_side_effects_allowed.stderr | 18 +- .../array_size_threshold.stderr | 6 +- .../await_holding_invalid_type.stderr | 6 +- tests/ui-toml/bad_toml/conf_bad_toml.stderr | 2 +- .../bad_toml_type/conf_bad_type.stderr | 2 +- .../conf_deprecated_key.stderr | 6 +- tests/ui-toml/dbg_macro/dbg_macro.stderr | 18 +- .../decimal_literal_representation.stderr | 2 +- .../auxiliary/proc_macros.rs | 29 + tests/ui-toml/disallowed_macros/clippy.toml | 1 + .../disallowed_macros/disallowed_macros.rs | 6 + .../disallowed_macros.stderr | 38 +- .../disallowed_names.stderr | 4 +- .../disallowed_names.stderr | 2 +- .../disallowed_script_idents.stderr | 2 +- .../doc_markdown.stderr | 2 +- .../doc_markdown.stderr | 6 +- .../duplicated_keys/duplicated_keys.stderr | 2 +- .../duplicated_keys.stderr | 4 +- .../duplicated_keys.stderr | 4 +- .../enum_variant_size.stderr | 2 +- .../excessive_nesting.stderr | 74 +-- tests/ui-toml/expect_used/expect_used.stderr | 4 +- .../explicit_iter_loop.stderr | 4 +- .../fn_params_excessive_bools/test.stderr | 2 +- tests/ui-toml/functions_maxlines/test.stderr | 8 +- .../ifs_same_cond/ifs_same_cond.stderr | 4 +- .../impl_trait_in_params.stderr | 2 +- .../invalid_min_rust_version.stderr | 2 +- .../threshold5/item_name_repetitions.stderr | 4 +- .../large_futures/large_futures.stderr | 2 +- .../large_include_file.stderr | 4 +- .../large_stack_frames.stderr | 2 +- .../large_types_passed_by_value.stderr | 2 +- .../lint_decimal_readability/test.stderr | 4 +- .../manual_let_else/manual_let_else.stderr | 2 +- .../index_refutable_slice.stderr | 4 +- .../min_ident_chars/auxiliary/extern_types.rs | 6 + .../min_ident_chars/min_ident_chars.rs | 5 +- .../min_ident_chars/min_ident_chars.stderr | 28 +- .../min_rust_version/min_rust_version.stderr | 2 +- ...conf_missing_enforced_import_rename.stderr | 12 +- .../module_inception/module_inception.stderr | 4 +- .../modulo_arithmetic.stderr | 8 +- .../conf_nonstandard_macro_braces.stderr | 16 +- tests/ui-toml/print_macro/print_macro.stderr | 4 +- .../private-doc-errors/doc_lints.stderr | 20 +- .../pub_crate_missing_doc.stderr | 14 +- ...ub_underscore_fields.all_pub_fields.stderr | 14 +- .../pub_underscore_fields.exported.stderr | 2 +- .../pub_underscore_fields.rs | 6 + .../result_large_err/result_large_err.stderr | 2 +- tests/ui-toml/semicolon_block/both.stderr | 8 +- .../semicolon_inside_block.stderr | 2 +- .../semicolon_outside_block.stderr | 6 +- .../test.stderr | 28 +- .../struct_excessive_bools/test.stderr | 2 +- .../suppress_lint_in_const/test.stderr | 12 +- .../conf_french_disallowed_name.stderr | 14 +- .../conf_disallowed_methods.stderr | 28 +- .../conf_disallowed_types.stderr | 42 +- tests/ui-toml/toml_trivially_copy/test.stderr | 4 +- .../toml_unknown_key/conf_unknown_key.stderr | 6 +- .../too_large_for_stack/boxed_local.stderr | 2 +- .../too_large_for_stack/useless_vec.stderr | 2 +- .../too_many_arguments.stderr | 2 +- .../type_complexity/type_complexity.stderr | 2 +- .../type_repetition_in_bounds/main.stderr | 2 +- .../undocumented_unsafe_blocks.default.stderr | 74 +-- ...undocumented_unsafe_blocks.disabled.stderr | 94 ++-- .../unnecessary_box_returns.stderr | 2 +- tests/ui-toml/unwrap_used/unwrap_used.stderr | 56 +- .../upper_case_acronyms.stderr | 26 +- tests/ui-toml/vec_box_sized/test.stderr | 6 +- .../verbose_bit_mask/verbose_bit_mask.stderr | 2 +- .../wildcard_imports/wildcard_imports.stderr | 6 +- .../wildcard_imports.stderr | 2 +- tests/ui/absurd-extreme-comparisons.stderr | 36 +- tests/ui/allow_attributes.stderr | 4 +- .../ui/allow_attributes_without_reason.stderr | 10 +- tests/ui/almost_complete_range.stderr | 54 +- tests/ui/approx_const.rs | 1 - tests/ui/approx_const.stderr | 46 +- tests/ui/arc_with_non_send_sync.stderr | 6 +- tests/ui/arithmetic_side_effects.stderr | 238 ++++---- tests/ui/as_conversions.stderr | 6 +- tests/ui/as_ptr_cast_mut.stderr | 4 +- tests/ui/as_underscore.stderr | 4 +- tests/ui/asm_syntax_not_x86.rs | 24 + ...ntax.stderr => asm_syntax_x86.i686.stderr} | 36 +- tests/ui/{asm_syntax.rs => asm_syntax_x86.rs} | 23 +- tests/ui/asm_syntax_x86.x86_64.stderr | 70 +++ tests/ui/assertions_on_constants.stderr | 20 +- tests/ui/assertions_on_result_states.stderr | 14 +- tests/ui/assign_ops.stderr | 22 +- tests/ui/assign_ops2.stderr | 20 +- tests/ui/async_yields_async.stderr | 12 +- tests/ui/attrs.stderr | 6 +- tests/ui/auxiliary/proc_macro_attr.rs | 20 + tests/ui/await_holding_lock.stderr | 52 +- tests/ui/await_holding_refcell_ref.stderr | 24 +- tests/ui/bind_instead_of_map.stderr | 8 +- tests/ui/bind_instead_of_map_multipart.stderr | 12 +- tests/ui/bit_masks.stderr | 34 +- .../blanket_clippy_restriction_lints.stderr | 6 +- tests/ui/blocks_in_conditions.fixed | 13 + tests/ui/blocks_in_conditions.rs | 13 + tests/ui/blocks_in_conditions.stderr | 8 +- tests/ui/blocks_in_conditions_closure.stderr | 6 +- tests/ui/bool_assert_comparison.stderr | 66 +-- tests/ui/bool_comparison.fixed | 2 +- tests/ui/bool_comparison.rs | 2 +- tests/ui/bool_comparison.stderr | 50 +- tests/ui/bool_to_int_with_if.stderr | 18 +- tests/ui/borrow_as_ptr.stderr | 4 +- tests/ui/borrow_as_ptr_no_std.stderr | 4 +- tests/ui/borrow_box.stderr | 22 +- tests/ui/borrow_deref_ref.stderr | 6 +- tests/ui/borrow_deref_ref_unfixable.stderr | 2 +- .../enums.stderr | 20 +- .../others.stderr | 30 +- .../traits.stderr | 32 +- tests/ui/box_collection.stderr | 18 +- tests/ui/box_default.fixed | 18 +- tests/ui/box_default.rs | 16 + tests/ui/box_default.stderr | 48 +- tests/ui/boxed_local.stderr | 8 +- .../shared_at_bottom.stderr | 20 +- .../shared_at_top.stderr | 20 +- .../shared_at_top_and_bottom.stderr | 22 +- .../valid_if_blocks.stderr | 22 +- tests/ui/builtin_type_shadow.stderr | 4 +- tests/ui/bytecount.stderr | 8 +- tests/ui/bytes_count_to_len.stderr | 8 +- tests/ui/bytes_nth.stderr | 6 +- ...sensitive_file_extension_comparisons.fixed | 5 + ...se_sensitive_file_extension_comparisons.rs | 5 + ...ensitive_file_extension_comparisons.stderr | 12 +- tests/ui/cast.rs | 67 ++- tests/ui/cast.stderr | 270 ++++++--- tests/ui/cast_abs_to_unsigned.stderr | 36 +- tests/ui/cast_alignment.stderr | 8 +- tests/ui/cast_enum_constructor.stderr | 4 +- tests/ui/cast_lossless_bool.stderr | 28 +- tests/ui/cast_lossless_float.stderr | 22 +- tests/ui/cast_lossless_integer.stderr | 42 +- tests/ui/cast_nan_to_int.stderr | 12 +- tests/ui/cast_raw_slice_pointer_cast.stderr | 14 +- tests/ui/cast_size.32bit.stderr | 38 +- tests/ui/cast_size.64bit.stderr | 36 +- tests/ui/cast_slice_different_sizes.stderr | 28 +- tests/ui/cfg_attr_cargo_clippy.fixed | 13 + tests/ui/cfg_attr_cargo_clippy.rs | 13 + tests/ui/cfg_attr_cargo_clippy.stderr | 47 ++ tests/ui/cfg_attr_rustfmt.stderr | 6 +- tests/ui/cfg_features.stderr | 16 +- tests/ui/char_lit_as_u8.stderr | 2 +- tests/ui/char_lit_as_u8_suggestions.stderr | 8 +- tests/ui/checked_conversions.stderr | 34 +- .../complex_conditionals.stderr | 44 +- .../complex_conditionals_nested.stderr | 8 +- .../checked_unwrap/simple_conditionals.stderr | 54 +- tests/ui/clear_with_drain.stderr | 42 +- tests/ui/clone_on_copy.stderr | 18 +- tests/ui/cloned_instead_of_copied.stderr | 16 +- tests/ui/cmp_null.stderr | 4 +- .../ui/cmp_owned/asymmetric_partial_eq.stderr | 12 +- tests/ui/cmp_owned/comparison_flip.stderr | 4 +- tests/ui/cmp_owned/with_suggestion.fixed | 2 +- tests/ui/cmp_owned/with_suggestion.stderr | 12 +- tests/ui/cmp_owned/without_suggestion.stderr | 6 +- tests/ui/cognitive_complexity.stderr | 40 +- .../ui/cognitive_complexity_attr_used.stderr | 2 +- tests/ui/collapsible_else_if.stderr | 16 +- tests/ui/collapsible_if.stderr | 18 +- tests/ui/collapsible_match.stderr | 48 +- tests/ui/collapsible_match2.stderr | 20 +- tests/ui/collapsible_str_replace.stderr | 28 +- tests/ui/collection_is_never_read.stderr | 40 +- tests/ui/comparison_chain.stderr | 14 +- tests/ui/comparison_to_empty.stderr | 18 +- tests/ui/const_comparisons.stderr | 62 +-- tests/ui/copy_iterator.stderr | 2 +- tests/ui/crashes/ice-10148.stderr | 2 +- tests/ui/crashes/ice-10645.stderr | 4 +- tests/ui/crashes/ice-10912.stderr | 4 +- tests/ui/crashes/ice-11065.rs | 1 - tests/ui/crashes/ice-11422.stderr | 2 +- tests/ui/crashes/ice-11803.stderr | 4 +- tests/ui/crashes/ice-12253.rs | 5 + tests/ui/crashes/ice-2774.stderr | 2 +- tests/ui/crashes/ice-360.stderr | 6 +- tests/ui/crashes/ice-3717.stderr | 4 +- tests/ui/crashes/ice-3891.stderr | 2 +- tests/ui/crashes/ice-3969.stderr | 10 +- tests/ui/crashes/ice-5497.stderr | 2 +- tests/ui/crashes/ice-5835.stderr | 2 +- tests/ui/crashes/ice-5872.stderr | 2 +- tests/ui/crashes/ice-6250.stderr | 4 +- tests/ui/crashes/ice-6251.stderr | 8 +- tests/ui/crashes/ice-6252.stderr | 6 +- tests/ui/crashes/ice-6255.rs | 2 +- tests/ui/crashes/ice-6255.stderr | 2 +- tests/ui/crashes/ice-6256.stderr | 2 +- tests/ui/crashes/ice-7169.stderr | 2 +- tests/ui/crashes/ice-7868.stderr | 2 +- tests/ui/crashes/ice-7869.stderr | 2 +- tests/ui/crashes/ice-8250.stderr | 2 +- tests/ui/crashes/ice-8850.stderr | 6 +- tests/ui/crashes/ice-9041.stderr | 2 +- tests/ui/crashes/ice-9405.stderr | 2 +- tests/ui/crashes/ice-9445.stderr | 2 +- tests/ui/crashes/ice-9463.stderr | 8 +- tests/ui/crashes/ice-96721.stderr | 2 +- .../needless_lifetimes_impl_trait.stderr | 4 +- ...needless_pass_by_value-w-late-bound.stderr | 4 +- tests/ui/crate_in_macro_def.stderr | 2 +- .../ui/crate_level_checks/no_std_swap.stderr | 2 +- .../std_main_recursion.stderr | 2 +- tests/ui/create_dir.stderr | 4 +- tests/ui/dbg_macro/dbg_macro.stderr | 38 +- tests/ui/debug_assert_with_mut_call.stderr | 56 +- .../ui/decimal_literal_representation.stderr | 14 +- .../enums.stderr | 24 +- .../declare_interior_mutable_const/others.rs | 5 +- .../others.stderr | 10 +- .../declare_interior_mutable_const/traits.rs | 3 +- .../traits.stderr | 22 +- tests/ui/def_id_nocore.stderr | 2 +- .../default_constructed_unit_structs.stderr | 12 +- tests/ui/default_instead_of_iter_empty.stderr | 6 +- ...efault_instead_of_iter_empty_no_std.stderr | 4 +- tests/ui/default_numeric_fallback_f64.stderr | 46 +- tests/ui/default_numeric_fallback_i32.stderr | 56 +- tests/ui/default_trait_access.stderr | 18 +- tests/ui/default_union_representation.stderr | 8 +- tests/ui/deprecated.stderr | 32 +- tests/ui/deprecated_old.stderr | 6 +- tests/ui/deref_addrof.stderr | 20 +- tests/ui/deref_addrof_double_trigger.stderr | 6 +- tests/ui/deref_by_slicing.stderr | 18 +- tests/ui/derivable_impls.stderr | 16 +- tests/ui/derive.stderr | 20 +- tests/ui/derive_ord_xor_partial_ord.stderr | 16 +- tests/ui/derive_partial_eq_without_eq.stderr | 22 +- tests/ui/derived_hash_with_manual_eq.stderr | 8 +- tests/ui/disallowed_names.stderr | 28 +- tests/ui/disallowed_script_idents.stderr | 6 +- tests/ui/diverging_sub_expression.stderr | 22 +- tests/ui/doc/doc-fixable.stderr | 62 +-- tests/ui/doc/unbalanced_ticks.stderr | 16 +- tests/ui/doc_errors.stderr | 14 +- tests/ui/doc_link_with_quotes.stderr | 4 +- tests/ui/doc_unsafe.stderr | 12 +- tests/ui/double_comparison.stderr | 16 +- tests/ui/double_must_use.stderr | 8 +- tests/ui/double_neg.stderr | 2 +- tests/ui/double_parens.stderr | 12 +- tests/ui/drain_collect.stderr | 22 +- tests/ui/drop_non_drop.stderr | 8 +- tests/ui/duplicate_underscore_argument.stderr | 2 +- tests/ui/duration_subsec.stderr | 10 +- tests/ui/eager_transmute.stderr | 34 +- tests/ui/else_if_without_else.stderr | 4 +- tests/ui/empty_docs.rs | 67 +++ tests/ui/empty_docs.stderr | 77 +++ tests/ui/empty_drop.stderr | 4 +- tests/ui/empty_enum.stderr | 2 +- .../empty_enum_variants_with_brackets.stderr | 8 +- tests/ui/empty_line_after_doc_comments.stderr | 6 +- .../empty_line_after_outer_attribute.stderr | 12 +- tests/ui/empty_loop.stderr | 6 +- tests/ui/empty_loop_no_std.stderr | 4 +- tests/ui/empty_structs_with_brackets.stderr | 4 +- tests/ui/endian_bytes.stderr | 172 +++--- tests/ui/entry.stderr | 20 +- tests/ui/entry_btree.stderr | 2 +- tests/ui/entry_with_else.stderr | 14 +- tests/ui/enum_clike_unportable_variant.stderr | 18 +- tests/ui/enum_glob_use.stderr | 6 +- tests/ui/enum_variants.stderr | 32 +- tests/ui/eprint_with_newline.stderr | 18 +- tests/ui/eq_op.stderr | 58 +- tests/ui/eq_op_macros.stderr | 24 +- tests/ui/equatable_if_let.stderr | 28 +- tests/ui/erasing_op.stderr | 10 +- tests/ui/err_expect.stderr | 4 +- tests/ui/error_impl_error.stderr | 14 +- tests/ui/eta.stderr | 62 +-- tests/ui/excessive_precision.stderr | 30 +- tests/ui/exhaustive_items.stderr | 10 +- tests/ui/exit1.stderr | 2 +- tests/ui/exit2.stderr | 2 +- tests/ui/expect.stderr | 6 +- tests/ui/expect_fun_call.stderr | 30 +- tests/ui/expect_tool_lint_rfc_2383.stderr | 12 +- tests/ui/explicit_auto_deref.stderr | 90 +-- tests/ui/explicit_counter_loop.stderr | 18 +- tests/ui/explicit_deref_methods.stderr | 24 +- tests/ui/explicit_into_iter_loop.stderr | 12 +- tests/ui/explicit_iter_loop.stderr | 38 +- tests/ui/explicit_write.stderr | 26 +- tests/ui/extend_with_drain.stderr | 8 +- tests/ui/extra_unused_lifetimes.stderr | 12 +- tests/ui/extra_unused_type_parameters.stderr | 16 +- ...ra_unused_type_parameters_unfixable.stderr | 6 +- tests/ui/fallible_impl_from.stderr | 18 +- tests/ui/field_reassign_with_default.stderr | 44 +- tests/ui/filetype_is_file.stderr | 6 +- tests/ui/filter_map_bool_then.stderr | 20 +- tests/ui/filter_map_identity.stderr | 8 +- tests/ui/filter_map_next.stderr | 2 +- tests/ui/filter_map_next_fixable.stderr | 4 +- tests/ui/flat_map_identity.stderr | 6 +- tests/ui/flat_map_option.stderr | 4 +- tests/ui/float_arithmetic.stderr | 34 +- tests/ui/float_cmp.stderr | 12 +- tests/ui/float_cmp_const.stderr | 16 +- tests/ui/float_equality_without_abs.stderr | 22 +- tests/ui/floating_point_abs.stderr | 16 +- tests/ui/floating_point_exp.stderr | 10 +- tests/ui/floating_point_hypot.stderr | 6 +- tests/ui/floating_point_log.stderr | 58 +- tests/ui/floating_point_logbase.stderr | 10 +- tests/ui/floating_point_mul_add.stderr | 26 +- tests/ui/floating_point_powf.stderr | 62 +-- tests/ui/floating_point_powi.stderr | 28 +- tests/ui/floating_point_rad.stderr | 16 +- tests/ui/fn_address_comparisons.stderr | 4 +- tests/ui/fn_params_excessive_bools.stderr | 14 +- tests/ui/fn_to_numeric_cast.32bit.stderr | 46 +- tests/ui/fn_to_numeric_cast.64bit.stderr | 46 +- tests/ui/fn_to_numeric_cast_any.stderr | 34 +- tests/ui/for_kv_map.stderr | 10 +- tests/ui/forget_non_drop.stderr | 8 +- tests/ui/format.stderr | 30 +- tests/ui/format_args.stderr | 50 +- tests/ui/format_args_unfixable.stderr | 36 +- tests/ui/format_collect.stderr | 18 +- tests/ui/format_push_string.stderr | 10 +- tests/ui/formatting.stderr | 12 +- tests/ui/four_forward_slashes.stderr | 10 +- .../ui/four_forward_slashes_first_line.stderr | 2 +- tests/ui/from_iter_instead_of_collect.stderr | 30 +- tests/ui/from_over_into.stderr | 14 +- tests/ui/from_over_into_unfixable.stderr | 8 +- tests/ui/from_raw_with_void_ptr.stderr | 20 +- tests/ui/from_str_radix_10.stderr | 16 +- tests/ui/functions.stderr | 32 +- tests/ui/functions_maxlines.stderr | 2 +- tests/ui/future_not_send.stderr | 36 +- tests/ui/get_first.stderr | 10 +- tests/ui/get_last_with_len.stderr | 12 +- tests/ui/get_unwrap.stderr | 62 +-- tests/ui/identity_op.stderr | 104 ++-- tests/ui/if_let_mutex.stderr | 6 +- tests/ui/if_not_else.stderr | 4 +- tests/ui/if_same_then_else.stderr | 24 +- tests/ui/if_same_then_else2.stderr | 24 +- tests/ui/if_then_some_else_none.stderr | 10 +- tests/ui/ifs_same_cond.stderr | 16 +- tests/ui/ignored_unit_patterns.stderr | 18 +- tests/ui/impl.stderr | 16 +- ...impl_hash_with_borrow_str_and_bytes.stderr | 6 +- tests/ui/impl_trait_in_params.stderr | 8 +- tests/ui/implicit_clone.stderr | 22 +- tests/ui/implicit_hasher.stderr | 12 +- tests/ui/implicit_return.stderr | 32 +- tests/ui/implicit_saturating_add.stderr | 48 +- tests/ui/implicit_saturating_sub.stderr | 46 +- tests/ui/implied_bounds_in_impls.fixed | 52 ++ tests/ui/implied_bounds_in_impls.rs | 52 ++ tests/ui/implied_bounds_in_impls.stderr | 118 +++- tests/ui/incompatible_msrv.rs | 13 + tests/ui/incompatible_msrv.stderr | 6 +- tests/ui/inconsistent_digit_grouping.stderr | 22 +- .../ui/inconsistent_struct_constructor.stderr | 4 +- .../if_let_slice_binding.stderr | 22 +- .../slice_indexing_in_macro.stderr | 4 +- tests/ui/indexing_slicing_index.stderr | 32 +- tests/ui/indexing_slicing_slice.stderr | 32 +- tests/ui/ineffective_open_options.stderr | 4 +- tests/ui/inefficient_to_string.stderr | 14 +- .../ui/infallible_destructuring_match.stderr | 8 +- tests/ui/infinite_iter.stderr | 32 +- tests/ui/infinite_loop.stderr | 22 +- tests/ui/infinite_loops.rs | 27 + tests/ui/infinite_loops.stderr | 34 +- tests/ui/inherent_to_string.stderr | 4 +- tests/ui/inline_fn_without_body.stderr | 6 +- tests/ui/inspect_for_each.stderr | 2 +- tests/ui/int_plus_one.stderr | 8 +- tests/ui/integer_division.stderr | 6 +- tests/ui/into_iter_on_ref.stderr | 54 +- tests/ui/into_iter_without_iter.stderr | 12 +- tests/ui/invalid_null_ptr_usage.stderr | 50 +- tests/ui/invalid_upcast_comparisons.stderr | 54 +- tests/ui/is_digit_ascii_radix.stderr | 6 +- tests/ui/issue-3145.stderr | 2 +- tests/ui/issue-7447.stderr | 4 +- tests/ui/issue_2356.stderr | 4 +- tests/ui/issue_4266.stderr | 6 +- tests/ui/items_after_statement.stderr | 6 +- .../in_submodule.stderr | 2 +- .../root_module.stderr | 2 +- tests/ui/iter_cloned_collect.stderr | 10 +- tests/ui/iter_count.stderr | 50 +- tests/ui/iter_filter_is_ok.stderr | 24 +- tests/ui/iter_filter_is_some.fixed | 3 +- tests/ui/iter_filter_is_some.rs | 3 +- tests/ui/iter_filter_is_some.stderr | 20 +- tests/ui/iter_kv_map.stderr | 76 +-- tests/ui/iter_next_loop.stderr | 2 +- tests/ui/iter_next_slice.stderr | 8 +- tests/ui/iter_not_returning_iterator.stderr | 6 +- tests/ui/iter_nth.stderr | 14 +- tests/ui/iter_nth_zero.stderr | 6 +- tests/ui/iter_on_empty_collections.stderr | 12 +- tests/ui/iter_on_single_items.stderr | 12 +- tests/ui/iter_out_of_bounds.stderr | 30 +- tests/ui/iter_over_hash_type.stderr | 26 +- tests/ui/iter_overeager_cloned.stderr | 38 +- tests/ui/iter_skip_next.stderr | 14 +- tests/ui/iter_skip_next_unfixable.stderr | 12 +- tests/ui/iter_skip_zero.stderr | 10 +- tests/ui/iter_with_drain.stderr | 12 +- tests/ui/iter_without_into_iter.stderr | 16 +- tests/ui/iterator_step_by_zero.stderr | 14 +- tests/ui/join_absolute_paths.stderr | 8 +- tests/ui/large_const_arrays.stderr | 18 +- tests/ui/large_digit_groups.stderr | 10 +- tests/ui/large_enum_variant.32bit.stderr | 44 +- tests/ui/large_enum_variant.64bit.stderr | 44 +- tests/ui/large_futures.stderr | 16 +- tests/ui/large_stack_arrays.stderr | 14 +- tests/ui/large_stack_frames.stderr | 6 +- tests/ui/large_types_passed_by_value.stderr | 16 +- tests/ui/len_without_is_empty.stderr | 42 +- tests/ui/len_zero.stderr | 46 +- tests/ui/len_zero_ranges.stderr | 4 +- tests/ui/let_and_return.stderr | 10 +- tests/ui/let_if_seq.stderr | 8 +- tests/ui/let_underscore_future.stderr | 6 +- tests/ui/let_underscore_lock.stderr | 8 +- tests/ui/let_underscore_must_use.stderr | 24 +- tests/ui/let_underscore_untyped.stderr | 20 +- tests/ui/let_unit.stderr | 6 +- tests/ui/let_with_type_underscore.stderr | 20 +- tests/ui/lines_filter_map_ok.stderr | 24 +- tests/ui/linkedlist.stderr | 18 +- tests/ui/literals.stderr | 40 +- tests/ui/lossy_float_literal.stderr | 22 +- tests/ui/macro_use_imports.stderr | 8 +- tests/ui/manual_assert.edition2018.stderr | 18 +- tests/ui/manual_assert.edition2021.stderr | 18 +- tests/ui/manual_async_fn.stderr | 26 +- tests/ui/manual_bits.stderr | 58 +- tests/ui/manual_c_str_literals.stderr | 26 +- tests/ui/manual_clamp.stderr | 70 +-- tests/ui/manual_filter.stderr | 30 +- tests/ui/manual_filter_map.stderr | 76 +-- tests/ui/manual_find.stderr | 4 +- tests/ui/manual_find_fixable.stderr | 24 +- tests/ui/manual_find_map.stderr | 78 +-- tests/ui/manual_flatten.stderr | 36 +- tests/ui/manual_float_methods.stderr | 12 +- tests/ui/manual_hash_one.stderr | 8 +- tests/ui/manual_instant_elapsed.stderr | 4 +- tests/ui/manual_is_ascii_check.stderr | 44 +- tests/ui/manual_is_variant_and.stderr | 16 +- tests/ui/manual_let_else.stderr | 60 +- tests/ui/manual_let_else_match.stderr | 20 +- tests/ui/manual_let_else_question_mark.stderr | 14 +- tests/ui/manual_main_separator_str.stderr | 8 +- tests/ui/manual_map_option.stderr | 42 +- tests/ui/manual_map_option_2.stderr | 10 +- .../manual_memcpy/with_loop_counters.stderr | 22 +- .../without_loop_counters.stderr | 32 +- tests/ui/manual_next_back.stderr | 4 +- tests/ui/manual_non_exhaustive_enum.stderr | 8 +- tests/ui/manual_non_exhaustive_struct.stderr | 20 +- tests/ui/manual_ok_or.stderr | 10 +- tests/ui/manual_range_patterns.stderr | 38 +- tests/ui/manual_rem_euclid.stderr | 20 +- tests/ui/manual_retain.stderr | 76 +-- tests/ui/manual_saturating_arithmetic.stderr | 48 +- tests/ui/manual_slice_size_calculation.stderr | 14 +- tests/ui/manual_split_once.stderr | 38 +- tests/ui/manual_str_repeat.stderr | 20 +- tests/ui/manual_string_new.stderr | 18 +- tests/ui/manual_strip.stderr | 32 +- tests/ui/manual_try_fold.stderr | 8 +- tests/ui/manual_unwrap_or.stderr | 28 +- tests/ui/manual_while_let_some.stderr | 14 +- tests/ui/many_single_char_names.stderr | 10 +- tests/ui/map_clone.stderr | 30 +- tests/ui/map_collect_result_unit.stderr | 4 +- tests/ui/map_err.stderr | 2 +- tests/ui/map_flatten.stderr | 8 +- tests/ui/map_flatten_fixable.stderr | 18 +- tests/ui/map_identity.stderr | 22 +- tests/ui/map_unwrap_or.stderr | 30 +- tests/ui/map_unwrap_or_fixable.stderr | 4 +- tests/ui/match_as_ref.stderr | 6 +- tests/ui/match_bool.stderr | 18 +- tests/ui/match_expr_like_matches_macro.stderr | 28 +- tests/ui/match_on_vec_items.stderr | 16 +- tests/ui/match_overlapping_arm.stderr | 32 +- tests/ui/match_ref_pats.stderr | 10 +- tests/ui/match_result_ok.stderr | 6 +- tests/ui/match_same_arms.stderr | 32 +- tests/ui/match_same_arms2.rs | 14 + tests/ui/match_same_arms2.stderr | 67 ++- .../ui/match_same_arms_non_exhaustive.stderr | 8 +- tests/ui/match_single_binding.stderr | 48 +- tests/ui/match_single_binding2.stderr | 8 +- tests/ui/match_str_case_mismatch.stderr | 14 +- tests/ui/match_wild_err_arm.stderr | 8 +- .../match_wildcard_for_single_variants.stderr | 20 +- tests/ui/mem_forget.stderr | 8 +- tests/ui/mem_replace.fixed | 8 + tests/ui/mem_replace.rs | 8 + tests/ui/mem_replace.stderr | 48 +- tests/ui/mem_replace_macro.rs | 4 +- tests/ui/mem_replace_macro.stderr | 6 +- tests/ui/mem_replace_no_std.stderr | 14 +- tests/ui/methods.stderr | 4 +- tests/ui/methods_fixable.stderr | 2 +- tests/ui/methods_unfixable.stderr | 4 +- tests/ui/min_ident_chars.rs | 6 + tests/ui/min_ident_chars.stderr | 78 ++- tests/ui/min_max.stderr | 26 +- tests/ui/min_rust_version_attr.stderr | 12 +- tests/ui/min_rust_version_invalid_attr.stderr | 12 +- tests/ui/mismatched_target_os_non_unix.stderr | 8 +- tests/ui/mismatched_target_os_unix.stderr | 34 +- tests/ui/mismatching_type_param_order.stderr | 20 +- tests/ui/misnamed_getters.stderr | 36 +- tests/ui/missing_assert_message.stderr | 32 +- tests/ui/missing_asserts_for_indexing.stderr | 94 ++-- ...sing_asserts_for_indexing_unfixable.stderr | 56 +- .../could_be_const.stderr | 22 +- tests/ui/missing_doc.stderr | 26 +- tests/ui/missing_doc_crate_missing.stderr | 2 +- tests/ui/missing_doc_impl.stderr | 14 +- tests/ui/missing_fields_in_debug.stderr | 16 +- tests/ui/missing_inline.stderr | 12 +- tests/ui/missing_panics_doc.stderr | 48 +- tests/ui/missing_spin_loop.stderr | 12 +- tests/ui/missing_spin_loop_no_std.stderr | 2 +- tests/ui/missing_trait_methods.stderr | 8 +- tests/ui/mistyped_literal_suffix.stderr | 32 +- .../ui/mixed_read_write_in_expression.stderr | 16 +- tests/ui/module_inception.stderr | 8 +- tests/ui/module_name_repetitions.stderr | 10 +- tests/ui/modulo_arithmetic_float.stderr | 20 +- tests/ui/modulo_arithmetic_integral.stderr | 34 +- .../modulo_arithmetic_integral_const.stderr | 34 +- tests/ui/modulo_one.stderr | 16 +- tests/ui/multi_assignments.stderr | 12 +- tests/ui/multiple_bound_locations.rs | 60 ++ tests/ui/multiple_bound_locations.stderr | 59 ++ tests/ui/multiple_unsafe_ops_per_block.stderr | 58 +- tests/ui/must_use_candidates.stderr | 10 +- tests/ui/must_use_unit.stderr | 6 +- tests/ui/mut_from_ref.stderr | 24 +- tests/ui/mut_key.stderr | 34 +- tests/ui/mut_mut.stderr | 18 +- tests/ui/mut_mutex_lock.stderr | 2 +- tests/ui/mut_range_bound.stderr | 14 +- tests/ui/mut_reference.stderr | 6 +- tests/ui/mutex_atomic.stderr | 22 +- tests/ui/needless_arbitrary_self_type.stderr | 12 +- ...dless_arbitrary_self_type_unfixable.stderr | 2 +- tests/ui/needless_bitwise_bool.stderr | 2 +- tests/ui/needless_bool/fixable.stderr | 42 +- tests/ui/needless_bool/simple.stderr | 8 +- tests/ui/needless_bool_assign.stderr | 10 +- tests/ui/needless_borrow.stderr | 54 +- tests/ui/needless_borrow_pat.stderr | 24 +- tests/ui/needless_borrowed_ref.stderr | 34 +- .../needless_borrows_for_generic_args.stderr | 24 +- tests/ui/needless_collect.stderr | 38 +- tests/ui/needless_collect_indirect.stderr | 32 +- tests/ui/needless_continue.stderr | 16 +- tests/ui/needless_doc_main.stderr | 8 +- tests/ui/needless_else.stderr | 2 +- tests/ui/needless_for_each_fixable.stderr | 16 +- tests/ui/needless_for_each_unfixable.stderr | 2 +- tests/ui/needless_if.stderr | 14 +- tests/ui/needless_late_init.stderr | 32 +- tests/ui/needless_lifetimes.stderr | 92 ++-- tests/ui/needless_match.stderr | 26 +- tests/ui/needless_option_as_deref.stderr | 6 +- tests/ui/needless_option_take.stderr | 2 +- .../needless_parens_on_range_literals.stderr | 12 +- tests/ui/needless_pass_by_ref_mut.stderr | 62 +-- tests/ui/needless_pass_by_value.stderr | 52 +- tests/ui/needless_pub_self.stderr | 6 +- tests/ui/needless_question_mark.stderr | 30 +- tests/ui/needless_range_loop.stderr | 28 +- tests/ui/needless_range_loop2.stderr | 16 +- tests/ui/needless_raw_string.stderr | 14 +- tests/ui/needless_raw_string_hashes.stderr | 30 +- tests/ui/needless_return.stderr | 104 ++-- .../needless_return_with_question_mark.stderr | 4 +- tests/ui/needless_splitn.stderr | 26 +- tests/ui/needless_update.stderr | 2 +- tests/ui/neg_cmp_op_on_partial_ord.stderr | 8 +- tests/ui/neg_multiply.stderr | 16 +- tests/ui/never_loop.stderr | 32 +- tests/ui/new_ret_no_self.stderr | 24 +- tests/ui/new_ret_no_self_overflow.stderr | 2 +- tests/ui/new_without_default.fixed | 10 +- tests/ui/new_without_default.rs | 4 +- tests/ui/new_without_default.stderr | 35 +- tests/ui/no_effect.stderr | 58 +- tests/ui/no_effect_async_fn.rs | 50 ++ tests/ui/no_effect_async_fn.stderr | 29 + tests/ui/no_effect_replace.stderr | 16 +- tests/ui/no_effect_return.stderr | 18 +- tests/ui/no_mangle_with_rust_abi.stderr | 10 +- tests/ui/non_canonical_clone_impl.stderr | 8 +- .../ui/non_canonical_partial_ord_impl.stderr | 4 +- ...nonical_partial_ord_impl_fully_qual.stderr | 4 +- tests/ui/non_expressive_names.stderr | 12 +- tests/ui/non_minimal_cfg.stderr | 8 +- tests/ui/non_minimal_cfg2.stderr | 2 +- tests/ui/non_octal_unix_permissions.stderr | 8 +- tests/ui/non_send_fields_in_send_ty.stderr | 52 +- tests/ui/nonminimal_bool.rs | 17 + tests/ui/nonminimal_bool.stderr | 127 ++++- tests/ui/nonminimal_bool_methods.stderr | 26 +- tests/ui/numbered_fields.stderr | 4 +- tests/ui/obfuscated_if_else.stderr | 2 +- tests/ui/octal_escapes.stderr | 18 +- tests/ui/ok_expect.stderr | 10 +- tests/ui/only_used_in_recursion.stderr | 64 +-- tests/ui/only_used_in_recursion2.stderr | 20 +- tests/ui/op_ref.stderr | 8 +- tests/ui/open_options.stderr | 16 +- tests/ui/open_options_fixable.stderr | 2 +- tests/ui/option_as_ref_cloned.stderr | 6 +- tests/ui/option_as_ref_deref.stderr | 36 +- tests/ui/option_env_unwrap.stderr | 14 +- tests/ui/option_filter_map.stderr | 16 +- tests/ui/option_if_let_else.stderr | 50 +- tests/ui/option_map_or_err_ok.stderr | 2 +- tests/ui/option_map_or_none.stderr | 10 +- tests/ui/option_map_unit_fn_fixable.stderr | 38 +- tests/ui/option_map_unit_fn_unfixable.stderr | 8 +- tests/ui/option_option.stderr | 26 +- tests/ui/or_fun_call.stderr | 62 +-- tests/ui/or_then_unwrap.stderr | 6 +- .../out_of_bounds_indexing/issue-3102.stderr | 4 +- tests/ui/out_of_bounds_indexing/simple.stderr | 12 +- tests/ui/overflow_check_conditional.stderr | 16 +- tests/ui/overly_complex_bool_expr.stderr | 20 +- tests/ui/panic_in_result_fn.stderr | 8 +- tests/ui/panic_in_result_fn_assertions.stderr | 12 +- tests/ui/panicking_macros.stderr | 32 +- tests/ui/partial_pub_fields.stderr | 8 +- tests/ui/partialeq_ne_impl.stderr | 2 +- tests/ui/partialeq_to_none.stderr | 30 +- tests/ui/path_buf_push_overwrite.stderr | 2 +- tests/ui/path_ends_with_ext.stderr | 4 +- .../pattern_type_mismatch/mutability.stderr | 4 +- .../pattern_alternatives.stderr | 6 +- .../pattern_structs.stderr | 16 +- .../pattern_tuples.stderr | 20 +- tests/ui/pattern_type_mismatch/syntax.stderr | 18 +- tests/ui/patterns.stderr | 6 +- .../ui/permissions_set_readonly_false.stderr | 2 +- tests/ui/precedence.stderr | 24 +- tests/ui/print.stderr | 16 +- tests/ui/print_in_format_impl.stderr | 14 +- tests/ui/print_literal.stderr | 32 +- tests/ui/print_stderr.stderr | 4 +- tests/ui/print_with_newline.stderr | 18 +- tests/ui/println_empty_string.stderr | 8 +- tests/ui/proc_macro.stderr | 2 +- tests/ui/ptr_arg.stderr | 48 +- tests/ui/ptr_as_ptr.stderr | 66 +-- tests/ui/ptr_cast_constness.stderr | 14 +- tests/ui/ptr_eq.stderr | 4 +- tests/ui/ptr_eq_no_std.stderr | 4 +- tests/ui/ptr_offset_with_cast.stderr | 4 +- tests/ui/pub_use.stderr | 2 +- tests/ui/pub_with_shorthand.stderr | 8 +- tests/ui/pub_without_shorthand.stderr | 6 +- tests/ui/question_mark.stderr | 32 +- tests/ui/question_mark_used.stderr | 2 +- tests/ui/range.stderr | 2 +- tests/ui/range_contains.stderr | 42 +- tests/ui/range_plus_minus_one.stderr | 18 +- tests/ui/rc_buffer.stderr | 16 +- tests/ui/rc_buffer_arc.stderr | 16 +- tests/ui/rc_clone_in_vec_init/arc.stderr | 8 +- tests/ui/rc_clone_in_vec_init/rc.stderr | 8 +- tests/ui/rc_clone_in_vec_init/weak.stderr | 16 +- tests/ui/rc_mutex.stderr | 8 +- tests/ui/read_line_without_trim.fixed | 13 + tests/ui/read_line_without_trim.rs | 13 + tests/ui/read_line_without_trim.stderr | 70 ++- tests/ui/read_zero_byte_vec.stderr | 22 +- tests/ui/readonly_write_lock.stderr | 4 +- tests/ui/recursive_format_impl.stderr | 20 +- tests/ui/redundant_allocation.stderr | 40 +- tests/ui/redundant_allocation_fixable.stderr | 24 +- tests/ui/redundant_as_str.stderr | 4 +- tests/ui/redundant_async_block.stderr | 20 +- tests/ui/redundant_at_rest_pattern.stderr | 12 +- tests/ui/redundant_clone.stderr | 60 +- tests/ui/redundant_closure_call_early.stderr | 4 +- .../ui/redundant_closure_call_fixable.stderr | 34 +- tests/ui/redundant_closure_call_late.stderr | 6 +- tests/ui/redundant_else.stderr | 14 +- tests/ui/redundant_field_names.stderr | 16 +- tests/ui/redundant_guards.fixed | 57 +- tests/ui/redundant_guards.rs | 57 +- tests/ui/redundant_guards.stderr | 98 +++- tests/ui/redundant_locals.stderr | 56 +- ...dundant_pattern_matching_drop_order.stderr | 44 +- ...undant_pattern_matching_if_let_true.stderr | 14 +- .../redundant_pattern_matching_ipaddr.stderr | 40 +- .../redundant_pattern_matching_option.stderr | 60 +- .../ui/redundant_pattern_matching_poll.stderr | 40 +- .../redundant_pattern_matching_result.stderr | 56 +- tests/ui/redundant_pub_crate.stderr | 32 +- tests/ui/redundant_slicing.stderr | 6 +- tests/ui/redundant_static_lifetimes.stderr | 36 +- ...redundant_static_lifetimes_multiple.stderr | 20 +- tests/ui/redundant_type_annotations.stderr | 34 +- tests/ui/ref_as_ptr.fixed | 88 +-- tests/ui/ref_as_ptr.rs | 88 +-- tests/ui/ref_as_ptr.stderr | 244 ++++----- tests/ui/ref_binding_to_reference.stderr | 14 +- tests/ui/ref_option_ref.stderr | 22 +- tests/ui/ref_patterns.stderr | 6 +- tests/ui/regex.stderr | 48 +- tests/ui/rename.stderr | 116 ++-- tests/ui/renamed_builtin_attr.stderr | 2 +- tests/ui/repeat_once.stderr | 12 +- tests/ui/repeat_vec_with_capacity.stderr | 6 +- tests/ui/repl_uninit.stderr | 8 +- tests/ui/reserve_after_initialization.stderr | 6 +- .../ui/rest_pat_in_fully_bound_structs.stderr | 6 +- tests/ui/result_filter_map.stderr | 8 +- tests/ui/result_large_err.stderr | 24 +- tests/ui/result_map_or_into_option.stderr | 6 +- tests/ui/result_map_unit_fn_fixable.stderr | 36 +- tests/ui/result_map_unit_fn_unfixable.stderr | 12 +- tests/ui/result_unit_error.stderr | 10 +- tests/ui/return_self_not_must_use.stderr | 6 +- tests/ui/reversed_empty_ranges_fixable.stderr | 8 +- ...reversed_empty_ranges_loops_fixable.stderr | 12 +- ...versed_empty_ranges_loops_unfixable.stderr | 4 +- .../ui/reversed_empty_ranges_unfixable.stderr | 6 +- .../ui/same_functions_in_if_condition.stderr | 26 +- tests/ui/same_item_push.stderr | 10 +- tests/ui/same_name_method.stderr | 24 +- tests/ui/search_is_some.stderr | 16 +- tests/ui/search_is_some_fixable_none.stderr | 86 +-- tests/ui/search_is_some_fixable_some.stderr | 94 ++-- tests/ui/seek_from_current.stderr | 2 +- .../ui/seek_to_start_instead_of_rewind.stderr | 6 +- tests/ui/self_assignment.stderr | 22 +- tests/ui/self_named_constructors.stderr | 2 +- tests/ui/semicolon_if_nothing_returned.fixed | 7 +- tests/ui/semicolon_if_nothing_returned.rs | 7 +- tests/ui/semicolon_if_nothing_returned.stderr | 10 +- tests/ui/semicolon_inside_block.stderr | 8 +- tests/ui/semicolon_outside_block.stderr | 8 +- tests/ui/serde.stderr | 2 +- tests/ui/shadow.stderr | 92 ++-- tests/ui/short_circuit_statement.stderr | 6 +- .../ui/should_impl_trait/method_list_1.stderr | 30 +- .../ui/should_impl_trait/method_list_2.stderr | 30 +- tests/ui/should_panic_without_expect.stderr | 4 +- tests/ui/significant_drop_in_scrutinee.stderr | 52 +- tests/ui/significant_drop_tightening.stderr | 8 +- tests/ui/similar_names.rs | 5 +- tests/ui/similar_names.stderr | 50 +- tests/ui/single_call_fn.rs | 22 + tests/ui/single_call_fn.stderr | 76 ++- tests/ui/single_char_add_str.stderr | 30 +- tests/ui/single_char_lifetime_names.stderr | 10 +- tests/ui/single_char_pattern.stderr | 80 +-- tests/ui/single_component_path_imports.stderr | 4 +- ...component_path_imports_nested_first.stderr | 6 +- tests/ui/single_element_loop.stderr | 14 +- tests/ui/single_match.stderr | 36 +- tests/ui/single_match_else.stderr | 18 +- tests/ui/single_range_in_vec_init.stderr | 20 +- .../expressions.stderr | 8 +- .../size_of_in_element_count/functions.stderr | 42 +- tests/ui/size_of_ref.stderr | 6 +- tests/ui/skip_while_next.stderr | 4 +- tests/ui/slow_vector_initialization.stderr | 26 +- tests/ui/stable_sort_primitive.stderr | 14 +- tests/ui/starts_ends_with.stderr | 32 +- tests/ui/std_instead_of_core.stderr | 22 +- tests/ui/str_split.stderr | 20 +- tests/ui/str_to_string.stderr | 4 +- tests/ui/string_add.stderr | 8 +- tests/ui/string_add_assign.stderr | 6 +- tests/ui/string_extend.stderr | 8 +- tests/ui/string_from_utf8_as_bytes.stderr | 2 +- tests/ui/string_lit_as_bytes.stderr | 14 +- tests/ui/string_lit_chars_any.stderr | 10 +- tests/ui/string_slice.stderr | 6 +- tests/ui/string_to_string.stderr | 2 +- tests/ui/strlen_on_c_strings.stderr | 14 +- tests/ui/struct_excessive_bools.stderr | 4 +- tests/ui/struct_fields.rs | 8 +- tests/ui/struct_fields.stderr | 50 +- tests/ui/suspicious_arithmetic_impl.stderr | 18 +- tests/ui/suspicious_command_arg_space.stderr | 4 +- tests/ui/suspicious_doc_comments.stderr | 18 +- .../suspicious_doc_comments_unfixable.stderr | 4 +- tests/ui/suspicious_else_formatting.stderr | 18 +- tests/ui/suspicious_map.stderr | 4 +- .../ui/suspicious_operation_groupings.stderr | 52 +- tests/ui/suspicious_splitn.stderr | 18 +- tests/ui/suspicious_to_owned.stderr | 12 +- .../ui/suspicious_unary_op_formatting.stderr | 8 +- tests/ui/suspicious_xor_used_as_pow.stderr | 14 +- tests/ui/swap.stderr | 34 +- tests/ui/swap_ptr_to_ref.stderr | 8 +- tests/ui/swap_ptr_to_ref_unfixable.stderr | 6 +- tests/ui/tabs_in_doc_comments.stderr | 16 +- tests/ui/temporary_assignment.stderr | 8 +- tests/ui/test_attr_in_doctest.stderr | 6 +- tests/ui/tests_outside_test_module.stderr | 2 +- ...local_initializer_can_be_made_const.stderr | 8 +- tests/ui/to_digit_is_some.stderr | 4 +- ...to_string_in_format_args_incremental.fixed | 8 - tests/ui/to_string_trait_impl.rs | 44 ++ tests/ui/to_string_trait_impl.stderr | 16 +- tests/ui/toplevel_ref_arg.stderr | 12 +- tests/ui/toplevel_ref_arg_non_rustfix.stderr | 4 +- tests/ui/track-diagnostics.stderr | 2 +- tests/ui/trailing_empty_array.stderr | 22 +- tests/ui/trailing_zeros.stderr | 4 +- tests/ui/trait_duplication_in_bounds.stderr | 20 +- .../trait_duplication_in_bounds_unfixable.rs | 1 + ...ait_duplication_in_bounds_unfixable.stderr | 18 +- tests/ui/transmute.stderr | 72 +-- tests/ui/transmute_32bit.stderr | 8 +- tests/ui/transmute_64bit.stderr | 4 +- tests/ui/transmute_collection.stderr | 36 +- tests/ui/transmute_float_to_int.stderr | 12 +- tests/ui/transmute_int_to_char.stderr | 4 +- tests/ui/transmute_int_to_char_no_std.stderr | 4 +- tests/ui/transmute_int_to_non_zero.stderr | 20 +- tests/ui/transmute_null_to_fn.stderr | 12 +- tests/ui/transmute_ptr_to_ptr.stderr | 14 +- tests/ui/transmute_ptr_to_ref.stderr | 44 +- tests/ui/transmute_ref_to_ref.stderr | 8 +- tests/ui/transmute_ref_to_ref_no_std.stderr | 8 +- tests/ui/transmute_undefined_repr.stderr | 24 +- ...transmutes_expressible_as_ptr_casts.stderr | 20 +- tests/ui/transmuting_null.stderr | 6 +- tests/ui/trim_split_whitespace.stderr | 16 +- tests/ui/trivially_copy_pass_by_ref.stderr | 38 +- tests/ui/try_err.stderr | 24 +- tests/ui/tuple_array_conversions.stderr | 20 +- tests/ui/type_complexity.stderr | 30 +- tests/ui/type_id_on_box.stderr | 6 +- tests/ui/type_repetition_in_bounds.rs | 2 +- tests/ui/type_repetition_in_bounds.stderr | 12 +- tests/ui/types.stderr | 2 +- .../ui/unchecked_duration_subtraction.stderr | 8 +- tests/ui/unconditional_recursion.rs | 2 +- tests/ui/unconditional_recursion.stderr | 91 ++-- tests/ui/unicode.stderr | 20 +- tests/ui/uninhabited_references.stderr | 8 +- tests/ui/uninit.stderr | 6 +- tests/ui/uninit_vec.stderr | 22 +- tests/ui/uninlined_format_args.stderr | 142 ++--- ...lined_format_args_panic.edition2018.stderr | 2 +- ...lined_format_args_panic.edition2021.stderr | 12 +- tests/ui/unit_arg.stderr | 20 +- tests/ui/unit_arg_empty_blocks.stderr | 8 +- tests/ui/unit_cmp.stderr | 12 +- tests/ui/unit_hash.stderr | 6 +- tests/ui/unit_return_expecting_ord.stderr | 12 +- tests/ui/unknown_attribute.stderr | 2 +- tests/ui/unknown_clippy_lints.stderr | 18 +- tests/ui/unnecessary_box_returns.stderr | 8 +- tests/ui/unnecessary_cast.fixed | 1 + tests/ui/unnecessary_cast.rs | 1 + tests/ui/unnecessary_cast.stderr | 80 +-- tests/ui/unnecessary_cast_unfixable.stderr | 4 +- tests/ui/unnecessary_clippy_cfg.rs | 23 + tests/ui/unnecessary_clippy_cfg.stderr | 61 +++ tests/ui/unnecessary_clone.stderr | 18 +- .../ui/unnecessary_fallible_conversions.fixed | 37 ++ tests/ui/unnecessary_fallible_conversions.rs | 37 ++ .../unnecessary_fallible_conversions.stderr | 124 ++++- ...sary_fallible_conversions_unfixable.stderr | 12 +- tests/ui/unnecessary_filter_map.stderr | 10 +- tests/ui/unnecessary_find_map.stderr | 10 +- tests/ui/unnecessary_fold.stderr | 32 +- tests/ui/unnecessary_get_then_check.fixed | 26 + tests/ui/unnecessary_get_then_check.rs | 26 + tests/ui/unnecessary_get_then_check.stderr | 75 +++ tests/ui/unnecessary_iter_cloned.stderr | 4 +- tests/ui/unnecessary_join.stderr | 4 +- tests/ui/unnecessary_lazy_eval.stderr | 126 ++--- .../ui/unnecessary_lazy_eval_unfixable.stderr | 8 +- tests/ui/unnecessary_literal_unwrap.stderr | 106 ++-- ...nnecessary_literal_unwrap_unfixable.stderr | 204 +++---- .../ui/unnecessary_map_on_constructor.stderr | 16 +- tests/ui/unnecessary_operation.stderr | 38 +- .../ui/unnecessary_owned_empty_strings.stderr | 4 +- .../ui/unnecessary_result_map_or_else.stderr | 8 +- tests/ui/unnecessary_safety_comment.stderr | 36 +- tests/ui/unnecessary_self_imports.stderr | 4 +- tests/ui/unnecessary_sort_by.stderr | 24 +- .../unnecessary_struct_initialization.stderr | 12 +- tests/ui/unnecessary_to_owned.fixed | 36 ++ tests/ui/unnecessary_to_owned.rs | 36 ++ tests/ui/unnecessary_to_owned.stderr | 202 ++++--- tests/ui/unnecessary_to_owned_on_split.stderr | 18 +- tests/ui/unnecessary_unsafety_doc.stderr | 14 +- tests/ui/unnecessary_wraps.stderr | 14 +- tests/ui/unneeded_field_pattern.stderr | 4 +- tests/ui/unneeded_wildcard_pattern.stderr | 30 +- tests/ui/unnested_or_patterns.stderr | 34 +- tests/ui/unnested_or_patterns2.stderr | 16 +- tests/ui/unreadable_literal.stderr | 20 +- tests/ui/unsafe_derive_deserialize.stderr | 8 +- tests/ui/unsafe_removed_from_name.stderr | 10 +- tests/ui/unseparated_prefix_literals.stderr | 18 +- tests/ui/unused_async.stderr | 10 +- tests/ui/unused_enumerate_index.stderr | 4 +- tests/ui/unused_format_specs_unfixable.stderr | 8 +- tests/ui/unused_io_amount.stderr | 70 +-- tests/ui/unused_peekable.stderr | 16 +- tests/ui/unused_rounding.stderr | 10 +- tests/ui/unused_self.stderr | 18 +- tests/ui/unused_unit.fixed | 7 + tests/ui/unused_unit.rs | 7 + tests/ui/unused_unit.stderr | 40 +- tests/ui/unwrap.stderr | 6 +- tests/ui/unwrap_expect_used.stderr | 12 +- tests/ui/unwrap_in_result.stderr | 8 +- tests/ui/unwrap_or.stderr | 4 +- tests/ui/unwrap_or_else_default.stderr | 32 +- tests/ui/upper_case_acronyms.stderr | 24 +- tests/ui/use_self.stderr | 84 +-- tests/ui/use_self_trait.stderr | 32 +- tests/ui/used_underscore_binding.stderr | 24 +- tests/ui/useless_asref.stderr | 38 +- tests/ui/useless_attribute.fixed | 10 +- tests/ui/useless_attribute.rs | 10 +- tests/ui/useless_attribute.stderr | 10 +- tests/ui/useless_conversion.stderr | 76 +-- tests/ui/useless_conversion_try.stderr | 20 +- tests/ui/vec.fixed | 4 + tests/ui/vec.rs | 4 + tests/ui/vec.stderr | 48 +- tests/ui/vec_box_sized.stderr | 18 +- tests/ui/vec_init_then_push.stderr | 16 +- tests/ui/vec_resize_to_zero.stderr | 2 +- tests/ui/verbose_file_reads.stderr | 4 +- tests/ui/waker_clone_wake.stderr | 4 +- tests/ui/while_let_loop.stderr | 10 +- tests/ui/while_let_on_iterator.stderr | 54 +- tests/ui/wild_in_or_pats.stderr | 8 +- tests/ui/wildcard_enum_match_arm.stderr | 14 +- tests/ui/wildcard_imports.stderr | 44 +- .../wildcard_imports_2021.edition2018.stderr | 44 +- .../wildcard_imports_2021.edition2021.stderr | 44 +- tests/ui/write_literal.stderr | 24 +- tests/ui/write_literal_2.stderr | 28 +- tests/ui/write_with_newline.stderr | 18 +- tests/ui/writeln_empty_string.stderr | 4 +- tests/ui/wrong_self_convention.stderr | 48 +- tests/ui/wrong_self_convention2.stderr | 4 +- tests/ui/wrong_self_conventions_mut.stderr | 4 +- tests/ui/zero_div_zero.stderr | 8 +- tests/ui/zero_offset.stderr | 16 +- tests/ui/zero_ptr.stderr | 10 +- tests/ui/zero_ptr_no_std.stderr | 8 +- tests/ui/zero_sized_btreemap_values.stderr | 26 +- tests/ui/zero_sized_hashmap_values.stderr | 26 +- triagebot.toml | 4 +- util/gh-pages/index.html | 14 +- 1096 files changed, 14122 insertions(+), 10811 deletions(-) create mode 100644 clippy_lints/src/methods/unnecessary_get_then_check.rs create mode 100644 clippy_lints/src/multiple_bound_locations.rs create mode 100644 tests/ui-toml/disallowed_macros/auxiliary/proc_macros.rs create mode 100644 tests/ui/asm_syntax_not_x86.rs rename tests/ui/{asm_syntax.stderr => asm_syntax_x86.i686.stderr} (58%) rename tests/ui/{asm_syntax.rs => asm_syntax_x86.rs} (64%) create mode 100644 tests/ui/asm_syntax_x86.x86_64.stderr create mode 100644 tests/ui/cfg_attr_cargo_clippy.fixed create mode 100644 tests/ui/cfg_attr_cargo_clippy.rs create mode 100644 tests/ui/cfg_attr_cargo_clippy.stderr create mode 100644 tests/ui/crashes/ice-12253.rs create mode 100644 tests/ui/empty_docs.rs create mode 100644 tests/ui/empty_docs.stderr create mode 100644 tests/ui/multiple_bound_locations.rs create mode 100644 tests/ui/multiple_bound_locations.stderr create mode 100644 tests/ui/no_effect_async_fn.rs create mode 100644 tests/ui/no_effect_async_fn.stderr delete mode 100644 tests/ui/to_string_in_format_args_incremental.fixed create mode 100644 tests/ui/unnecessary_clippy_cfg.rs create mode 100644 tests/ui/unnecessary_clippy_cfg.stderr create mode 100644 tests/ui/unnecessary_get_then_check.fixed create mode 100644 tests/ui/unnecessary_get_then_check.rs create mode 100644 tests/ui/unnecessary_get_then_check.stderr diff --git a/.github/driver.sh b/.github/driver.sh index 40a2aad0f5379..11fd6b5c79ed8 100755 --- a/.github/driver.sh +++ b/.github/driver.sh @@ -32,7 +32,7 @@ test "$sysroot" = $desired_sysroot ) # Check that the --sysroot argument is only passed once via arg_file.txt (SYSROOT is ignored) -( +( echo "fn main() {}" > target/driver_test.rs echo "--sysroot="$(./target/debug/clippy-driver --print sysroot)"" > arg_file.txt echo "--verbose" >> arg_file.txt @@ -45,7 +45,7 @@ unset CARGO_MANIFEST_DIR # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 # FIXME: How to match the clippy invocation in compile-test.rs? ./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1 -sed -e "s,tests/ui,\$DIR," -e "/= help: for/d" double_neg.stderr > normalized.stderr +sed -e "/= help: for/d" double_neg.stderr > normalized.stderr diff -u normalized.stderr tests/ui/double_neg.stderr # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b853567219c9..f0b01742deb05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5125,6 +5125,7 @@ Released 2018-09-13 [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access [`default_union_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_union_representation [`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr +[`deprecated_clippy_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_clippy_cfg_attr [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof [`deref_by_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_by_slicing @@ -5157,6 +5158,7 @@ Released 2018-09-13 [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else +[`empty_docs`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_docs [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum [`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum_variants_with_brackets @@ -5429,6 +5431,7 @@ Released 2018-09-13 [`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic [`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one [`multi_assignments`]: https://rust-lang.github.io/rust-clippy/master/index.html#multi_assignments +[`multiple_bound_locations`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations [`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions [`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl [`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_unsafe_ops_per_block @@ -5725,10 +5728,12 @@ Released 2018-09-13 [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints [`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast +[`unnecessary_clippy_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_clippy_cfg [`unnecessary_fallible_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map [`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map [`unnecessary_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fold +[`unnecessary_get_then_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_get_then_check [`unnecessary_join`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_join [`unnecessary_lazy_evaluations`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations [`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap diff --git a/Cargo.toml b/Cargo.toml index 321424880d1e2..5d1d0ce2c42fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,17 +27,17 @@ rustc_tools_util = "0.3.0" tempfile = { version = "3.2", optional = true } termize = "0.1" color-print = "0.3.4" -anstream = "0.5.0" +anstream = "0.6.0" [dev-dependencies] -ui_test = "0.21.2" +ui_test = "0.22.2" tester = "0.9" regex = "1.5" toml = "0.7.3" walkdir = "2.3" # This is used by the `collect-metadata` alias. filetime = "0.2" -itertools = "0.11" +itertools = "0.12" # UI test dependencies clippy_utils = { path = "clippy_utils" } diff --git a/book/src/configuration.md b/book/src/configuration.md index e8274bc4575d0..9eb067abd91ec 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -33,26 +33,29 @@ disallowed-names = ["bar", ".."] # -> ["bar", "foo", "baz", "quux"] To deactivate the "for further information visit *lint-link*" message you can define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable. -### Allowing/denying lints +### Allowing/Denying Lints -You can add options to your code to `allow`/`warn`/`deny` Clippy lints: +#### Attributes in Code -* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`) +You can add attributes to your code to `allow`/`warn`/`deny` Clippy lints: -* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`, - `#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive lints prone to false - positives. +* the whole set of `warn`-by-default lints using the `clippy` lint group (`#![allow(clippy::all)]`) + +* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![warn(clippy::all, clippy::pedantic)]`. Note + that `clippy::pedantic` contains some very aggressive lints prone to false positives. * only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.) * `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc. Note: `allow` means to suppress the lint for your code. With `warn` the lint will only emit a warning, while with `deny` -the lint will emit an error, when triggering for your code. An error causes clippy to exit with an error code, so is -useful in scripts like CI/CD. +the lint will emit an error, when triggering for your code. An error causes Clippy to exit with an error code, so is +most useful in scripts used in CI/CD. + +#### Command Line Flags -If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra -flags to Clippy during the run: +If you do not want to include your lint levels in the code, you can globally enable/disable lints by passing extra flags +to Clippy during the run: To allow `lint_name`, run @@ -66,19 +69,33 @@ And to warn on `lint_name`, run cargo clippy -- -W clippy::lint_name ``` -This also works with lint groups. For example, you can run Clippy with warnings for all lints enabled: +This also works with lint groups. For example, you can run Clippy with warnings for all pedantic lints enabled: ```terminal cargo clippy -- -W clippy::pedantic ``` -If you care only about a single lint, you can allow all others and then explicitly warn on the lint(s) you are +If you care only about a certain lints, you can allow all others and then explicitly warn on the lints you are interested in: ```terminal cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::... ``` +#### Lints Section in `Cargo.toml` + +Finally, lints can be allowed/denied using [the lints +section](https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-lints-section)) in the `Cargo.toml` file: + +To deny `clippy::enum_glob_use`, put the following in the `Cargo.toml`: + +```toml +[lints.clippy] +enum_glob_use = "deny" +``` + +For more details and options, refer to the Cargo documentation. + ### Specifying the minimum supported Rust version Projects that intend to support old versions of Rust can disable lints pertaining to newer features by specifying the @@ -113,17 +130,14 @@ found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv) Very rarely, you may wish to prevent Clippy from evaluating certain sections of code entirely. You can do this with [conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html) by checking that the -`cargo-clippy` feature is not set. You may need to provide a stub so that the code compiles: +`clippy` cfg is not set. You may need to provide a stub so that the code compiles: ```rust -#[cfg(not(feature = "cargo-clippy"))] +#[cfg(not(clippy)] include!(concat!(env!("OUT_DIR"), "/my_big_function-generated.rs")); -#[cfg(feature = "cargo-clippy")] +#[cfg(clippy)] fn my_big_function(_input: &str) -> Option { None } ``` - -This feature is not actually part of your crate, so specifying `--all-features` to other tools, e.g. `cargo test ---all-features`, will not disable it. diff --git a/book/src/development/emitting_lints.md b/book/src/development/emitting_lints.md index a12f6aa91b307..d70f4fc17ebf0 100644 --- a/book/src/development/emitting_lints.md +++ b/book/src/development/emitting_lints.md @@ -82,7 +82,7 @@ The output looks something like this (from the example earlier): ```text error: an inclusive range would be more readable - --> $DIR/range_plus_minus_one.rs:37:14 + --> tests/ui/range_plus_minus_one.rs:37:14 | LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` @@ -135,14 +135,14 @@ Examples: ```text error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing. - --> $DIR/drop_forget_ref.rs:10:5 + --> tests/ui/drop_forget_ref.rs:10:5 | 10 | forget(&SomeStruct); | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::forget-ref` implied by `-D warnings` note: argument has type &SomeStruct - --> $DIR/drop_forget_ref.rs:10:12 + --> tests/ui/drop_forget_ref.rs:10:12 | 10 | forget(&SomeStruct); | ^^^^^^^^^^^ @@ -158,7 +158,7 @@ Example: ```text error: constant division of 0.0 with 0.0 will always result in NaN - --> $DIR/zero_div_zero.rs:6:25 + --> tests/ui/zero_div_zero.rs:6:25 | 6 | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ @@ -176,7 +176,7 @@ Example: ```text error: This `.fold` can be more succinctly expressed as `.any` ---> $DIR/methods.rs:390:13 +--> tests/ui/methods.rs:390:13 | 390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)` diff --git a/book/src/development/writing_tests.md b/book/src/development/writing_tests.md index 8937e0d8e9469..39a5ad9668851 100644 --- a/book/src/development/writing_tests.md +++ b/book/src/development/writing_tests.md @@ -97,19 +97,19 @@ failures: ---- compile_test stdout ---- normalized stderr: error: function called "foo" - --> $DIR/foo_functions.rs:6:12 + --> tests/ui/foo_functions.rs:6:12 | LL | pub fn foo(&self) {} | ^^^ | = note: `-D clippy::foo-functions` implied by `-D warnings` error: function called "foo" - --> $DIR/foo_functions.rs:13:8 + --> tests/ui/foo_functions.rs:13:8 | LL | fn foo(&self) {} | ^^^ error: function called "foo" - --> $DIR/foo_functions.rs:19:4 + --> tests/ui/foo_functions.rs:19:4 | LL | fn foo() {} | ^^^ diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index f2357e2b5de92..214a60d3bfdf7 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -278,7 +278,7 @@ The minimum number of struct fields for the lints about field names to trigger --- **Affected lints:** -* [`struct_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_variant_names) +* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names) ## `enum-variant-size-threshold` diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 9741b94d50413..b781259ad9695 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -325,7 +325,7 @@ define_Conf! { /// /// The minimum number of enum variants for the lints about variant names to trigger (enum_variant_name_threshold: u64 = 3), - /// Lint: STRUCT_VARIANT_NAMES. + /// Lint: STRUCT_FIELD_NAMES. /// /// The minimum number of struct fields for the lints about field names to trigger (struct_field_name_threshold: u64 = 3), @@ -648,7 +648,7 @@ fn deserialize(file: &SourceFile) -> TryConf { extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS); extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES); // TODO: THIS SHOULD BE TESTED, this comment will be gone soon - if conf.conf.allowed_idents_below_min_chars.contains(&"..".to_owned()) { + if conf.conf.allowed_idents_below_min_chars.contains("..") { conf.conf .allowed_idents_below_min_chars .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string)); diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 5449feed090a9..dab3119894a4d 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -6,7 +6,7 @@ clippy::missing_panics_doc, rustc::diagnostic_outside_of_impl, rustc::untranslatable_diagnostic, - rustc::untranslatable_diagnostic_trivial, + rustc::untranslatable_diagnostic_trivial )] extern crate rustc_ast; diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 5ec67554e7d89..42a953039b1c0 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" aho-corasick = "1.0" clap = "4.1.4" indoc = "1.0" -itertools = "0.11" +itertools = "0.12" opener = "0.6" shell-escape = "0.1" walkdir = "2.3" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 6e6e315bb6561..6ae089b3e0321 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -14,7 +14,7 @@ cargo_metadata = "0.18" clippy_config = { path = "../clippy_config" } clippy_utils = { path = "../clippy_utils" } declare_clippy_lint = { path = "../declare_clippy_lint" } -itertools = "0.11" +itertools = "0.12" quine-mc_cluskey = "0.2" regex-syntax = "0.8" serde = { version = "1.0", features = ["derive"] } diff --git a/clippy_lints/src/asm_syntax.rs b/clippy_lints/src/asm_syntax.rs index feb6437ee26ac..c2fa56e136031 100644 --- a/clippy_lints/src/asm_syntax.rs +++ b/clippy_lints/src/asm_syntax.rs @@ -2,8 +2,11 @@ use std::fmt; use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions}; -use rustc_lint::{EarlyContext, EarlyLintPass, Lint}; +use rustc_ast::{InlineAsm, Item, ItemKind}; +use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; use rustc_session::declare_lint_pass; +use rustc_span::Span; +use rustc_target::asm::InlineAsmArch; #[derive(Clone, Copy, PartialEq, Eq)] enum AsmStyle { @@ -31,8 +34,14 @@ impl std::ops::Not for AsmStyle { } } -fn check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr, check_for: AsmStyle) { - if let ExprKind::InlineAsm(ref inline_asm) = expr.kind { +fn check_asm_syntax( + lint: &'static Lint, + cx: &EarlyContext<'_>, + inline_asm: &InlineAsm, + span: Span, + check_for: AsmStyle, +) { + if matches!(cx.sess().asm_arch, Some(InlineAsmArch::X86 | InlineAsmArch::X86_64)) { let style = if inline_asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { AsmStyle::Att } else { @@ -43,7 +52,7 @@ fn check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr span_lint_and_help( cx, lint, - expr.span, + span, &format!("{style} x86 assembly syntax used"), None, &format!("use {} x86 assembly syntax", !style), @@ -89,7 +98,15 @@ declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]); impl EarlyLintPass for InlineAsmX86IntelSyntax { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - check_expr_asm_syntax(Self::get_lints()[0], cx, expr, AsmStyle::Intel); + if let ExprKind::InlineAsm(inline_asm) = &expr.kind { + check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Intel); + } + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if let ItemKind::GlobalAsm(inline_asm) = &item.kind { + check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Intel); + } } } @@ -130,6 +147,14 @@ declare_lint_pass!(InlineAsmX86AttSyntax => [INLINE_ASM_X86_ATT_SYNTAX]); impl EarlyLintPass for InlineAsmX86AttSyntax { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - check_expr_asm_syntax(Self::get_lints()[0], cx, expr, AsmStyle::Att); + if let ExprKind::InlineAsm(inline_asm) = &expr.kind { + check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Att); + } + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + if let ItemKind::GlobalAsm(inline_asm) = &item.kind { + check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Att); + } } } diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index da38422874b44..f2937d51340b8 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -1,7 +1,9 @@ //! checks for attributes use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{ + span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, +}; use clippy_utils::is_from_proc_macro; use clippy_utils::macros::{is_panic, macro_backtrace}; use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments}; @@ -433,6 +435,56 @@ declare_clippy_lint! { "prevent from misusing the wrong attr name" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for + /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with + /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`. + /// + /// ### Why is this bad? + /// This feature has been deprecated for years and shouldn't be used anymore. + /// + /// ### Example + /// ```no_run + /// #[cfg(feature = "cargo-clippy")] + /// struct Bar; + /// ``` + /// + /// Use instead: + /// ```no_run + /// #[cfg(clippy)] + /// struct Bar; + /// ``` + #[clippy::version = "1.78.0"] + pub DEPRECATED_CLIPPY_CFG_ATTR, + suspicious, + "usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`" +} + +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` + /// and suggests to replace it with `#[allow(clippy::lint)]`. + /// + /// ### Why is this bad? + /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not + /// run by anything else than clippy. + /// + /// ### Example + /// ```no_run + /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))] + /// ``` + /// + /// Use instead: + /// ```no_run + /// #![allow(clippy::deprecated_cfg_attr)] + /// ``` + #[clippy::version = "1.78.0"] + pub UNNECESSARY_CLIPPY_CFG, + suspicious, + "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`" +} + declare_lint_pass!(Attributes => [ ALLOW_ATTRIBUTES_WITHOUT_REASON, INLINE_ALWAYS, @@ -512,6 +564,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { || is_word(lint, sym::deprecated) || is_word(lint, sym!(unreachable_pub)) || is_word(lint, sym!(unused)) + || is_word(lint, sym!(unused_import_braces)) || extract_clippy_lint(lint).map_or(false, |s| { matches!( s.as_str(), @@ -794,6 +847,8 @@ impl_lint_pass!(EarlyAttributes => [ EMPTY_LINE_AFTER_DOC_COMMENTS, NON_MINIMAL_CFG, MAYBE_MISUSED_CFG, + DEPRECATED_CLIPPY_CFG_ATTR, + UNNECESSARY_CLIPPY_CFG, ]); impl EarlyLintPass for EarlyAttributes { @@ -803,6 +858,7 @@ impl EarlyLintPass for EarlyAttributes { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) { check_deprecated_cfg_attr(cx, attr, &self.msrv); + check_deprecated_cfg(cx, attr); check_mismatched_target_os(cx, attr); check_minimal_cfg_condition(cx, attr); check_misused_cfg(cx, attr); @@ -857,39 +913,146 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It } } +fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) { + if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") { + span_lint_and_sugg( + cx, + DEPRECATED_CLIPPY_CFG_ATTR, + item.span, + "`feature = \"cargo-clippy\"` was replaced by `clippy`", + "replace with", + "clippy".to_string(), + Applicability::MachineApplicable, + ); + } +} + +fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) { + if let Some(ident) = attr.ident() { + if ["any", "all", "not"].contains(&ident.name.as_str()) { + let Some(list) = attr.meta_item_list() else { return }; + for item in list.iter().filter_map(|item| item.meta_item()) { + check_deprecated_cfg_recursively(cx, item); + } + } else { + check_cargo_clippy_attr(cx, attr); + } + } +} + +fn check_deprecated_cfg(cx: &EarlyContext<'_>, attr: &Attribute) { + if attr.has_name(sym::cfg) + && let Some(list) = attr.meta_item_list() + { + for item in list.iter().filter_map(|item| item.meta_item()) { + check_deprecated_cfg_recursively(cx, item); + } + } +} + fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) { - if msrv.meets(msrvs::TOOL_ATTRIBUTES) - // check cfg_attr - && attr.has_name(sym::cfg_attr) + // check cfg_attr + if attr.has_name(sym::cfg_attr) && let Some(items) = attr.meta_item_list() && items.len() == 2 - // check for `rustfmt` && let Some(feature_item) = items[0].meta_item() - && feature_item.has_name(sym::rustfmt) - // check for `rustfmt_skip` and `rustfmt::skip` - && let Some(skip_item) = &items[1].meta_item() - && (skip_item.has_name(sym!(rustfmt_skip)) - || skip_item - .path - .segments - .last() - .expect("empty path in attribute") - .ident - .name - == sym::skip) - // Only lint outer attributes, because custom inner attributes are unstable - // Tracking issue: https://github.com/rust-lang/rust/issues/54726 - && attr.style == AttrStyle::Outer { - span_lint_and_sugg( - cx, - DEPRECATED_CFG_ATTR, - attr.span, - "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes", - "use", - "#[rustfmt::skip]".to_string(), - Applicability::MachineApplicable, - ); + // check for `rustfmt` + if feature_item.has_name(sym::rustfmt) + && msrv.meets(msrvs::TOOL_ATTRIBUTES) + // check for `rustfmt_skip` and `rustfmt::skip` + && let Some(skip_item) = &items[1].meta_item() + && (skip_item.has_name(sym!(rustfmt_skip)) + || skip_item + .path + .segments + .last() + .expect("empty path in attribute") + .ident + .name + == sym::skip) + // Only lint outer attributes, because custom inner attributes are unstable + // Tracking issue: https://github.com/rust-lang/rust/issues/54726 + && attr.style == AttrStyle::Outer + { + span_lint_and_sugg( + cx, + DEPRECATED_CFG_ATTR, + attr.span, + "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes", + "use", + "#[rustfmt::skip]".to_string(), + Applicability::MachineApplicable, + ); + } else { + check_deprecated_cfg_recursively(cx, feature_item); + if let Some(behind_cfg_attr) = items[1].meta_item() { + check_clippy_cfg_attr(cx, feature_item, behind_cfg_attr, attr); + } + } + } +} + +fn check_clippy_cfg_attr( + cx: &EarlyContext<'_>, + cfg_attr: &rustc_ast::MetaItem, + behind_cfg_attr: &rustc_ast::MetaItem, + attr: &Attribute, +) { + if cfg_attr.has_name(sym::clippy) + && let Some(ident) = behind_cfg_attr.ident() + && Level::from_symbol(ident.name, Some(attr.id)).is_some() + && let Some(items) = behind_cfg_attr.meta_item_list() + { + let nb_items = items.len(); + let mut clippy_lints = Vec::with_capacity(items.len()); + for item in items { + if let Some(meta_item) = item.meta_item() + && let [part1, _] = meta_item.path.segments.as_slice() + && part1.ident.name == sym::clippy + { + clippy_lints.push(item.span()); + } + } + if clippy_lints.is_empty() { + return; + } + if nb_items == clippy_lints.len() { + if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) { + span_lint_and_sugg( + cx, + UNNECESSARY_CLIPPY_CFG, + attr.span, + "no need to put clippy lints behind a `clippy` cfg", + "replace with", + format!( + "#{}[{}]", + if attr.style == AttrStyle::Inner { "!" } else { "" }, + snippet + ), + Applicability::MachineApplicable, + ); + } + } else { + let snippet = clippy_lints + .iter() + .filter_map(|sp| snippet_opt(cx, *sp)) + .collect::>() + .join(","); + span_lint_and_note( + cx, + UNNECESSARY_CLIPPY_CFG, + clippy_lints, + "no need to put clippy lints behind a `clippy` cfg", + None, + &format!( + "write instead: `#{}[{}({})]`", + if attr.style == AttrStyle::Inner { "!" } else { "" }, + ident.name, + snippet + ), + ); + } } } diff --git a/clippy_lints/src/blocks_in_conditions.rs b/clippy_lints/src/blocks_in_conditions.rs index ff4dffd06079f..2eb0dac974258 100644 --- a/clippy_lints/src/blocks_in_conditions.rs +++ b/clippy_lints/src/blocks_in_conditions.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_block_with_applicability; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::{for_each_expr, Descend}; -use clippy_utils::{get_parent_expr, higher}; +use clippy_utils::{get_parent_expr, higher, is_from_proc_macro}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource}; @@ -13,7 +13,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does - /// Checks for `if` conditions that use blocks containing an + /// Checks for `if` and `match` conditions that use blocks containing an /// expression, statements or conditions that use closures with blocks. /// /// ### Why is this bad? @@ -25,6 +25,11 @@ declare_clippy_lint! { /// if { true } { /* ... */ } /// /// if { let x = somefunc(); x } { /* ... */ } + /// + /// match { let e = somefunc(); e } { + /// // ... + /// # _ => {} + /// } /// ``` /// /// Use instead: @@ -34,6 +39,12 @@ declare_clippy_lint! { /// /// let res = { let x = somefunc(); x }; /// if res { /* ... */ } + /// + /// let res = { let e = somefunc(); e }; + /// match res { + /// // ... + /// # _ => {} + /// } /// ``` #[clippy::version = "1.45.0"] pub BLOCKS_IN_CONDITIONS, @@ -94,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { } } else { let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); - if span.from_expansion() || expr.span.from_expansion() { + if span.from_expansion() || expr.span.from_expansion() || is_from_proc_macro(cx, cond) { return; } // move block higher diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 2d1c250ace905..0d66f2d644d98 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -85,7 +85,117 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { ) { NonminimalBoolVisitor { cx }.visit_body(body); } + + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + match expr.kind { + ExprKind::Unary(UnOp::Not, sub) => check_inverted_condition(cx, expr.span, sub), + // This check the case where an element in a boolean comparison is inverted, like: + // + // ``` + // let a = true; + // !a == false; + // ``` + ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) => { + check_inverted_bool_in_condition(cx, expr.span, op.node, left, right); + }, + _ => {}, + } + } +} + +fn inverted_bin_op_eq_str(op: BinOpKind) -> Option<&'static str> { + match op { + BinOpKind::Eq => Some("!="), + BinOpKind::Ne => Some("=="), + _ => None, + } +} + +fn bin_op_eq_str(op: BinOpKind) -> Option<&'static str> { + match op { + BinOpKind::Eq => Some("=="), + BinOpKind::Ne => Some("!="), + _ => None, + } +} + +fn check_inverted_condition(cx: &LateContext<'_>, expr_span: Span, sub_expr: &Expr<'_>) { + if !expr_span.from_expansion() + && let ExprKind::Binary(op, left, right) = sub_expr.kind + && let Some(left) = snippet_opt(cx, left.span) + && let Some(right) = snippet_opt(cx, right.span) + { + let Some(op) = inverted_bin_op_eq_str(op.node) else { + return; + }; + span_lint_and_sugg( + cx, + NONMINIMAL_BOOL, + expr_span, + "this boolean expression can be simplified", + "try", + format!("{left} {op} {right}",), + Applicability::MachineApplicable, + ); + } +} + +fn check_inverted_bool_in_condition( + cx: &LateContext<'_>, + expr_span: Span, + op: BinOpKind, + left: &Expr<'_>, + right: &Expr<'_>, +) { + if expr_span.from_expansion() + && (!cx.typeck_results().node_types()[left.hir_id].is_bool() + || !cx.typeck_results().node_types()[right.hir_id].is_bool()) + { + return; + } + + let suggestion = match (left.kind, right.kind) { + (ExprKind::Unary(UnOp::Not, left_sub), ExprKind::Unary(UnOp::Not, right_sub)) => { + let Some(left) = snippet_opt(cx, left_sub.span) else { + return; + }; + let Some(right) = snippet_opt(cx, right_sub.span) else { + return; + }; + let Some(op) = bin_op_eq_str(op) else { return }; + format!("{left} {op} {right}") + }, + (ExprKind::Unary(UnOp::Not, left_sub), _) => { + let Some(left) = snippet_opt(cx, left_sub.span) else { + return; + }; + let Some(right) = snippet_opt(cx, right.span) else { + return; + }; + let Some(op) = inverted_bin_op_eq_str(op) else { return }; + format!("{left} {op} {right}") + }, + (_, ExprKind::Unary(UnOp::Not, right_sub)) => { + let Some(left) = snippet_opt(cx, left.span) else { return }; + let Some(right) = snippet_opt(cx, right_sub.span) else { + return; + }; + let Some(op) = inverted_bin_op_eq_str(op) else { return }; + format!("{left} {op} {right}") + }, + _ => return, + }; + span_lint_and_sugg( + cx, + NONMINIMAL_BOOL, + expr_span, + "this boolean expression can be simplified", + "try", + suggestion, + Applicability::MachineApplicable, + ); } + struct NonminimalBoolVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, } diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index ef12fe344e409..779ae03c4640b 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -1,11 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::macro_backtrace; +use clippy_utils::source::snippet_opt; use clippy_utils::ty::expr_sig; -use clippy_utils::{get_parent_node, is_default_equivalent, path_def_id}; +use clippy_utils::{is_default_equivalent, path_def_id}; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_ty, Visitor}; -use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, TyKind}; +use rustc_hir::{Block, Expr, ExprKind, Local, Node, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::print::with_forced_trimmed_paths; @@ -41,13 +42,24 @@ declare_lint_pass!(BoxDefault => [BOX_DEFAULT]); impl LateLintPass<'_> for BoxDefault { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + // If the expression is a call (`Box::new(...)`) if let ExprKind::Call(box_new, [arg]) = expr.kind + // And call is of the form `::something` + // Here, it would be `::new` && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_new.kind - && let ExprKind::Call(arg_path, ..) = arg.kind - && !in_external_macro(cx.sess(), expr.span) - && (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr)) + // And that method is `new` && seg.ident.name == sym::new + // And the call is that of a `Box` method && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box()) + // And the single argument to the call is another function call + // This is the `T::default()` of `Box::new(T::default())` + && let ExprKind::Call(arg_path, inner_call_args) = arg.kind + // And we are not in a foreign crate's macro + && !in_external_macro(cx.sess(), expr.span) + // And the argument expression has the same context as the outer call expression + // or that we are inside a `vec!` macro expansion + && (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr)) + // And the argument is equivalent to `Default::default()` && is_default_equivalent(cx, arg) { span_lint_and_sugg( @@ -59,7 +71,17 @@ impl LateLintPass<'_> for BoxDefault { if is_plain_default(cx, arg_path) || given_type(cx, expr) { "Box::default()".into() } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) { - with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) + // Check if we can copy from the source expression in the replacement. + // We need the call to have no argument (see `explicit_default_type`). + if inner_call_args.is_empty() + && let Some(ty) = explicit_default_type(arg_path) + && let Some(s) = snippet_opt(cx, ty.span) + { + format!("Box::<{s}>::default()") + } else { + // Otherwise, use the inferred type's formatting. + with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) + } } else { return; }, @@ -81,6 +103,20 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool { } } +// Checks whether the call is of the form `A::B::f()`. Returns `A::B` if it is. +// +// In the event we have this kind of construct, it's easy to use `A::B` as a replacement in the +// quickfix. `f` must however have no parameter. Should `f` have some, then some of the type of +// `A::B` may be inferred from the arguments. This would be the case for `Vec::from([0; false])`, +// where the argument to `from` allows inferring this is a `Vec` +fn explicit_default_type<'a>(arg_path: &'a Expr<'_>) -> Option<&'a Ty<'a>> { + if let ExprKind::Path(QPath::TypeRelative(ty, _)) = &arg_path.kind { + Some(ty) + } else { + None + } +} + fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool { macro_backtrace(expr.span).next().map_or(false, |call| { cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span) @@ -100,26 +136,23 @@ impl<'tcx> Visitor<'tcx> for InferVisitor { } fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - match get_parent_node(cx.tcx, expr.hir_id) { - Some(Node::Local(Local { ty: Some(ty), .. })) => { + match cx.tcx.parent_hir_node(expr.hir_id) { + Node::Local(Local { ty: Some(ty), .. }) => { let mut v = InferVisitor::default(); v.visit_ty(ty); !v.0 }, - Some( - Node::Expr(Expr { + Node::Expr(Expr { + kind: ExprKind::Call(path, args), + .. + }) + | Node::Block(Block { + expr: Some(Expr { kind: ExprKind::Call(path, args), .. - }) - | Node::Block(Block { - expr: - Some(Expr { - kind: ExprKind::Call(path, args), - .. - }), - .. }), - ) => { + .. + }) => { if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) && let Some(sig) = expr_sig(cx, path) && let Some(input) = sig.input(index) diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 1543ae8039968..ab89bb2f5f159 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -131,8 +131,7 @@ pub(super) fn check( let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),)); let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) { - (false, false) if from_nbits > to_nbits => "", - (true, false) if from_nbits > to_nbits => "", + (_, false) if from_nbits > to_nbits => "", (false, true) if from_nbits > 64 => "", (false, true) if from_nbits > 32 => " on targets with 32-bit wide pointers", _ => return, diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 1df5a25f674d7..8fd95d9654cf0 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,15 +1,47 @@ +use std::convert::Infallible; +use std::ops::ControlFlow; + use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::{clip, method_chain_args, sext}; +use clippy_utils::visitors::{for_each_expr, Descend}; +use clippy_utils::{method_chain_args, sext}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty, UintTy}; +use rustc_middle::ty::{self, Ty}; use super::CAST_SIGN_LOSS; -const METHODS_RET_POSITIVE: &[&str] = &["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"]; +/// A list of methods that can never return a negative value. +/// Includes methods that panic rather than returning a negative value. +/// +/// Methods that can overflow and return a negative value must not be included in this list, +/// because casting their return values can still result in sign loss. +const METHODS_RET_POSITIVE: &[&str] = &[ + "checked_abs", + "saturating_abs", + "isqrt", + "checked_isqrt", + "rem_euclid", + "checked_rem_euclid", + "wrapping_rem_euclid", +]; + +/// A list of methods that act like `pow()`. See `pow_call_result_sign()` for details. +/// +/// Methods that can overflow and return a negative value must not be included in this list, +/// because casting their return values can still result in sign loss. +const METHODS_POW: &[&str] = &["pow", "saturating_pow", "checked_pow"]; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) { +/// A list of methods that act like `unwrap()`, and don't change the sign of the inner value. +const METHODS_UNWRAP: &[&str] = &["unwrap", "unwrap_unchecked", "expect", "into_ok"]; + +pub(super) fn check<'cx>( + cx: &LateContext<'cx>, + expr: &Expr<'_>, + cast_op: &Expr<'_>, + cast_from: Ty<'cx>, + cast_to: Ty<'_>, +) { if should_lint(cx, cast_op, cast_from, cast_to) { span_lint( cx, @@ -20,35 +52,27 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, c } } -fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) -> bool { +fn should_lint<'cx>(cx: &LateContext<'cx>, cast_op: &Expr<'_>, cast_from: Ty<'cx>, cast_to: Ty<'_>) -> bool { match (cast_from.is_integral(), cast_to.is_integral()) { (true, true) => { if !cast_from.is_signed() || cast_to.is_signed() { return false; } - // Don't lint if `cast_op` is known to be positive. + // Don't lint if `cast_op` is known to be positive, ignoring overflow. if let Sign::ZeroOrPositive = expr_sign(cx, cast_op, cast_from) { return false; } - let (mut uncertain_count, mut negative_count) = (0, 0); - // Peel off possible binary expressions, e.g. x * x * y => [x, x, y] - let Some(exprs) = exprs_with_selected_binop_peeled(cast_op) else { - // Assume cast sign lose if we cannot determine the sign of `cast_op` - return true; - }; - for expr in exprs { - let ty = cx.typeck_results().expr_ty(expr); - match expr_sign(cx, expr, ty) { - Sign::Negative => negative_count += 1, - Sign::Uncertain => uncertain_count += 1, - Sign::ZeroOrPositive => (), - }; + if let Sign::ZeroOrPositive = expr_muldiv_sign(cx, cast_op) { + return false; + } + + if let Sign::ZeroOrPositive = expr_add_sign(cx, cast_op) { + return false; } - // Lint if there are odd number of uncertain or negative results - uncertain_count % 2 == 1 || negative_count % 2 == 1 + true }, (false, true) => !cast_to.is_signed(), @@ -57,7 +81,13 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast } } -fn get_const_int_eval(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Option { +fn get_const_signed_int_eval<'cx>( + cx: &LateContext<'cx>, + expr: &Expr<'_>, + ty: impl Into>>, +) -> Option { + let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr)); + if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)? && let ty::Int(ity) = *ty.kind() { @@ -66,29 +96,52 @@ fn get_const_int_eval(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Opti None } +fn get_const_unsigned_int_eval<'cx>( + cx: &LateContext<'cx>, + expr: &Expr<'_>, + ty: impl Into>>, +) -> Option { + let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr)); + + if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)? + && let ty::Uint(_ity) = *ty.kind() + { + return Some(n); + } + None +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] enum Sign { ZeroOrPositive, Negative, Uncertain, } -fn expr_sign(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Sign { +fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into>>) -> Sign { // Try evaluate this expr first to see if it's positive - if let Some(val) = get_const_int_eval(cx, expr, ty) { + if let Some(val) = get_const_signed_int_eval(cx, expr, ty) { return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative }; } + if let Some(_val) = get_const_unsigned_int_eval(cx, expr, None) { + return Sign::ZeroOrPositive; + } + // Calling on methods that always return non-negative values. if let ExprKind::MethodCall(path, caller, args, ..) = expr.kind { let mut method_name = path.ident.name.as_str(); - if method_name == "unwrap" - && let Some(arglist) = method_chain_args(expr, &["unwrap"]) + // Peel unwrap(), expect(), etc. + while let Some(&found_name) = METHODS_UNWRAP.iter().find(|&name| &method_name == name) + && let Some(arglist) = method_chain_args(expr, &[found_name]) && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind { + // The original type has changed, but we can't use `ty` here anyway, because it has been + // moved. method_name = inner_path.ident.name.as_str(); } - if method_name == "pow" + if METHODS_POW.iter().any(|&name| method_name == name) && let [arg] = args { return pow_call_result_sign(cx, caller, arg); @@ -100,53 +153,182 @@ fn expr_sign(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Sign { Sign::Uncertain } -/// Return the sign of the `pow` call's result. +/// Return the sign of the `pow` call's result, ignoring overflow. /// -/// If the caller is a positive number, the result is always positive, -/// If the `power_of` is a even number, the result is always positive as well, -/// Otherwise a [`Sign::Uncertain`] will be returned. -fn pow_call_result_sign(cx: &LateContext<'_>, caller: &Expr<'_>, power_of: &Expr<'_>) -> Sign { - let caller_ty = cx.typeck_results().expr_ty(caller); - if let Some(caller_val) = get_const_int_eval(cx, caller, caller_ty) - && caller_val >= 0 - { - return Sign::ZeroOrPositive; +/// If the base is positive, the result is always positive. +/// If the exponent is a even number, the result is always positive, +/// Otherwise, if the base is negative, and the exponent is an odd number, the result is always +/// negative. +/// +/// Otherwise, returns [`Sign::Uncertain`]. +fn pow_call_result_sign(cx: &LateContext<'_>, base: &Expr<'_>, exponent: &Expr<'_>) -> Sign { + let base_sign = expr_sign(cx, base, None); + + // Rust's integer pow() functions take an unsigned exponent. + let exponent_val = get_const_unsigned_int_eval(cx, exponent, None); + let exponent_is_even = exponent_val.map(|val| val % 2 == 0); + + match (base_sign, exponent_is_even) { + // Non-negative bases always return non-negative results, ignoring overflow. + (Sign::ZeroOrPositive, _) | + // Any base raised to an even exponent is non-negative. + // These both hold even if we don't know the value of the base. + (_, Some(true)) + => Sign::ZeroOrPositive, + + // A negative base raised to an odd exponent is non-negative. + (Sign::Negative, Some(false)) => Sign::Negative, + + // Negative/unknown base to an unknown exponent, or unknown base to an odd exponent. + // Could be negative or positive depending on the actual values. + (Sign::Negative | Sign::Uncertain, None) | + (Sign::Uncertain, Some(false)) => Sign::Uncertain, } +} - if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), power_of) - && clip(cx.tcx, n, UintTy::U32) % 2 == 0 - { - return Sign::ZeroOrPositive; +/// Peels binary operators such as [`BinOpKind::Mul`] or [`BinOpKind::Rem`], +/// where the result could always be positive. See [`exprs_with_muldiv_binop_peeled()`] for details. +/// +/// Returns the sign of the list of peeled expressions. +fn expr_muldiv_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign { + let mut negative_count = 0; + + // Peel off possible binary expressions, for example: + // x * x / y => [x, x, y] + // a % b => [a] + let exprs = exprs_with_muldiv_binop_peeled(expr); + for expr in exprs { + match expr_sign(cx, expr, None) { + Sign::Negative => negative_count += 1, + // A mul/div is: + // - uncertain if there are any uncertain values (because they could be negative or positive), + Sign::Uncertain => return Sign::Uncertain, + Sign::ZeroOrPositive => (), + }; } - Sign::Uncertain + // A mul/div is: + // - negative if there are an odd number of negative values, + // - positive or zero otherwise. + if negative_count % 2 == 1 { + Sign::Negative + } else { + Sign::ZeroOrPositive + } +} + +/// Peels binary operators such as [`BinOpKind::Add`], where the result could always be positive. +/// See [`exprs_with_add_binop_peeled()`] for details. +/// +/// Returns the sign of the list of peeled expressions. +fn expr_add_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign { + let mut negative_count = 0; + let mut positive_count = 0; + + // Peel off possible binary expressions, for example: + // a + b + c => [a, b, c] + let exprs = exprs_with_add_binop_peeled(expr); + for expr in exprs { + match expr_sign(cx, expr, None) { + Sign::Negative => negative_count += 1, + // A sum is: + // - uncertain if there are any uncertain values (because they could be negative or positive), + Sign::Uncertain => return Sign::Uncertain, + Sign::ZeroOrPositive => positive_count += 1, + }; + } + + // A sum is: + // - positive or zero if there are only positive (or zero) values, + // - negative if there are only negative (or zero) values, or + // - uncertain if there are both. + // We could split Zero out into its own variant, but we don't yet. + if negative_count == 0 { + Sign::ZeroOrPositive + } else if positive_count == 0 { + Sign::Negative + } else { + Sign::Uncertain + } } /// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`], -/// which the result could always be positive under certain condition. +/// where the result depends on: +/// - the number of negative values in the entire expression, or +/// - the number of negative values on the left hand side of the expression. +/// Ignores overflow. /// -/// Other operators such as `+`/`-` causing the result's sign hard to determine, which we will -/// return `None` -fn exprs_with_selected_binop_peeled<'a>(expr: &'a Expr<'_>) -> Option>> { - #[inline] - fn collect_operands<'a>(expr: &'a Expr<'a>, operands: &mut Vec<&'a Expr<'a>>) -> Option<()> { - match expr.kind { - ExprKind::Binary(op, lhs, rhs) => { - if matches!(op.node, BinOpKind::Mul | BinOpKind::Div | BinOpKind::Rem) { - collect_operands(lhs, operands); - operands.push(rhs); - } else { - // Things are complicated when there are other binary ops exist, - // abort checking by returning `None` for now. - return None; - } - }, - _ => operands.push(expr), +/// +/// Expressions using other operators are preserved, so we can try to evaluate them later. +fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> { + let mut res = vec![]; + + for_each_expr(expr, |sub_expr| -> ControlFlow { + // We don't check for mul/div/rem methods here, but we could. + if let ExprKind::Binary(op, lhs, _rhs) = sub_expr.kind { + if matches!(op.node, BinOpKind::Mul | BinOpKind::Div) { + // For binary operators where both sides contribute to the sign of the result, + // collect all their operands, recursively. This ignores overflow. + ControlFlow::Continue(Descend::Yes) + } else if matches!(op.node, BinOpKind::Rem | BinOpKind::Shr) { + // For binary operators where the left hand side determines the sign of the result, + // only collect that side, recursively. Overflow panics, so this always holds. + // + // Large left shifts turn negatives into zeroes, so we can't use it here. + // + // > Given remainder = dividend % divisor, the remainder will have the same sign as the dividend + // > ... + // > Arithmetic right shift on signed integer types + // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators + + // We want to descend into the lhs, but skip the rhs. + // That's tricky to do using for_each_expr(), so we just keep the lhs intact. + res.push(lhs); + ControlFlow::Continue(Descend::No) + } else { + // The sign of the result of other binary operators depends on the values of the operands, + // so try to evaluate the expression. + res.push(sub_expr); + ControlFlow::Continue(Descend::No) + } + } else { + // For other expressions, including unary operators and constants, try to evaluate the expression. + res.push(sub_expr); + ControlFlow::Continue(Descend::No) } - Some(()) - } + }); + res +} + +/// Peels binary operators such as [`BinOpKind::Add`], where the result depends on: +/// - all the expressions being positive, or +/// - all the expressions being negative. +/// Ignores overflow. +/// +/// Expressions using other operators are preserved, so we can try to evaluate them later. +fn exprs_with_add_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> { let mut res = vec![]; - collect_operands(expr, &mut res)?; - Some(res) + + for_each_expr(expr, |sub_expr| -> ControlFlow { + // We don't check for add methods here, but we could. + if let ExprKind::Binary(op, _lhs, _rhs) = sub_expr.kind { + if matches!(op.node, BinOpKind::Add) { + // For binary operators where both sides contribute to the sign of the result, + // collect all their operands, recursively. This ignores overflow. + ControlFlow::Continue(Descend::Yes) + } else { + // The sign of the result of other binary operators depends on the values of the operands, + // so try to evaluate the expression. + res.push(sub_expr); + ControlFlow::Continue(Descend::No) + } + } else { + // For other expressions, including unary operators and constants, try to evaluate the expression. + res.push(sub_expr); + ControlFlow::Continue(Descend::No) + } + }); + + res } diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs index d600d2aec1b5e..9d5a486336d5f 100644 --- a/clippy_lints/src/casts/ref_as_ptr.rs +++ b/clippy_lints/src/casts/ref_as_ptr.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_no_std_crate; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; +use clippy_utils::{expr_use_ctxt, is_no_std_crate, ExprUseNode}; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability, Ty, TyKind}; use rustc_lint::LateContext; @@ -9,7 +9,12 @@ use rustc_middle::ty::{self, TypeAndMut}; use super::REF_AS_PTR; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_hir_ty: &Ty<'_>) { +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + cast_expr: &'tcx Expr<'_>, + cast_to_hir_ty: &Ty<'_>, +) { let (cast_from, cast_to) = ( cx.typeck_results().expr_ty(cast_expr), cx.typeck_results().expr_ty(expr), @@ -17,6 +22,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, if matches!(cast_from.kind(), ty::Ref(..)) && let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind() + && let Some(use_cx) = expr_use_ctxt(cx, expr) + // TODO: only block the lint if `cast_expr` is a temporary + && !matches!(use_cx.node, ExprUseNode::Local(_) | ExprUseNode::ConstStatic(_)) { let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" }; let fn_name = match to_mutbl { diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index b4a23d0d4db41..cc513d46bf4ec 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::numeric_literal::NumericLiteral; use clippy_utils::source::snippet_opt; use clippy_utils::visitors::{for_each_expr, Visitable}; -use clippy_utils::{get_parent_expr, get_parent_node, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; +use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local}; use rustc_ast::{LitFloatType, LitIntType, LitKind}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -264,8 +264,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx } // Local usage } else if let Res::Local(hir_id) = res - && let Some(parent) = get_parent_node(cx.tcx, hir_id) - && let Node::Local(l) = parent + && let Node::Local(l) = cx.tcx.parent_hir_node(hir_id) { if let Some(e) = l.init && is_cast_from_ty_alias(cx, e, cast_from) diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index d0c989cfff304..d820413e11129 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::for_each_expr_with_closures; -use clippy_utils::{get_enclosing_block, get_parent_node, path_to_local_id}; +use clippy_utils::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; use rustc_hir::{Block, ExprKind, HirId, LangItem, Local, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -94,7 +94,7 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc // `id` appearing in the left-hand side of an assignment is not a read access: // // id = ...; // Not reading `id`. - if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id) + if let Node::Expr(parent) = cx.tcx.parent_hir_node(expr.hir_id) && let ExprKind::Assign(lhs, ..) = parent.kind && path_to_local_id(lhs, id) { @@ -108,7 +108,7 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc // Only assuming this for "official" methods defined on the type. For methods defined in extension // traits (identified as local, based on the orphan rule), pessimistically assume that they might // have side effects, so consider them a read. - if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id) + if let Node::Expr(parent) = cx.tcx.parent_hir_node(expr.hir_id) && let ExprKind::MethodCall(_, receiver, _, _) = parent.kind && path_to_local_id(receiver, id) && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id) @@ -117,7 +117,7 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc // The method call is a statement, so the return value is not used. That's not a read access: // // id.foo(args); - if let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id) { + if let Node::Stmt(..) = cx.tcx.parent_hir_node(parent.hir_id) { return ControlFlow::Continue(()); } diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 0a5baabd973ea..fb3ae2457e3c4 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -51,6 +51,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO, crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO, crate::attrs::DEPRECATED_CFG_ATTR_INFO, + crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO, crate::attrs::DEPRECATED_SEMVER_INFO, crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO, crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO, @@ -59,6 +60,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::attrs::MISMATCHED_TARGET_OS_INFO, crate::attrs::NON_MINIMAL_CFG_INFO, crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO, + crate::attrs::UNNECESSARY_CLIPPY_CFG_INFO, crate::attrs::USELESS_ATTRIBUTE_INFO, crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO, crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO, @@ -137,6 +139,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_types::DISALLOWED_TYPES_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, crate::doc::DOC_MARKDOWN_INFO, + crate::doc::EMPTY_DOCS_INFO, crate::doc::MISSING_ERRORS_DOC_INFO, crate::doc::MISSING_PANICS_DOC_INFO, crate::doc::MISSING_SAFETY_DOC_INFO, @@ -453,6 +456,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_FILTER_MAP_INFO, crate::methods::UNNECESSARY_FIND_MAP_INFO, crate::methods::UNNECESSARY_FOLD_INFO, + crate::methods::UNNECESSARY_GET_THEN_CHECK_INFO, crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, @@ -497,6 +501,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::module_style::MOD_MODULE_FILES_INFO, crate::module_style::SELF_NAMED_MODULE_FILES_INFO, crate::multi_assignments::MULTI_ASSIGNMENTS_INFO, + crate::multiple_bound_locations::MULTIPLE_BOUND_LOCATIONS_INFO, crate::multiple_unsafe_ops_per_block::MULTIPLE_UNSAFE_OPS_PER_BLOCK_INFO, crate::mut_key::MUTABLE_KEY_TYPE_INFO, crate::mut_mut::MUT_MUT_INFO, diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 0ddfeaa0ae059..560b2acc1c702 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -2,9 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs}; -use clippy_utils::{ - expr_use_ctxt, get_parent_expr, get_parent_node, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode, -}; +use clippy_utils::{expr_use_ctxt, get_parent_expr, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode}; use core::mem; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; @@ -1008,8 +1006,8 @@ fn report<'tcx>( data.first_expr.span, state.msg, |diag| { - let (precedence, calls_field) = match get_parent_node(cx.tcx, data.first_expr.hir_id) { - Some(Node::Expr(e)) => match e.kind { + let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { + Node::Expr(e) => match e.kind { ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false), ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))), _ => (e.precedence().order(), false), diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index 656b3d9bfaf1b..75379cb4e5458 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -1,13 +1,16 @@ use clippy_config::types::DisallowedPath; -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashSet; +use rustc_errors::DiagnosticBuilder; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty}; +use rustc_hir::{ + Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty, +}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::{ExpnId, Span}; +use rustc_span::{ExpnId, MacroKind, Span}; declare_clippy_lint! { /// ### What it does @@ -57,6 +60,10 @@ pub struct DisallowedMacros { conf_disallowed: Vec, disallowed: DefIdMap, seen: FxHashSet, + + // Track the most recently seen node that can have a `derive` attribute. + // Needed to use the correct lint level. + derive_src: Option, } impl DisallowedMacros { @@ -65,10 +72,11 @@ impl DisallowedMacros { conf_disallowed, disallowed: DefIdMap::default(), seen: FxHashSet::default(), + derive_src: None, } } - fn check(&mut self, cx: &LateContext<'_>, span: Span) { + fn check(&mut self, cx: &LateContext<'_>, span: Span, derive_src: Option) { if self.conf_disallowed.is_empty() { return; } @@ -80,18 +88,26 @@ impl DisallowedMacros { if let Some(&index) = self.disallowed.get(&mac.def_id) { let conf = &self.conf_disallowed[index]; - - span_lint_and_then( - cx, - DISALLOWED_MACROS, - mac.span, - &format!("use of a disallowed macro `{}`", conf.path()), - |diag| { - if let Some(reason) = conf.reason() { - diag.note(reason); - } - }, - ); + let msg = format!("use of a disallowed macro `{}`", conf.path()); + let add_note = |diag: &mut DiagnosticBuilder<'_, _>| { + if let Some(reason) = conf.reason() { + diag.note(reason); + } + }; + if matches!(mac.kind, MacroKind::Derive) + && let Some(derive_src) = derive_src + { + span_lint_hir_and_then( + cx, + DISALLOWED_MACROS, + cx.tcx.local_def_id_to_hir_id(derive_src.def_id), + mac.span, + &msg, + add_note, + ); + } else { + span_lint_and_then(cx, DISALLOWED_MACROS, mac.span, &msg, add_note); + } } } } @@ -110,49 +126,57 @@ impl LateLintPass<'_> for DisallowedMacros { } fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - self.check(cx, expr.span); + self.check(cx, expr.span, None); // `$t + $t` can have the context of $t, check also the span of the binary operator if let ExprKind::Binary(op, ..) = expr.kind { - self.check(cx, op.span); + self.check(cx, op.span, None); } } fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) { - self.check(cx, stmt.span); + self.check(cx, stmt.span, None); } fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_>) { - self.check(cx, ty.span); + self.check(cx, ty.span, None); } fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { - self.check(cx, pat.span); + self.check(cx, pat.span, None); } fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - self.check(cx, item.span); - self.check(cx, item.vis_span); + self.check(cx, item.span, self.derive_src); + self.check(cx, item.vis_span, None); + + if matches!( + item.kind, + ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..) + ) && macro_backtrace(item.span).all(|m| !matches!(m.kind, MacroKind::Derive)) + { + self.derive_src = Some(item.owner_id); + } } fn check_foreign_item(&mut self, cx: &LateContext<'_>, item: &ForeignItem<'_>) { - self.check(cx, item.span); - self.check(cx, item.vis_span); + self.check(cx, item.span, None); + self.check(cx, item.vis_span, None); } fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &ImplItem<'_>) { - self.check(cx, item.span); - self.check(cx, item.vis_span); + self.check(cx, item.span, None); + self.check(cx, item.vis_span, None); } fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { - self.check(cx, item.span); + self.check(cx, item.span, None); } fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, _: HirId) { - self.check(cx, path.span); + self.check(cx, path.span, None); } fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &Attribute) { - self.check(cx, attr.span); + self.check(cx, attr.span, self.derive_src); } } diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 2b4ce6ddfaaa3..9af34c3a7bf0b 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -19,7 +19,8 @@ use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_resolve::rustdoc::{ - add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, DocFragment, + add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, span_of_fragments, + DocFragment, }; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition; @@ -338,6 +339,30 @@ declare_clippy_lint! { "suspicious usage of (outer) doc comments" } +declare_clippy_lint! { + /// ### What it does + /// Detects documentation that is empty. + /// ### Why is this bad? + /// Empty docs clutter code without adding value, reducing readability and maintainability. + /// ### Example + /// ```no_run + /// /// + /// fn returns_true() -> bool { + /// true + /// } + /// ``` + /// Use instead: + /// ```no_run + /// fn returns_true() -> bool { + /// true + /// } + /// ``` + #[clippy::version = "1.78.0"] + pub EMPTY_DOCS, + suspicious, + "docstrings exist but documentation is empty" +} + #[derive(Clone)] pub struct Documentation { valid_idents: FxHashSet, @@ -364,7 +389,8 @@ impl_lint_pass!(Documentation => [ NEEDLESS_DOCTEST_MAIN, TEST_ATTR_IN_DOCTEST, UNNECESSARY_SAFETY_DOC, - SUSPICIOUS_DOC_COMMENTS + SUSPICIOUS_DOC_COMMENTS, + EMPTY_DOCS, ]); impl<'tcx> LateLintPass<'tcx> for Documentation { @@ -373,11 +399,22 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { check_attrs(cx, &self.valid_idents, attrs); } + fn check_variant(&mut self, cx: &LateContext<'tcx>, variant: &'tcx hir::Variant<'tcx>) { + let attrs = cx.tcx.hir().attrs(variant.hir_id); + check_attrs(cx, &self.valid_idents, attrs); + } + + fn check_field_def(&mut self, cx: &LateContext<'tcx>, variant: &'tcx hir::FieldDef<'tcx>) { + let attrs = cx.tcx.hir().attrs(variant.hir_id); + check_attrs(cx, &self.valid_idents, attrs); + } + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir().attrs(item.hir_id()); let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return; }; + match item.kind { hir::ItemKind::Fn(ref sig, _, body_id) => { if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { @@ -502,13 +539,23 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ suspicious_doc_comments::check(cx, attrs); let (fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true); - let mut doc = String::new(); - for fragment in &fragments { - add_doc_fragment(&mut doc, fragment); - } + let mut doc = fragments.iter().fold(String::new(), |mut acc, fragment| { + add_doc_fragment(&mut acc, fragment); + acc + }); doc.pop(); - if doc.is_empty() { + if doc.trim().is_empty() { + if let Some(span) = span_of_fragments(&fragments) { + span_lint_and_help( + cx, + EMPTY_DOCS, + span, + "empty doc comment", + None, + "consider removing or filling it", + ); + } return Some(DocHeaders::default()); } diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 124d78fc4ffdc..bf6f54c1e72a3 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::is_must_use_func_call; use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item}; -use clippy_utils::{get_parent_node, is_must_use_func_call}; use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -144,8 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { // } fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool { if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) { - let parent_node = get_parent_node(cx.tcx, drop_expr.hir_id); - if let Some(Node::Arm(Arm { body, .. })) = &parent_node { + if let Node::Arm(Arm { body, .. }) = cx.tcx.parent_hir_node(drop_expr.hir_id) { return body.hir_id == drop_expr.hir_id; } } diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 8af321e4d553b..61f550ce0beb4 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -4,7 +4,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_diag_trait_item; use clippy_utils::macros::{ find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, - is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage, + is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage, MacroCall, }; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; @@ -20,7 +20,6 @@ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_middle::ty::Ty; use rustc_session::impl_lint_pass; -use rustc_span::def_id::DefId; use rustc_span::edition::Edition::Edition2021; use rustc_span::{sym, Span, Symbol}; @@ -189,32 +188,18 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { && is_format_macro(cx, macro_call.def_id) && let Some(format_args) = find_format_args(cx, expr, macro_call.expn) { - for piece in &format_args.template { - if let FormatArgsPiece::Placeholder(placeholder) = piece - && let Ok(index) = placeholder.argument.index - && let Some(arg) = format_args.arguments.all_args().get(index) - { - let arg_expr = find_format_arg_expr(expr, arg); - - check_unused_format_specifier(cx, placeholder, arg_expr); - - if placeholder.format_trait != FormatTrait::Display - || placeholder.format_options != FormatOptions::default() - || is_aliased(&format_args, index) - { - continue; - } + let linter = FormatArgsExpr { + cx, + expr, + macro_call: ¯o_call, + format_args: &format_args, + ignore_mixed: self.ignore_mixed, + }; - if let Ok(arg_hir_expr) = arg_expr { - let name = cx.tcx.item_name(macro_call.def_id); - check_format_in_format_args(cx, macro_call.span, name, arg_hir_expr); - check_to_string_in_format_args(cx, name, arg_hir_expr); - } - } - } + linter.check_templates(); if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) { - check_uninlined_args(cx, &format_args, macro_call.span, macro_call.def_id, self.ignore_mixed); + linter.check_uninlined_args(); } } } @@ -222,255 +207,279 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { extract_msrv_attr!(LateContext); } -fn check_unused_format_specifier( - cx: &LateContext<'_>, - placeholder: &FormatPlaceholder, - arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>, -) { - let ty_or_ast_expr = arg_expr.map(|expr| cx.typeck_results().expr_ty(expr).peel_refs()); - - let is_format_args = match ty_or_ast_expr { - Ok(ty) => is_type_lang_item(cx, ty, LangItem::FormatArguments), - Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)), - }; - - let options = &placeholder.format_options; - - let arg_span = match arg_expr { - Ok(expr) => expr.span, - Err(expr) => expr.span, - }; - - if let Some(placeholder_span) = placeholder.span - && is_format_args - && *options != FormatOptions::default() - { - span_lint_and_then( - cx, - UNUSED_FORMAT_SPECS, - placeholder_span, - "format specifiers have no effect on `format_args!()`", - |diag| { - let mut suggest_format = |spec| { - let message = format!("for the {spec} to apply consider using `format!()`"); - - if let Some(mac_call) = root_macro_call(arg_span) - && cx.tcx.is_diagnostic_item(sym::format_args_macro, mac_call.def_id) - { - diag.span_suggestion( - cx.sess().source_map().span_until_char(mac_call.span, '!'), - message, - "format", - Applicability::MaybeIncorrect, - ); - } else { - diag.help(message); - } - }; +struct FormatArgsExpr<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + macro_call: &'a MacroCall, + format_args: &'a rustc_ast::FormatArgs, + ignore_mixed: bool, +} - if options.width.is_some() { - suggest_format("width"); +impl<'a, 'tcx> FormatArgsExpr<'a, 'tcx> { + fn check_templates(&self) { + for piece in &self.format_args.template { + if let FormatArgsPiece::Placeholder(placeholder) = piece + && let Ok(index) = placeholder.argument.index + && let Some(arg) = self.format_args.arguments.all_args().get(index) + { + let arg_expr = find_format_arg_expr(self.expr, arg); + + self.check_unused_format_specifier(placeholder, arg_expr); + + if let Ok(arg_expr) = arg_expr + && placeholder.format_trait == FormatTrait::Display + && placeholder.format_options == FormatOptions::default() + && !self.is_aliased(index) + { + let name = self.cx.tcx.item_name(self.macro_call.def_id); + self.check_format_in_format_args(name, arg_expr); + self.check_to_string_in_format_args(name, arg_expr); } + } + } + } - if options.precision.is_some() { - suggest_format("precision"); - } + fn check_unused_format_specifier( + &self, + placeholder: &FormatPlaceholder, + arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>, + ) { + let ty_or_ast_expr = arg_expr.map(|expr| self.cx.typeck_results().expr_ty(expr).peel_refs()); - if let Some(format_span) = format_placeholder_format_span(placeholder) { - diag.span_suggestion_verbose( - format_span, - "if the current behavior is intentional, remove the format specifiers", - "", - Applicability::MaybeIncorrect, - ); - } - }, - ); - } -} + let is_format_args = match ty_or_ast_expr { + Ok(ty) => is_type_lang_item(self.cx, ty, LangItem::FormatArguments), + Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)), + }; -fn check_uninlined_args( - cx: &LateContext<'_>, - args: &rustc_ast::FormatArgs, - call_site: Span, - def_id: DefId, - ignore_mixed: bool, -) { - if args.span.from_expansion() { - return; - } - if call_site.edition() < Edition2021 && (is_panic(cx, def_id) || is_assert_macro(cx, def_id)) { - // panic!, assert!, and debug_assert! before 2021 edition considers a single string argument as - // non-format - return; + let options = &placeholder.format_options; + + let arg_span = match arg_expr { + Ok(expr) => expr.span, + Err(expr) => expr.span, + }; + + if let Some(placeholder_span) = placeholder.span + && is_format_args + && *options != FormatOptions::default() + { + span_lint_and_then( + self.cx, + UNUSED_FORMAT_SPECS, + placeholder_span, + "format specifiers have no effect on `format_args!()`", + |diag| { + let mut suggest_format = |spec| { + let message = format!("for the {spec} to apply consider using `format!()`"); + + if let Some(mac_call) = root_macro_call(arg_span) + && self.cx.tcx.is_diagnostic_item(sym::format_args_macro, mac_call.def_id) + { + diag.span_suggestion( + self.cx.sess().source_map().span_until_char(mac_call.span, '!'), + message, + "format", + Applicability::MaybeIncorrect, + ); + } else { + diag.help(message); + } + }; + + if options.width.is_some() { + suggest_format("width"); + } + + if options.precision.is_some() { + suggest_format("precision"); + } + + if let Some(format_span) = format_placeholder_format_span(placeholder) { + diag.span_suggestion_verbose( + format_span, + "if the current behavior is intentional, remove the format specifiers", + "", + Applicability::MaybeIncorrect, + ); + } + }, + ); + } } - let mut fixes = Vec::new(); - // If any of the arguments are referenced by an index number, - // and that argument is not a simple variable and cannot be inlined, - // we cannot remove any other arguments in the format string, - // because the index numbers might be wrong after inlining. - // Example of an un-inlinable format: print!("{}{1}", foo, 2) - for (pos, usage) in format_arg_positions(args) { - if !check_one_arg(args, pos, usage, &mut fixes, ignore_mixed) { + fn check_uninlined_args(&self) { + if self.format_args.span.from_expansion() { + return; + } + if self.macro_call.span.edition() < Edition2021 + && (is_panic(self.cx, self.macro_call.def_id) || is_assert_macro(self.cx, self.macro_call.def_id)) + { + // panic!, assert!, and debug_assert! before 2021 edition considers a single string argument as + // non-format return; } - } - if fixes.is_empty() { - return; - } + let mut fixes = Vec::new(); + // If any of the arguments are referenced by an index number, + // and that argument is not a simple variable and cannot be inlined, + // we cannot remove any other arguments in the format string, + // because the index numbers might be wrong after inlining. + // Example of an un-inlinable format: print!("{}{1}", foo, 2) + for (pos, usage) in self.format_arg_positions() { + if !self.check_one_arg(pos, usage, &mut fixes) { + return; + } + } - // multiline span display suggestion is sometimes broken: https://github.com/rust-lang/rust/pull/102729#discussion_r988704308 - // in those cases, make the code suggestion hidden - let multiline_fix = fixes.iter().any(|(span, _)| cx.sess().source_map().is_multiline(*span)); - - // Suggest removing each argument only once, for example in `format!("{0} {0}", arg)`. - fixes.sort_unstable_by_key(|(span, _)| *span); - fixes.dedup_by_key(|(span, _)| *span); - - span_lint_and_then( - cx, - UNINLINED_FORMAT_ARGS, - call_site, - "variables can be used directly in the `format!` string", - |diag| { - diag.multipart_suggestion_with_style( - "change this to", - fixes, - Applicability::MachineApplicable, - if multiline_fix { CompletelyHidden } else { ShowCode }, - ); - }, - ); -} + if fixes.is_empty() { + return; + } -fn check_one_arg( - args: &rustc_ast::FormatArgs, - pos: &FormatArgPosition, - usage: FormatParamUsage, - fixes: &mut Vec<(Span, String)>, - ignore_mixed: bool, -) -> bool { - let index = pos.index.unwrap(); - let arg = &args.arguments.all_args()[index]; - - if !matches!(arg.kind, FormatArgumentKind::Captured(_)) - && let rustc_ast::ExprKind::Path(None, path) = &arg.expr.kind - && let [segment] = path.segments.as_slice() - && segment.args.is_none() - && let Some(arg_span) = format_arg_removal_span(args, index) - && let Some(pos_span) = pos.span - { - let replacement = match usage { - FormatParamUsage::Argument => segment.ident.name.to_string(), - FormatParamUsage::Width => format!("{}$", segment.ident.name), - FormatParamUsage::Precision => format!(".{}$", segment.ident.name), - }; - fixes.push((pos_span, replacement)); - fixes.push((arg_span, String::new())); - true // successful inlining, continue checking - } else { - // Do not continue inlining (return false) in case - // * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)` - // * if allow_mixed_uninlined_format_args is false and this arg hasn't been inlined already - pos.kind != FormatArgPositionKind::Number - && (!ignore_mixed || matches!(arg.kind, FormatArgumentKind::Captured(_))) - } -} + // multiline span display suggestion is sometimes broken: https://github.com/rust-lang/rust/pull/102729#discussion_r988704308 + // in those cases, make the code suggestion hidden + let multiline_fix = fixes + .iter() + .any(|(span, _)| self.cx.sess().source_map().is_multiline(*span)); -fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symbol, arg: &Expr<'_>) { - let expn_data = arg.span.ctxt().outer_expn_data(); - if expn_data.call_site.from_expansion() { - return; - } - let Some(mac_id) = expn_data.macro_def_id else { return }; - if !cx.tcx.is_diagnostic_item(sym::format_macro, mac_id) { - return; + // Suggest removing each argument only once, for example in `format!("{0} {0}", arg)`. + fixes.sort_unstable_by_key(|(span, _)| *span); + fixes.dedup_by_key(|(span, _)| *span); + + span_lint_and_then( + self.cx, + UNINLINED_FORMAT_ARGS, + self.macro_call.span, + "variables can be used directly in the `format!` string", + |diag| { + diag.multipart_suggestion_with_style( + "change this to", + fixes, + Applicability::MachineApplicable, + if multiline_fix { CompletelyHidden } else { ShowCode }, + ); + }, + ); } - span_lint_and_then( - cx, - FORMAT_IN_FORMAT_ARGS, - call_site, - &format!("`format!` in `{name}!` args"), - |diag| { - diag.help(format!( - "combine the `format!(..)` arguments with the outer `{name}!(..)` call" - )); - diag.help("or consider changing `format!` to `format_args!`"); - }, - ); -} -fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) { - if !value.span.from_expansion() - && let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind - && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id) - && is_diag_trait_item(cx, method_def_id, sym::ToString) - && let receiver_ty = cx.typeck_results().expr_ty(receiver) - && let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display) - && let (n_needed_derefs, target) = - count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter()) - && implements_trait(cx, target, display_trait_id, &[]) - && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait() - && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) - { - let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]); - if n_needed_derefs == 0 && !needs_ref { - span_lint_and_sugg( - cx, - TO_STRING_IN_FORMAT_ARGS, - to_string_span.with_lo(receiver.span.hi()), - &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), - "remove this", - String::new(), - Applicability::MachineApplicable, - ); + fn check_one_arg(&self, pos: &FormatArgPosition, usage: FormatParamUsage, fixes: &mut Vec<(Span, String)>) -> bool { + let index = pos.index.unwrap(); + let arg = &self.format_args.arguments.all_args()[index]; + + if !matches!(arg.kind, FormatArgumentKind::Captured(_)) + && let rustc_ast::ExprKind::Path(None, path) = &arg.expr.kind + && let [segment] = path.segments.as_slice() + && segment.args.is_none() + && let Some(arg_span) = format_arg_removal_span(self.format_args, index) + && let Some(pos_span) = pos.span + { + let replacement = match usage { + FormatParamUsage::Argument => segment.ident.name.to_string(), + FormatParamUsage::Width => format!("{}$", segment.ident.name), + FormatParamUsage::Precision => format!(".{}$", segment.ident.name), + }; + fixes.push((pos_span, replacement)); + fixes.push((arg_span, String::new())); + true // successful inlining, continue checking } else { - span_lint_and_sugg( - cx, - TO_STRING_IN_FORMAT_ARGS, - value.span, - &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), - "use this", - format!( - "{}{:*>n_needed_derefs$}{receiver_snippet}", - if needs_ref { "&" } else { "" }, - "" - ), - Applicability::MachineApplicable, - ); + // Do not continue inlining (return false) in case + // * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)` + // * if allow_mixed_uninlined_format_args is false and this arg hasn't been inlined already + pos.kind != FormatArgPositionKind::Number + && (!self.ignore_mixed || matches!(arg.kind, FormatArgumentKind::Captured(_))) } } -} -fn format_arg_positions( - format_args: &rustc_ast::FormatArgs, -) -> impl Iterator { - format_args.template.iter().flat_map(|piece| match piece { - FormatArgsPiece::Placeholder(placeholder) => { - let mut positions = ArrayVec::<_, 3>::new(); + fn check_format_in_format_args(&self, name: Symbol, arg: &Expr<'_>) { + let expn_data = arg.span.ctxt().outer_expn_data(); + if expn_data.call_site.from_expansion() { + return; + } + let Some(mac_id) = expn_data.macro_def_id else { return }; + if !self.cx.tcx.is_diagnostic_item(sym::format_macro, mac_id) { + return; + } + span_lint_and_then( + self.cx, + FORMAT_IN_FORMAT_ARGS, + self.macro_call.span, + &format!("`format!` in `{name}!` args"), + |diag| { + diag.help(format!( + "combine the `format!(..)` arguments with the outer `{name}!(..)` call" + )); + diag.help("or consider changing `format!` to `format_args!`"); + }, + ); + } - positions.push((&placeholder.argument, FormatParamUsage::Argument)); - if let Some(FormatCount::Argument(position)) = &placeholder.format_options.width { - positions.push((position, FormatParamUsage::Width)); - } - if let Some(FormatCount::Argument(position)) = &placeholder.format_options.precision { - positions.push((position, FormatParamUsage::Precision)); + fn check_to_string_in_format_args(&self, name: Symbol, value: &Expr<'_>) { + let cx = self.cx; + if !value.span.from_expansion() + && let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind + && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id) + && is_diag_trait_item(cx, method_def_id, sym::ToString) + && let receiver_ty = cx.typeck_results().expr_ty(receiver) + && let Some(display_trait_id) = cx.tcx.get_diagnostic_item(sym::Display) + && let (n_needed_derefs, target) = + count_needed_derefs(receiver_ty, cx.typeck_results().expr_adjustments(receiver).iter()) + && implements_trait(cx, target, display_trait_id, &[]) + && let Some(sized_trait_id) = cx.tcx.lang_items().sized_trait() + && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) + { + let needs_ref = !implements_trait(cx, receiver_ty, sized_trait_id, &[]); + if n_needed_derefs == 0 && !needs_ref { + span_lint_and_sugg( + cx, + TO_STRING_IN_FORMAT_ARGS, + to_string_span.with_lo(receiver.span.hi()), + &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), + "remove this", + String::new(), + Applicability::MachineApplicable, + ); + } else { + span_lint_and_sugg( + cx, + TO_STRING_IN_FORMAT_ARGS, + value.span, + &format!("`to_string` applied to a type that implements `Display` in `{name}!` args"), + "use this", + format!( + "{}{:*>n_needed_derefs$}{receiver_snippet}", + if needs_ref { "&" } else { "" }, + "" + ), + Applicability::MachineApplicable, + ); } + } + } - positions - }, - FormatArgsPiece::Literal(_) => ArrayVec::new(), - }) -} + fn format_arg_positions(&self) -> impl Iterator { + self.format_args.template.iter().flat_map(|piece| match piece { + FormatArgsPiece::Placeholder(placeholder) => { + let mut positions = ArrayVec::<_, 3>::new(); -/// Returns true if the format argument at `index` is referred to by multiple format params -fn is_aliased(format_args: &rustc_ast::FormatArgs, index: usize) -> bool { - format_arg_positions(format_args) - .filter(|(position, _)| position.index == Ok(index)) - .at_most_one() - .is_err() + positions.push((&placeholder.argument, FormatParamUsage::Argument)); + if let Some(FormatCount::Argument(position)) = &placeholder.format_options.width { + positions.push((position, FormatParamUsage::Width)); + } + if let Some(FormatCount::Argument(position)) = &placeholder.format_options.precision { + positions.push((position, FormatParamUsage::Precision)); + } + + positions + }, + FormatArgsPiece::Literal(_) => ArrayVec::new(), + }) + } + + /// Returns true if the format argument at `index` is referred to by multiple format params + fn is_aliased(&self, index: usize) -> bool { + self.format_arg_positions() + .filter(|(position, _)| position.index == Ok(index)) + .at_most_one() + .is_err() + } } fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>) diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index 9360eb1fa91ad..93517076cda01 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -7,7 +7,7 @@ use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, Symbol}; declare_clippy_lint! { /// ### What it does @@ -119,123 +119,132 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl { } fn check_impl_item_post(&mut self, cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { - // Assume no nested Impl of Debug and Display within eachother + // Assume no nested Impl of Debug and Display within each other if is_format_trait_impl(cx, impl_item).is_some() { self.format_trait_impl = None; } } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - let Some(format_trait_impl) = self.format_trait_impl else { - return; - }; - - if format_trait_impl.name == sym::Display { - check_to_string_in_display(cx, expr); + if let Some(format_trait_impl) = self.format_trait_impl { + let linter = FormatImplExpr { + cx, + expr, + format_trait_impl, + }; + linter.check_to_string_in_display(); + linter.check_self_in_format_args(); + linter.check_print_in_format_impl(); } - - check_self_in_format_args(cx, expr, format_trait_impl); - check_print_in_format_impl(cx, expr, format_trait_impl); } } -fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::MethodCall(path, self_arg, ..) = expr.kind - // Get the hir_id of the object we are calling the method on - // Is the method to_string() ? - && path.ident.name == sym::to_string - // Is the method a part of the ToString trait? (i.e. not to_string() implemented - // separately) - && let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && is_diag_trait_item(cx, expr_def_id, sym::ToString) - // Is the method is called on self - && let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind - && let [segment] = path.segments - && segment.ident.name == kw::SelfLower - { - span_lint( - cx, - RECURSIVE_FORMAT_IMPL, - expr.span, - "using `self.to_string` in `fmt::Display` implementation will cause infinite recursion", - ); - } +struct FormatImplExpr<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + format_trait_impl: FormatTraitNames, } -fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTraitNames) { - // Check each arg in format calls - do we ever use Display on self (directly or via deref)? - if let Some(outer_macro) = root_macro_call_first_node(cx, expr) - && let macro_def_id = outer_macro.def_id - && is_format_macro(cx, macro_def_id) - && let Some(format_args) = find_format_args(cx, expr, outer_macro.expn) - { - for piece in &format_args.template { - if let FormatArgsPiece::Placeholder(placeholder) = piece - && let trait_name = match placeholder.format_trait { - FormatTrait::Display => sym::Display, - FormatTrait::Debug => sym::Debug, - FormatTrait::LowerExp => sym!(LowerExp), - FormatTrait::UpperExp => sym!(UpperExp), - FormatTrait::Octal => sym!(Octal), - FormatTrait::Pointer => sym::Pointer, - FormatTrait::Binary => sym!(Binary), - FormatTrait::LowerHex => sym!(LowerHex), - FormatTrait::UpperHex => sym!(UpperHex), +impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> { + fn check_to_string_in_display(&self) { + if self.format_trait_impl.name == sym::Display + && let ExprKind::MethodCall(path, self_arg, ..) = self.expr.kind + // Get the hir_id of the object we are calling the method on + // Is the method to_string() ? + && path.ident.name == sym::to_string + // Is the method a part of the ToString trait? (i.e. not to_string() implemented + // separately) + && let Some(expr_def_id) = self.cx.typeck_results().type_dependent_def_id(self.expr.hir_id) + && is_diag_trait_item(self.cx, expr_def_id, sym::ToString) + // Is the method is called on self + && let ExprKind::Path(QPath::Resolved(_, path)) = self_arg.kind + && let [segment] = path.segments + && segment.ident.name == kw::SelfLower + { + span_lint( + self.cx, + RECURSIVE_FORMAT_IMPL, + self.expr.span, + "using `self.to_string` in `fmt::Display` implementation will cause infinite recursion", + ); + } + } + + fn check_self_in_format_args(&self) { + // Check each arg in format calls - do we ever use Display on self (directly or via deref)? + if let Some(outer_macro) = root_macro_call_first_node(self.cx, self.expr) + && let macro_def_id = outer_macro.def_id + && is_format_macro(self.cx, macro_def_id) + && let Some(format_args) = find_format_args(self.cx, self.expr, outer_macro.expn) + { + for piece in &format_args.template { + if let FormatArgsPiece::Placeholder(placeholder) = piece + && let trait_name = match placeholder.format_trait { + FormatTrait::Display => sym::Display, + FormatTrait::Debug => sym::Debug, + FormatTrait::LowerExp => sym!(LowerExp), + FormatTrait::UpperExp => sym!(UpperExp), + FormatTrait::Octal => sym!(Octal), + FormatTrait::Pointer => sym::Pointer, + FormatTrait::Binary => sym!(Binary), + FormatTrait::LowerHex => sym!(LowerHex), + FormatTrait::UpperHex => sym!(UpperHex), + } + && trait_name == self.format_trait_impl.name + && let Ok(index) = placeholder.argument.index + && let Some(arg) = format_args.arguments.all_args().get(index) + && let Ok(arg_expr) = find_format_arg_expr(self.expr, arg) + { + self.check_format_arg_self(arg_expr); } - && trait_name == impl_trait.name - && let Ok(index) = placeholder.argument.index - && let Some(arg) = format_args.arguments.all_args().get(index) - && let Ok(arg_expr) = find_format_arg_expr(expr, arg) - { - check_format_arg_self(cx, expr.span, arg_expr, impl_trait); } } } -} -fn check_format_arg_self(cx: &LateContext<'_>, span: Span, arg: &Expr<'_>, impl_trait: FormatTraitNames) { - // Handle multiple dereferencing of references e.g. &&self - // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl) - // Since the argument to fmt is itself a reference: &self - let reference = peel_ref_operators(cx, arg); - let map = cx.tcx.hir(); - // Is the reference self? - if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) { - let FormatTraitNames { name, .. } = impl_trait; - span_lint( - cx, - RECURSIVE_FORMAT_IMPL, - span, - &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"), - ); + fn check_format_arg_self(&self, arg: &Expr<'_>) { + // Handle multiple dereferencing of references e.g. &&self + // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl) + // Since the argument to fmt is itself a reference: &self + let reference = peel_ref_operators(self.cx, arg); + let map = self.cx.tcx.hir(); + // Is the reference self? + if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) { + let FormatTraitNames { name, .. } = self.format_trait_impl; + span_lint( + self.cx, + RECURSIVE_FORMAT_IMPL, + self.expr.span, + &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"), + ); + } } -} -fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTraitNames) { - if let Some(macro_call) = root_macro_call_first_node(cx, expr) - && let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id) - { - let replacement = match name { - sym::print_macro | sym::eprint_macro => "write", - sym::println_macro | sym::eprintln_macro => "writeln", - _ => return, - }; + fn check_print_in_format_impl(&self) { + if let Some(macro_call) = root_macro_call_first_node(self.cx, self.expr) + && let Some(name) = self.cx.tcx.get_diagnostic_name(macro_call.def_id) + { + let replacement = match name { + sym::print_macro | sym::eprint_macro => "write", + sym::println_macro | sym::eprintln_macro => "writeln", + _ => return, + }; - let name = name.as_str().strip_suffix("_macro").unwrap(); + let name = name.as_str().strip_suffix("_macro").unwrap(); - span_lint_and_sugg( - cx, - PRINT_IN_FORMAT_IMPL, - macro_call.span, - &format!("use of `{name}!` in `{}` impl", impl_trait.name), - "replace with", - if let Some(formatter_name) = impl_trait.formatter_name { - format!("{replacement}!({formatter_name}, ..)") - } else { - format!("{replacement}!(..)") - }, - Applicability::HasPlaceholders, - ); + span_lint_and_sugg( + self.cx, + PRINT_IN_FORMAT_IMPL, + macro_call.span, + &format!("use of `{name}!` in `{}` impl", self.format_trait_impl.name), + "replace with", + if let Some(formatter_name) = self.format_trait_impl.formatter_name { + format!("{replacement}!({formatter_name}, ..)") + } else { + format!("{replacement}!(..)") + }, + Applicability::HasPlaceholders, + ); + } } } diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index fab8ffedb9493..74582f7f1de23 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -1,11 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::FnKind; +use rustc_hir::def_id::DefId; use rustc_hir::{ - Body, FnDecl, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, ItemKind, TraitBoundModifier, TraitItem, - TraitItemKind, TyKind, + GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, TypeBinding, + WherePredicate, }; use rustc_hir_analysis::hir_ty_to_ty; use rustc_lint::{LateContext, LateLintPass}; @@ -50,20 +49,17 @@ declare_clippy_lint! { } declare_lint_pass!(ImpliedBoundsInImpls => [IMPLIED_BOUNDS_IN_IMPLS]); -#[allow(clippy::too_many_arguments)] fn emit_lint( cx: &LateContext<'_>, poly_trait: &rustc_hir::PolyTraitRef<'_>, - opaque_ty: &rustc_hir::OpaqueTy<'_>, + bounds: GenericBounds<'_>, index: usize, - // The bindings that were implied + // The bindings that were implied, used for suggestion purposes since removing a bound with associated types + // means we might need to then move it to a different bound implied_bindings: &[rustc_hir::TypeBinding<'_>], - // The original bindings that `implied_bindings` are implied from - implied_by_bindings: &[rustc_hir::TypeBinding<'_>], - implied_by_args: &[GenericArg<'_>], - implied_by_span: Span, + bound: &ImplTraitBound<'_>, ) { - let implied_by = snippet(cx, implied_by_span, ".."); + let implied_by = snippet(cx, bound.span, ".."); span_lint_and_then( cx, @@ -75,10 +71,10 @@ fn emit_lint( // to include the `+` token that is ahead or behind, // so we don't end up with something like `impl + B` or `impl A + ` - let implied_span_extended = if let Some(next_bound) = opaque_ty.bounds.get(index + 1) { + let implied_span_extended = if let Some(next_bound) = bounds.get(index + 1) { poly_trait.span.to(next_bound.span().shrink_to_lo()) } else if index > 0 - && let Some(prev_bound) = opaque_ty.bounds.get(index - 1) + && let Some(prev_bound) = bounds.get(index - 1) { prev_bound.span().shrink_to_hi().to(poly_trait.span.shrink_to_hi()) } else { @@ -93,17 +89,17 @@ fn emit_lint( // If we're going to suggest removing `Deref<..>`, we'll need to put `` on `DerefMut` let omitted_assoc_tys: Vec<_> = implied_bindings .iter() - .filter(|binding| !implied_by_bindings.iter().any(|b| b.ident == binding.ident)) + .filter(|binding| !bound.bindings.iter().any(|b| b.ident == binding.ident)) .collect(); if !omitted_assoc_tys.is_empty() { // `<>` needs to be added if there aren't yet any generic arguments or bindings - let needs_angle_brackets = implied_by_args.is_empty() && implied_by_bindings.is_empty(); - let insert_span = match (implied_by_args, implied_by_bindings) { + let needs_angle_brackets = bound.args.is_empty() && bound.bindings.is_empty(); + let insert_span = match (bound.args, bound.bindings) { ([.., arg], [.., binding]) => arg.span().max(binding.span).shrink_to_hi(), ([.., arg], []) => arg.span().shrink_to_hi(), ([], [.., binding]) => binding.span.shrink_to_hi(), - ([], []) => implied_by_span.shrink_to_hi(), + ([], []) => bound.span.shrink_to_hi(), }; let mut associated_tys_sugg = if needs_angle_brackets { @@ -223,111 +219,135 @@ fn is_same_generics<'tcx>( }) } -fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) { - if let FnRetTy::Return(ty) = decl.output - &&let TyKind::OpaqueDef(item_id, ..) = ty.kind - && let item = cx.tcx.hir().item(item_id) - && let ItemKind::OpaqueTy(opaque_ty) = item.kind - // Very often there is only a single bound, e.g. `impl Deref<..>`, in which case - // we can avoid doing a bunch of stuff unnecessarily. - && opaque_ty.bounds.len() > 1 - { - // Get all the (implied) trait predicates in the bounds. - // For `impl Deref + DerefMut` this will contain [`Deref`]. - // The implied `Deref` comes from `DerefMut` because `trait DerefMut: Deref {}`. - // N.B. (G)ATs are fine to disregard, because they must be the same for all of its supertraits. - // Example: - // `impl Deref + DerefMut` is not allowed. - // `DerefMut::Target` needs to match `Deref::Target`. - let implied_bounds: Vec<_> = opaque_ty - .bounds - .iter() - .filter_map(|bound| { - if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound - && let [.., path] = poly_trait.trait_ref.path.segments - && poly_trait.bound_generic_params.is_empty() - && let Some(trait_def_id) = path.res.opt_def_id() - && let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates - && !predicates.is_empty() - // If the trait has no supertrait, there is nothing to add. - { - Some((bound.span(), path, predicates, trait_def_id)) - } else { - None - } - }) - .collect(); +struct ImplTraitBound<'tcx> { + /// The span of the bound in the `impl Trait` type + span: Span, + /// The predicates defined in the trait referenced by this bound. This also contains the actual + /// supertrait bounds + predicates: &'tcx [(ty::Clause<'tcx>, Span)], + /// The `DefId` of the trait being referenced by this bound + trait_def_id: DefId, + /// The generic arguments on the `impl Trait` bound + args: &'tcx [GenericArg<'tcx>], + /// The associated types on this bound + bindings: &'tcx [TypeBinding<'tcx>], +} - // Lint all bounds in the `impl Trait` type that are also in the `implied_bounds` vec. - // This involves some extra logic when generic arguments are present, since - // simply comparing trait `DefId`s won't be enough. We also need to compare the generics. - for (index, bound) in opaque_ty.bounds.iter().enumerate() { +/// Given an `impl Trait` type, gets all the supertraits from each bound ("implied bounds"). +/// +/// For `impl Deref + DerefMut + Eq` this returns `[Deref, PartialEq]`. +/// The `Deref` comes from `DerefMut` because `trait DerefMut: Deref {}`, and `PartialEq` comes from +/// `Eq`. +fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) -> Vec> { + bounds + .iter() + .filter_map(|bound| { if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound && let [.., path] = poly_trait.trait_ref.path.segments - && let implied_args = path.args.map_or([].as_slice(), |a| a.args) - && let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings) - && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id() - && let Some((implied_by_span, implied_by_args, implied_by_bindings)) = - implied_bounds - .iter() - .find_map(|&(span, implied_by_path, preds, implied_by_def_id)| { - let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args); - let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings); + && poly_trait.bound_generic_params.is_empty() + && let Some(trait_def_id) = path.res.opt_def_id() + && let predicates = cx.tcx.super_predicates_of(trait_def_id).predicates + // If the trait has no supertrait, there is no need to collect anything from that bound + && !predicates.is_empty() + { + Some(ImplTraitBound { + predicates, + args: path.args.map_or([].as_slice(), |p| p.args), + bindings: path.args.map_or([].as_slice(), |p| p.bindings), + trait_def_id, + span: bound.span(), + }) + } else { + None + } + }) + .collect() +} - preds.iter().find_map(|(clause, _)| { - if let ClauseKind::Trait(tr) = clause.kind().skip_binder() - && tr.def_id() == def_id - && is_same_generics( - cx.tcx, - tr.trait_ref.args, - implied_by_args, - implied_args, - implied_by_def_id, - def_id, - ) - { - Some((span, implied_by_args, implied_by_bindings)) - } else { - None - } - }) - }) +/// Given a bound in an `impl Trait` type, looks for a trait in the set of supertraits (previously +/// collected in [`collect_supertrait_bounds`]) that matches (same trait and generic arguments). +fn find_bound_in_supertraits<'a, 'tcx>( + cx: &LateContext<'tcx>, + trait_def_id: DefId, + args: &'tcx [GenericArg<'tcx>], + bounds: &'a [ImplTraitBound<'tcx>], +) -> Option<&'a ImplTraitBound<'tcx>> { + bounds.iter().find(|bound| { + bound.predicates.iter().any(|(clause, _)| { + if let ClauseKind::Trait(tr) = clause.kind().skip_binder() + && tr.def_id() == trait_def_id { - emit_lint( - cx, - poly_trait, - opaque_ty, - index, - implied_bindings, - implied_by_bindings, - implied_by_args, - implied_by_span, - ); + is_same_generics( + cx.tcx, + tr.trait_ref.args, + bound.args, + args, + bound.trait_def_id, + trait_def_id, + ) + } else { + false } + }) + }) +} + +fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { + if bounds.len() == 1 { + // Very often there is only a single bound, e.g. `impl Deref<..>`, in which case + // we can avoid doing a bunch of stuff unnecessarily; there will trivially be + // no duplicate bounds + return; + } + + let supertraits = collect_supertrait_bounds(cx, bounds); + + // Lint all bounds in the `impl Trait` type that we've previously also seen in the set of + // supertraits of each of the bounds. + // This involves some extra logic when generic arguments are present, since + // simply comparing trait `DefId`s won't be enough. We also need to compare the generics. + for (index, bound) in bounds.iter().enumerate() { + if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound + && let [.., path] = poly_trait.trait_ref.path.segments + && let implied_args = path.args.map_or([].as_slice(), |a| a.args) + && let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings) + && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id() + && let Some(bound) = find_bound_in_supertraits(cx, def_id, implied_args, &supertraits) + // If the implied bound has a type binding that also exists in the implied-by trait, + // then we shouldn't lint. See #11880 for an example. + && let assocs = cx.tcx.associated_items(bound.trait_def_id) + && !implied_bindings.iter().any(|binding| { + assocs + .filter_by_name_unhygienic(binding.ident.name) + .next() + .is_some_and(|assoc| assoc.kind == ty::AssocKind::Type) + }) + { + emit_lint(cx, poly_trait, bounds, index, implied_bindings, bound); } } } -impl LateLintPass<'_> for ImpliedBoundsInImpls { - fn check_fn( - &mut self, - cx: &LateContext<'_>, - _: FnKind<'_>, - decl: &FnDecl<'_>, - _: &Body<'_>, - _: Span, - _: LocalDefId, - ) { - check(cx, decl); - } - fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) { - if let TraitItemKind::Fn(sig, ..) = &item.kind { - check(cx, sig.decl); +impl<'tcx> LateLintPass<'tcx> for ImpliedBoundsInImpls { + fn check_generics(&mut self, cx: &LateContext<'tcx>, generics: &rustc_hir::Generics<'tcx>) { + for predicate in generics.predicates { + if let WherePredicate::BoundPredicate(predicate) = predicate + // In theory, the origin doesn't really matter, + // we *could* also lint on explicit where clauses written out by the user, + // not just impl trait desugared ones, but that contradicts with the lint name... + && let PredicateOrigin::ImplTrait = predicate.origin + { + check(cx, predicate.bounds); + } } } - fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &ImplItem<'_>) { - if let ImplItemKind::Fn(sig, ..) = &item.kind { - check(cx, sig.decl); + + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &rustc_hir::Ty<'_>) { + if let TyKind::OpaqueDef(item_id, ..) = ty.kind + && let item = cx.tcx.hir().item(item_id) + && let ItemKind::OpaqueTy(opaque_ty) = item.kind + { + check(cx, opaque_ty.bounds); } } } diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index f2f0e7d426628..cd000fcd18449 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -1,14 +1,15 @@ use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_in_test_function; use rustc_attr::{StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; -use rustc_span::Span; +use rustc_span::{ExpnKind, Span}; declare_clippy_lint! { /// ### What it does @@ -81,13 +82,18 @@ impl IncompatibleMsrv { version } - fn emit_lint_if_under_msrv(&mut self, cx: &LateContext<'_>, def_id: DefId, span: Span) { + fn emit_lint_if_under_msrv(&mut self, cx: &LateContext<'_>, def_id: DefId, node: HirId, span: Span) { if def_id.is_local() { // We don't check local items since their MSRV is supposed to always be valid. return; } let version = self.get_def_id_version(cx.tcx, def_id); - if self.msrv.meets(version) { + if self.msrv.meets(version) || is_in_test_function(cx.tcx, node) { + return; + } + if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = span.ctxt().outer_expn_data().kind { + // Desugared expressions get to cheat and stability is ignored. + // Intentionally not using `.from_expansion()`, since we do still care about macro expansions return; } self.emit_lint_for(cx, span, version); @@ -117,14 +123,14 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { match expr.kind { ExprKind::MethodCall(_, _, _, span) => { if let Some(method_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { - self.emit_lint_if_under_msrv(cx, method_did, span); + self.emit_lint_if_under_msrv(cx, method_did, expr.hir_id, span); } }, ExprKind::Call(call, [_]) => { if let ExprKind::Path(qpath) = call.kind && let Some(path_def_id) = cx.qpath_res(&qpath, call.hir_id).opt_def_id() { - self.emit_lint_if_under_msrv(cx, path_def_id, call.span); + self.emit_lint_if_under_msrv(cx, path_def_id, expr.hir_id, call.span); } }, _ => {}, diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index 41e9d5b1c2e9d..5b5eb355f86cd 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -255,7 +255,9 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { && let hir::Node::Expr(maybe_addrof_expr) = cx.tcx.parent_hir_node(parent_id) && let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind { - use_info.index_use.push((index_value, cx.tcx.hir().span(parent_expr.hir_id))); + use_info + .index_use + .push((index_value, cx.tcx.hir().span(parent_expr.hir_id))); return; } diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 391db0b0df726..35fcd8cdd3547 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -174,6 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { // only `usize` index is legal in rust array index // leave other type to rustc if let Constant::Int(off) = constant + && off <= usize::MAX as u128 && let ty::Uint(utype) = cx.typeck_results().expr_ty(index).kind() && *utype == ty::UintTy::Usize && let ty::Array(_, s) = ty.kind() diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 276c1abb60cd5..0b4c416d94db0 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -385,7 +385,6 @@ impl LateLintPass<'_> for ItemNameRepetitions { assert!(last.is_some()); } - #[expect(clippy::similar_names)] fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { let item_name = item.ident.name.as_str(); let item_camel = to_camel_case(item_name); diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index b9fad726511c5..32ae6be568735 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::span_lint; -use clippy_utils::get_parent_node; use clippy_utils::ty::implements_trait; use rustc_hir::def_id::LocalDefId; use rustc_hir::{FnSig, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind}; @@ -56,8 +55,8 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator { let name = item.ident.name.as_str(); if matches!(name, "iter" | "iter_mut") && !matches!( - get_parent_node(cx.tcx, item.hir_id()), - Some(Node::Item(Item { kind: ItemKind::Impl(i), .. })) if i.of_trait.is_some() + cx.tcx.parent_hir_node(item.hir_id()), + Node::Item(Item { kind: ItemKind::Impl(i), .. }) if i.of_trait.is_some() ) { if let ImplItemKind::Fn(fn_sig, _) = &item.kind { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 14bd82f9c97ea..76e759683145e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -14,7 +14,7 @@ clippy::missing_docs_in_private_items, clippy::must_use_candidate, rustc::diagnostic_outside_of_impl, - rustc::untranslatable_diagnostic, + rustc::untranslatable_diagnostic )] #![warn(trivial_casts, trivial_numeric_casts)] // warn on lints, that are included in `rust-lang/rust`s bootstrap @@ -231,6 +231,7 @@ mod missing_trait_methods; mod mixed_read_write_in_expression; mod module_style; mod multi_assignments; +mod multiple_bound_locations; mod multiple_unsafe_ops_per_block; mod mut_key; mod mut_mut; @@ -1067,7 +1068,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| { Box::new(single_call_fn::SingleCallFn { avoid_breaking_exported_api, - def_id_to_usage: rustc_data_structures::fx::FxHashMap::default(), + def_id_to_usage: rustc_data_structures::fx::FxIndexMap::default(), }) }); store.register_early_pass(move || { @@ -1116,6 +1117,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { }); store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv()))); store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); + store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/loops/infinite_loop.rs b/clippy_lints/src/loops/infinite_loop.rs index 5e099f1e76f86..5b5bb88c17908 100644 --- a/clippy_lints/src/loops/infinite_loop.rs +++ b/clippy_lints/src/loops/infinite_loop.rs @@ -1,17 +1,18 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{fn_def_id, is_lint_allowed}; +use clippy_utils::{fn_def_id, is_from_proc_macro, is_lint_allowed}; use hir::intravisit::{walk_expr, Visitor}; use hir::{Expr, ExprKind, FnRetTy, FnSig, Node}; use rustc_ast::Label; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext}; +use rustc_middle::lint::in_external_macro; use super::INFINITE_LOOP; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, - expr: &Expr<'_>, + expr: &Expr<'tcx>, loop_block: &'tcx hir::Block<'_>, label: Option