From 9b221109bf8c0b24e7114f32add87863ed7253a6 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 14 Jun 2024 14:57:14 +0000 Subject: [PATCH 01/12] Add powerpc-unknown-openbsd maintaince status --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- src/doc/rustc/src/platform-support/powerpc-unknown-openbsd.md | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/powerpc-unknown-openbsd.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 201ace5ce3a7b..8277cc75537c2 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -60,6 +60,7 @@ - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md) - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) + - [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md) - [powerpc64-ibm-aix](platform-support/aix.md) - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index c672cff74526e..894e404da58fd 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -329,7 +329,7 @@ target | std | host | notes `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3 [`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems -`powerpc-unknown-openbsd` | ? | | +[`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | | `powerpc-wrs-vxworks-spe` | ? | | `powerpc-wrs-vxworks` | ? | | `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2) diff --git a/src/doc/rustc/src/platform-support/powerpc-unknown-openbsd.md b/src/doc/rustc/src/platform-support/powerpc-unknown-openbsd.md new file mode 100644 index 0000000000000..b1600c71f1f3c --- /dev/null +++ b/src/doc/rustc/src/platform-support/powerpc-unknown-openbsd.md @@ -0,0 +1,3 @@ +## Designated maintainers + +`powerpc-unknown-openbsd` is not maintained by OpenBSD developers and there are currently no active rustc maintainers. From 2220ef88adfc935e14aeb0a6fc0f8c12b93bf453 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 18 Apr 2024 01:51:06 +0200 Subject: [PATCH 02/12] Add PidFd::{kill, wait, try_wait} --- library/std/src/os/linux/process.rs | 68 ++++++++++---- library/std/src/sys/pal/unix/linux/mod.rs | 1 + library/std/src/sys/pal/unix/linux/pidfd.rs | 76 ++++++++++++++++ .../std/src/sys/pal/unix/linux/pidfd/tests.rs | 88 +++++++++++++++++++ library/std/src/sys/pal/unix/mod.rs | 2 + .../src/sys/pal/unix/process/process_unix.rs | 80 +++++++---------- .../pal/unix/process/process_unix/tests.rs | 54 ------------ 7 files changed, 252 insertions(+), 117 deletions(-) create mode 100644 library/std/src/sys/pal/unix/linux/mod.rs create mode 100644 library/std/src/sys/pal/unix/linux/pidfd.rs create mode 100644 library/std/src/sys/pal/unix/linux/pidfd/tests.rs diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 2ba67a6dd1aa9..cf0c679640d3c 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -6,14 +6,15 @@ use crate::io::Result; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; -use crate::process; +use crate::process::{self, ExitStatus}; use crate::sealed::Sealed; -#[cfg(not(doc))] use crate::sys::fd::FileDesc; +#[cfg(not(doc))] +use crate::sys::linux::pidfd::PidFd as InnerPidFd; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; #[cfg(doc)] -struct FileDesc; +struct InnerPidFd; /// This type represents a file descriptor that refers to a process. /// @@ -47,25 +48,60 @@ struct FileDesc; /// [`take_pidfd`]: ChildExt::take_pidfd /// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html #[derive(Debug)] +#[repr(transparent)] pub struct PidFd { - inner: FileDesc, + inner: InnerPidFd, +} + +impl PidFd { + /// Forces the child process to exit. + /// + /// Unlike [`Child::kill`] it is possible to attempt to kill + /// reaped children since PidFd does not suffer from pid recycling + /// races. But doing so will return an Error. + /// + /// [`Child::kill`]: process::Child::kill + pub fn kill(&self) -> Result<()> { + self.inner.kill() + } + + /// Waits for the child to exit completely, returning the status that it exited with. + /// + /// Unlike [`Child::wait`] it does not ensure that the stdin handle is closed. + /// Additionally it will not return an `ExitStatus` if the child + /// has already been reaped. Instead an error will be returned. + /// + /// [`Child::wait`]: process::Child::wait + pub fn wait(&self) -> Result { + self.inner.wait().map(FromInner::from_inner) + } + + /// Attempts to collect the exit status of the child if it has already exited. + /// + /// Unlike [`Child::try_wait`] this method will return an Error + /// if the child has already been reaped. + /// + /// [`Child::try_wait`]: process::Child::try_wait + pub fn try_wait(&self) -> Result> { + Ok(self.inner.try_wait()?.map(FromInner::from_inner)) + } } -impl AsInner for PidFd { +impl AsInner for PidFd { #[inline] - fn as_inner(&self) -> &FileDesc { + fn as_inner(&self) -> &InnerPidFd { &self.inner } } -impl FromInner for PidFd { - fn from_inner(inner: FileDesc) -> PidFd { +impl FromInner for PidFd { + fn from_inner(inner: InnerPidFd) -> PidFd { PidFd { inner } } } -impl IntoInner for PidFd { - fn into_inner(self) -> FileDesc { +impl IntoInner for PidFd { + fn into_inner(self) -> InnerPidFd { self.inner } } @@ -73,37 +109,37 @@ impl IntoInner for PidFd { impl AsRawFd for PidFd { #[inline] fn as_raw_fd(&self) -> RawFd { - self.as_inner().as_raw_fd() + self.as_inner().as_inner().as_raw_fd() } } impl FromRawFd for PidFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { - Self::from_inner(FileDesc::from_raw_fd(fd)) + Self::from_inner(InnerPidFd::from_raw_fd(fd)) } } impl IntoRawFd for PidFd { fn into_raw_fd(self) -> RawFd { - self.into_inner().into_raw_fd() + self.into_inner().into_inner().into_raw_fd() } } impl AsFd for PidFd { fn as_fd(&self) -> BorrowedFd<'_> { - self.as_inner().as_fd() + self.as_inner().as_inner().as_fd() } } impl From for PidFd { fn from(fd: OwnedFd) -> Self { - Self::from_inner(FileDesc::from_inner(fd)) + Self::from_inner(InnerPidFd::from_inner(FileDesc::from_inner(fd))) } } impl From for OwnedFd { fn from(pid_fd: PidFd) -> Self { - pid_fd.into_inner().into_inner() + pid_fd.into_inner().into_inner().into_inner() } } diff --git a/library/std/src/sys/pal/unix/linux/mod.rs b/library/std/src/sys/pal/unix/linux/mod.rs new file mode 100644 index 0000000000000..88aa1e3deccf8 --- /dev/null +++ b/library/std/src/sys/pal/unix/linux/mod.rs @@ -0,0 +1 @@ +pub mod pidfd; diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs new file mode 100644 index 0000000000000..7474f80e94f9d --- /dev/null +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -0,0 +1,76 @@ +use crate::io; +use crate::os::fd::{AsRawFd, FromRawFd, RawFd}; +use crate::sys::cvt; +use crate::sys::pal::unix::fd::FileDesc; +use crate::sys::process::ExitStatus; +use crate::sys_common::{AsInner, FromInner, IntoInner}; + +#[cfg(test)] +mod tests; + +#[derive(Debug)] +pub(crate) struct PidFd(FileDesc); + +impl PidFd { + pub fn kill(&self) -> io::Result<()> { + return cvt(unsafe { + libc::syscall( + libc::SYS_pidfd_send_signal, + self.0.as_raw_fd(), + libc::SIGKILL, + crate::ptr::null::<()>(), + 0, + ) + }) + .map(drop); + } + + pub fn wait(&self) -> io::Result { + let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; + cvt(unsafe { + libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) + })?; + return Ok(ExitStatus::from_waitid_siginfo(siginfo)); + } + + pub fn try_wait(&self) -> io::Result> { + let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; + + cvt(unsafe { + libc::waitid( + libc::P_PIDFD, + self.0.as_raw_fd() as u32, + &mut siginfo, + libc::WEXITED | libc::WNOHANG, + ) + })?; + if unsafe { siginfo.si_pid() } == 0 { + return Ok(None); + } + return Ok(Some(ExitStatus::from_waitid_siginfo(siginfo))); + } +} + +impl AsInner for PidFd { + fn as_inner(&self) -> &FileDesc { + &self.0 + } +} + +impl IntoInner for PidFd { + fn into_inner(self) -> FileDesc { + self.0 + } +} + +impl FromInner for PidFd { + fn from_inner(inner: FileDesc) -> Self { + Self(inner) + } +} + +impl FromRawFd for PidFd { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + Self(FileDesc::from_raw_fd(fd)) + } +} diff --git a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs new file mode 100644 index 0000000000000..42b3df6299114 --- /dev/null +++ b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs @@ -0,0 +1,88 @@ +use crate::assert_matches::assert_matches; +use crate::os::fd::{AsRawFd, RawFd}; +use crate::os::linux::process::{ChildExt, CommandExt}; +use crate::os::unix::process::ExitStatusExt; +use crate::process::Command; + +#[test] +fn test_command_pidfd() { + let pidfd_open_available = probe_pidfd_support(); + + // always exercise creation attempts + let mut child = Command::new("false").create_pidfd(true).spawn().unwrap(); + + // but only check if we know that the kernel supports pidfds. + // We don't assert the precise value, since the standard library + // might have opened other file descriptors before our code runs. + if pidfd_open_available { + assert!(child.pidfd().is_ok()); + } + if let Ok(pidfd) = child.pidfd() { + let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap(); + assert!(flags & libc::FD_CLOEXEC != 0); + } + let status = child.wait().expect("error waiting on pidfd"); + assert_eq!(status.code(), Some(1)); + + let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap(); + assert_matches!(child.try_wait(), Ok(None)); + child.kill().expect("failed to kill child"); + let status = child.wait().expect("error waiting on pidfd"); + assert_eq!(status.signal(), Some(libc::SIGKILL)); + + let _ = Command::new("echo") + .create_pidfd(false) + .spawn() + .unwrap() + .pidfd() + .expect_err("pidfd should not have been created when create_pid(false) is set"); + + let _ = Command::new("echo") + .spawn() + .unwrap() + .pidfd() + .expect_err("pidfd should not have been created"); +} + +#[test] +fn test_pidfd() { + if !probe_pidfd_support() { + return; + } + + let mut child = Command::new("sleep") + .arg("1000") + .create_pidfd(true) + .spawn() + .expect("executing 'sleep' failed"); + + let fd = child.take_pidfd().unwrap(); + drop(child); + + assert_matches!(fd.try_wait(), Ok(None)); + fd.kill().expect("kill failed"); + fd.kill().expect("sending kill twice failed"); + let status = fd.wait().expect("1st wait failed"); + assert_eq!(status.signal(), Some(libc::SIGKILL)); + + // Trying to wait again for a reaped child is safe since there's no pid-recycling race. + // But doing so will return an error. + let res = fd.wait(); + assert_matches!(res, Err(e) if e.raw_os_error() == Some(libc::ECHILD)); + + // Ditto for additional attempts to kill an already-dead child. + let res = fd.kill(); + assert_matches!(res, Err(e) if e.raw_os_error() == Some(libc::ESRCH)); +} + +fn probe_pidfd_support() -> bool { + // pidfds require the pidfd_open syscall + let our_pid = crate::process::id(); + let pidfd = unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) }; + if pidfd >= 0 { + unsafe { libc::close(pidfd as RawFd) }; + true + } else { + false + } +} diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 735ed96bc7b16..b370f06e92baf 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -20,6 +20,8 @@ pub mod io; pub mod kernel_copy; #[cfg(target_os = "l4re")] mod l4re; +#[cfg(target_os = "linux")] +pub mod linux; #[cfg(not(target_os = "l4re"))] pub mod net; #[cfg(target_os = "l4re")] diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 72bda90a9ba71..479f18876e30d 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -7,9 +7,7 @@ use crate::sys::cvt; use crate::sys::process::process_common::*; #[cfg(target_os = "linux")] -use crate::os::linux::process::PidFd; -#[cfg(target_os = "linux")] -use crate::os::unix::io::AsRawFd; +use crate::sys::pal::unix::linux::pidfd::PidFd; #[cfg(target_os = "vxworks")] use libc::RTP_ID as pid_t; @@ -815,16 +813,7 @@ impl Process { #[cfg(target_os = "linux")] if let Some(pid_fd) = self.pidfd.as_ref() { // pidfd_send_signal predates pidfd_open. so if we were able to get an fd then sending signals will work too - return cvt(unsafe { - libc::syscall( - libc::SYS_pidfd_send_signal, - pid_fd.as_raw_fd(), - libc::SIGKILL, - crate::ptr::null::<()>(), - 0, - ) - }) - .map(drop); + return pid_fd.kill(); } cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) } @@ -836,12 +825,7 @@ impl Process { } #[cfg(target_os = "linux")] if let Some(pid_fd) = self.pidfd.as_ref() { - let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; - - cvt_r(|| unsafe { - libc::waitid(libc::P_PIDFD, pid_fd.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) - })?; - let status = ExitStatus::from_waitid_siginfo(siginfo); + let status = pid_fd.wait()?; self.status = Some(status); return Ok(status); } @@ -857,22 +841,11 @@ impl Process { } #[cfg(target_os = "linux")] if let Some(pid_fd) = self.pidfd.as_ref() { - let mut siginfo: libc::siginfo_t = unsafe { crate::mem::zeroed() }; - - cvt(unsafe { - libc::waitid( - libc::P_PIDFD, - pid_fd.as_raw_fd() as u32, - &mut siginfo, - libc::WEXITED | libc::WNOHANG, - ) - })?; - if unsafe { siginfo.si_pid() } == 0 { - return Ok(None); + let status = pid_fd.try_wait()?; + if let Some(status) = status { + self.status = Some(status) } - let status = ExitStatus::from_waitid_siginfo(siginfo); - self.status = Some(status); - return Ok(Some(status)); + return Ok(status); } let mut status = 0 as c_int; let pid = cvt(unsafe { libc::waitpid(self.pid, &mut status, libc::WNOHANG) })?; @@ -1105,20 +1078,33 @@ impl ExitStatusError { } #[cfg(target_os = "linux")] -#[unstable(feature = "linux_pidfd", issue = "82971")] -impl crate::os::linux::process::ChildExt for crate::process::Child { - fn pidfd(&self) -> io::Result<&PidFd> { - self.handle - .pidfd - .as_ref() - .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) - } +mod linux_child_ext { + + use crate::io; + use crate::mem; + use crate::os::linux::process as os; + use crate::sys::pal::unix::linux::pidfd as imp; + use crate::sys::pal::unix::ErrorKind; + use crate::sys_common::FromInner; + + #[unstable(feature = "linux_pidfd", issue = "82971")] + impl crate::os::linux::process::ChildExt for crate::process::Child { + fn pidfd(&self) -> io::Result<&os::PidFd> { + self.handle + .pidfd + .as_ref() + // SAFETY: The os type is a transparent wrapper, therefore we can transmute references + .map(|fd| unsafe { mem::transmute::<&imp::PidFd, &os::PidFd>(fd) }) + .ok_or_else(|| io::Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) + } - fn take_pidfd(&mut self) -> io::Result { - self.handle - .pidfd - .take() - .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) + fn take_pidfd(&mut self) -> io::Result { + self.handle + .pidfd + .take() + .map(|fd| >::from_inner(fd)) + .ok_or_else(|| io::Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) + } } } diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs index 0a6c6ec19fc7e..e5e1f956bc351 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs @@ -60,57 +60,3 @@ fn test_command_fork_no_unwind() { || signal == libc::SIGSEGV ); } - -#[test] -#[cfg(target_os = "linux")] // pidfds are a linux-specific concept -fn test_command_pidfd() { - use crate::assert_matches::assert_matches; - use crate::os::fd::{AsRawFd, RawFd}; - use crate::os::linux::process::{ChildExt, CommandExt}; - use crate::process::Command; - - // pidfds require the pidfd_open syscall - let our_pid = crate::process::id(); - let pidfd = unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) }; - let pidfd_open_available = if pidfd >= 0 { - unsafe { libc::close(pidfd as RawFd) }; - true - } else { - false - }; - - // always exercise creation attempts - let mut child = Command::new("false").create_pidfd(true).spawn().unwrap(); - - // but only check if we know that the kernel supports pidfds. - // We don't assert the precise value, since the standard library - // might have opened other file descriptors before our code runs. - if pidfd_open_available { - assert!(child.pidfd().is_ok()); - } - if let Ok(pidfd) = child.pidfd() { - let flags = super::cvt(unsafe { libc::fcntl(pidfd.as_raw_fd(), libc::F_GETFD) }).unwrap(); - assert!(flags & libc::FD_CLOEXEC != 0); - } - let status = child.wait().expect("error waiting on pidfd"); - assert_eq!(status.code(), Some(1)); - - let mut child = Command::new("sleep").arg("1000").create_pidfd(true).spawn().unwrap(); - assert_matches!(child.try_wait(), Ok(None)); - child.kill().expect("failed to kill child"); - let status = child.wait().expect("error waiting on pidfd"); - assert_eq!(status.signal(), Some(libc::SIGKILL)); - - let _ = Command::new("echo") - .create_pidfd(false) - .spawn() - .unwrap() - .pidfd() - .expect_err("pidfd should not have been created when create_pid(false) is set"); - - let _ = Command::new("echo") - .spawn() - .unwrap() - .pidfd() - .expect_err("pidfd should not have been created"); -} From 210400a1bea715c2b1463349d79aac661429519a Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 13 Jun 2024 23:55:03 +0200 Subject: [PATCH 03/12] to extract a pidfd we must consume the child As long as a pidfd is on a child it can be safely reaped. Taking it would mean the child would now have to be awaited through its pid, but could also be awaited through the pidfd. This could then suffer from a recycling race. --- library/std/src/os/linux/process.rs | 22 +++++++++++++------ .../std/src/sys/pal/unix/linux/pidfd/tests.rs | 5 ++--- .../src/sys/pal/unix/process/process_unix.rs | 4 ++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index cf0c679640d3c..e9d436bc355cd 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -20,7 +20,7 @@ struct InnerPidFd; /// /// A `PidFd` can be obtained by setting the corresponding option on [`Command`] /// with [`create_pidfd`]. Subsequently, the created pidfd can be retrieved -/// from the [`Child`] by calling [`pidfd`] or [`take_pidfd`]. +/// from the [`Child`] by calling [`pidfd`] or [`into_pidfd`]. /// /// Example: /// ```no_run @@ -34,7 +34,7 @@ struct InnerPidFd; /// .expect("Failed to spawn child"); /// /// let pidfd = child -/// .take_pidfd() +/// .into_pidfd() /// .expect("Failed to retrieve pidfd"); /// /// // The file descriptor will be closed when `pidfd` is dropped. @@ -45,7 +45,7 @@ struct InnerPidFd; /// [`create_pidfd`]: CommandExt::create_pidfd /// [`Child`]: process::Child /// [`pidfd`]: fn@ChildExt::pidfd -/// [`take_pidfd`]: ChildExt::take_pidfd +/// [`into_pidfd`]: ChildExt::into_pidfd /// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html #[derive(Debug)] #[repr(transparent)] @@ -160,18 +160,26 @@ pub trait ChildExt: Sealed { /// [`Child`]: process::Child fn pidfd(&self) -> Result<&PidFd>; - /// Takes ownership of the [`PidFd`] created for this [`Child`], if available. + /// Returns the [`PidFd`] created for this [`Child`], if available. + /// Otherwise self is returned. /// /// A pidfd will only be available if its creation was requested with /// [`create_pidfd`] when the corresponding [`Command`] was created. /// + /// Taking ownership of the PidFd consumes the Child to avoid pid reuse + /// races. Use [`pidfd`] and [`BorrowedFd::try_clone_to_owned`] if + /// you don't want to disassemble the Child yet. + /// /// Even if requested, a pidfd may not be available due to an older /// version of Linux being in use, or if some other error occurred. /// /// [`Command`]: process::Command /// [`create_pidfd`]: CommandExt::create_pidfd + /// [`pidfd`]: ChildExt::pidfd /// [`Child`]: process::Child - fn take_pidfd(&mut self) -> Result; + fn into_pidfd(self) -> crate::result::Result + where + Self: Sized; } /// Os-specific extensions for [`Command`] @@ -182,7 +190,7 @@ pub trait CommandExt: Sealed { /// spawned by this [`Command`]. /// By default, no pidfd will be created. /// - /// The pidfd can be retrieved from the child with [`pidfd`] or [`take_pidfd`]. + /// The pidfd can be retrieved from the child with [`pidfd`] or [`into_pidfd`]. /// /// A pidfd will only be created if it is possible to do so /// in a guaranteed race-free manner. Otherwise, [`pidfd`] will return an error. @@ -196,7 +204,7 @@ pub trait CommandExt: Sealed { /// [`Command`]: process::Command /// [`Child`]: process::Child /// [`pidfd`]: fn@ChildExt::pidfd - /// [`take_pidfd`]: ChildExt::take_pidfd + /// [`into_pidfd`]: ChildExt::into_pidfd fn create_pidfd(&mut self, val: bool) -> &mut process::Command; } diff --git a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs index 42b3df6299114..6d9532f2ef1ff 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd/tests.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd/tests.rs @@ -50,14 +50,13 @@ fn test_pidfd() { return; } - let mut child = Command::new("sleep") + let child = Command::new("sleep") .arg("1000") .create_pidfd(true) .spawn() .expect("executing 'sleep' failed"); - let fd = child.take_pidfd().unwrap(); - drop(child); + let fd = child.into_pidfd().unwrap(); assert_matches!(fd.try_wait(), Ok(None)); fd.kill().expect("kill failed"); diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 479f18876e30d..32382d9a50cf4 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -1098,12 +1098,12 @@ mod linux_child_ext { .ok_or_else(|| io::Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) } - fn take_pidfd(&mut self) -> io::Result { + fn into_pidfd(mut self) -> Result { self.handle .pidfd .take() .map(|fd| >::from_inner(fd)) - .ok_or_else(|| io::Error::new(ErrorKind::Uncategorized, "No pidfd was created.")) + .ok_or_else(|| self) } } } From c4ddc863ae168dcba9afa3fe4cc83a4f4a78359f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 17 Jun 2024 19:19:41 -0500 Subject: [PATCH 04/12] Print the tested value in int_log tests --- library/core/tests/num/int_log.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs index a1edb1a518632..2320a7acc35ac 100644 --- a/library/core/tests/num/int_log.rs +++ b/library/core/tests/num/int_log.rs @@ -24,15 +24,15 @@ fn checked_ilog() { #[cfg(not(miri))] // Miri is too slow for i in i16::MIN..=0 { - assert_eq!(i.checked_ilog(4), None); + assert_eq!(i.checked_ilog(4), None, "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=i16::MAX { - assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32)); + assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32), "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=u16::MAX { - assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32)); + assert_eq!(i.checked_ilog(13), Some((i as f32).log(13.0) as u32), "checking {i}"); } } @@ -49,30 +49,30 @@ fn checked_ilog2() { assert_eq!(0i16.checked_ilog2(), None); for i in 1..=u8::MAX { - assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32)); + assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=u16::MAX { // Guard against Android's imprecise f32::ilog2 implementation. if i != 8192 && i != 32768 { - assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32)); + assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}"); } } for i in i8::MIN..=0 { - assert_eq!(i.checked_ilog2(), None); + assert_eq!(i.checked_ilog2(), None, "checking {i}"); } for i in 1..=i8::MAX { - assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32)); + assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in i16::MIN..=0 { - assert_eq!(i.checked_ilog2(), None); + assert_eq!(i.checked_ilog2(), None, "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=i16::MAX { // Guard against Android's imprecise f32::ilog2 implementation. if i != 8192 { - assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32)); + assert_eq!(i.checked_ilog2(), Some((i as f32).log2() as u32), "checking {i}"); } } } @@ -95,19 +95,19 @@ fn checked_ilog10() { #[cfg(not(miri))] // Miri is too slow for i in i16::MIN..=0 { - assert_eq!(i.checked_ilog10(), None); + assert_eq!(i.checked_ilog10(), None, "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=i16::MAX { - assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32)); + assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32), "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=u16::MAX { - assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32)); + assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32), "checking {i}"); } #[cfg(not(miri))] // Miri is too slow for i in 1..=100_000u32 { - assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32)); + assert_eq!(i.checked_ilog10(), Some((i as f32).log10() as u32), "checking {i}"); } } From d51b4462ec2d4a7d8d647afcf86353ca4e971b70 Mon Sep 17 00:00:00 2001 From: ardi Date: Fri, 7 Jun 2024 16:25:43 +0200 Subject: [PATCH 05/12] Improve conflict marker recovery --- .../rustc_parse/src/parser/diagnostics.rs | 51 ++++++++++++++----- tests/ui/parser/diff-markers/enum-2.stderr | 19 ++++--- tests/ui/parser/diff-markers/enum.stderr | 17 ++++--- tests/ui/parser/diff-markers/fn-arg.stderr | 17 ++++--- .../parser/diff-markers/item-with-attr.stderr | 17 ++++--- tests/ui/parser/diff-markers/item.stderr | 17 ++++--- tests/ui/parser/diff-markers/statement.stderr | 17 ++++--- .../ui/parser/diff-markers/struct-expr.stderr | 17 ++++--- tests/ui/parser/diff-markers/struct.stderr | 17 ++++--- .../ui/parser/diff-markers/trait-item.stderr | 17 ++++--- .../parser/diff-markers/tuple-struct.stderr | 17 ++++--- .../unclosed-delims-in-macro.stderr | 17 ++++--- .../ui/parser/diff-markers/unclosed-delims.rs | 10 ++-- .../diff-markers/unclosed-delims.stderr | 17 ++++--- .../parser/diff-markers/use-statement.stderr | 17 ++++--- 15 files changed, 189 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c1aac84bcaec7..e4630bbceb9bb 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2990,14 +2990,18 @@ impl<'a> Parser<'a> { } pub(crate) fn err_vcs_conflict_marker(&mut self) -> PResult<'a, ()> { + // <<<<<<< let Some(start) = self.conflict_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) else { return Ok(()); }; let mut spans = Vec::with_capacity(3); spans.push(start); + // ||||||| let mut middlediff3 = None; + // ======= let mut middle = None; + // >>>>>>> let mut end = None; loop { if self.token.kind == TokenKind::Eof { @@ -3018,29 +3022,50 @@ impl<'a> Parser<'a> { } self.bump(); } + let mut err = self.dcx().struct_span_err(spans, "encountered diff marker"); - err.span_label(start, "after this is the code before the merge"); - if let Some(middle) = middlediff3 { - err.span_label(middle, ""); - } + match middlediff3 { + // We're using diff3 + Some(middlediff3) => { + err.span_label( + start, + "between this marker and `|||||||` is the code that we're merging into", + ); + err.span_label(middlediff3, "between this marker and `=======` is the base code (what the two refs diverged from)"); + } + None => { + err.span_label( + start, + "between this marker and `=======` is the code that we're merging into", + ); + } + }; + if let Some(middle) = middle { - err.span_label(middle, ""); + err.span_label(middle, "between this marker and `>>>>>>>` is the incoming code"); } if let Some(end) = end { - err.span_label(end, "above this are the incoming code changes"); + err.span_label(end, "this marker concludes the conflict region"); } - err.help( - "if you're having merge conflicts after pulling new code, the top section is the code \ - you already had and the bottom section is the remote code", + err.note( + "conflict markers indicate that a merge was started but could not be completed due \ + to merge conflicts\n\ + to resolve a conflict, keep only the code you want and then delete the lines \ + containing conflict markers", ); err.help( - "if you're in the middle of a rebase, the top section is the code being rebased onto \ - and the bottom section is the code coming from the current commit being rebased", + "if you're having merge conflicts after pulling new code:\n\ + the top section is the code you already had and the bottom section is the remote code\n\ + if you're in the middle of a rebase:\n\ + the top section is the code being rebased onto and the bottom section is the code \ + coming from the current commit being rebased", ); + err.note( - "for an explanation on these markers from the `git` documentation, visit \ - ", + "for an explanation on these markers from the `git` documentation:\n\ + visit ", ); + Err(err) } diff --git a/tests/ui/parser/diff-markers/enum-2.stderr b/tests/ui/parser/diff-markers/enum-2.stderr index 20e551c2f959a..b76cf5d5a01ee 100644 --- a/tests/ui/parser/diff-markers/enum-2.stderr +++ b/tests/ui/parser/diff-markers/enum-2.stderr @@ -2,20 +2,25 @@ error: encountered diff marker --> $DIR/enum-2.rs:3:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `|||||||` is the code that we're merging into LL | x: u8, LL | ||||||| - | ------- + | ------- between this marker and `=======` is the base code (what the two refs diverged from) LL | z: (), LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | y: i8, LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/enum.stderr b/tests/ui/parser/diff-markers/enum.stderr index be94331dce528..0ce473bc70232 100644 --- a/tests/ui/parser/diff-markers/enum.stderr +++ b/tests/ui/parser/diff-markers/enum.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/enum.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | Foo(u8), LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | Bar(i8), LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/fn-arg.stderr b/tests/ui/parser/diff-markers/fn-arg.stderr index aabcb826c1283..24521ffa62623 100644 --- a/tests/ui/parser/diff-markers/fn-arg.stderr +++ b/tests/ui/parser/diff-markers/fn-arg.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/fn-arg.rs:3:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | x: u8, LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | x: i8, LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/item-with-attr.stderr b/tests/ui/parser/diff-markers/item-with-attr.stderr index eefb2792e90bc..432673cd5518b 100644 --- a/tests/ui/parser/diff-markers/item-with-attr.stderr +++ b/tests/ui/parser/diff-markers/item-with-attr.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/item-with-attr.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | fn foo() {} LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | fn bar() {} LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/item.stderr b/tests/ui/parser/diff-markers/item.stderr index a3092ebfcfd36..180c74e5d6967 100644 --- a/tests/ui/parser/diff-markers/item.stderr +++ b/tests/ui/parser/diff-markers/item.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/item.rs:1:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | fn foo() {} LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | fn bar() {} LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/statement.stderr b/tests/ui/parser/diff-markers/statement.stderr index c6c6cae876594..6dccce4a48eee 100644 --- a/tests/ui/parser/diff-markers/statement.stderr +++ b/tests/ui/parser/diff-markers/statement.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/statement.rs:10:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | S::foo(); LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | S::bar(); LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/struct-expr.stderr b/tests/ui/parser/diff-markers/struct-expr.stderr index bdea8c841c638..3733cdd349644 100644 --- a/tests/ui/parser/diff-markers/struct-expr.stderr +++ b/tests/ui/parser/diff-markers/struct-expr.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/struct-expr.rs:6:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | x: 42, LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | x: 0, LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/struct.stderr b/tests/ui/parser/diff-markers/struct.stderr index 749941290cb82..44f8346613e68 100644 --- a/tests/ui/parser/diff-markers/struct.stderr +++ b/tests/ui/parser/diff-markers/struct.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/struct.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | x: u8, LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | x: i8, LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/trait-item.stderr b/tests/ui/parser/diff-markers/trait-item.stderr index f01bbe8ba0340..4361542c7743b 100644 --- a/tests/ui/parser/diff-markers/trait-item.stderr +++ b/tests/ui/parser/diff-markers/trait-item.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/trait-item.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | fn foo() {} LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | fn bar() {} LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/tuple-struct.stderr b/tests/ui/parser/diff-markers/tuple-struct.stderr index 8dae123c96dca..7fda24ba48532 100644 --- a/tests/ui/parser/diff-markers/tuple-struct.stderr +++ b/tests/ui/parser/diff-markers/tuple-struct.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/tuple-struct.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | u8, LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | i8, LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr index 6995b8e6f2370..927821ddfaedb 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/unclosed-delims-in-macro.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into ... LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | () { // LL | >>>>>>> 7a4f13c blah blah blah - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/unclosed-delims.rs b/tests/ui/parser/diff-markers/unclosed-delims.rs index 653a605c28c60..7d400c3827bb6 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.rs +++ b/tests/ui/parser/diff-markers/unclosed-delims.rs @@ -2,13 +2,17 @@ mod tests { #[test] <<<<<<< HEAD //~^ ERROR encountered diff marker -//~| NOTE after this is the code before the merge +//~| NOTE between this marker and `=======` + +//~| NOTE conflict markers indicate that +//~| HELP if you're having merge conflicts //~| NOTE for an explanation on these markers + fn test1() { ======= -//~^ NOTE +//~^ NOTE between this marker and `>>>>>>>` fn test2() { >>>>>>> 7a4f13c blah blah blah -//~^ NOTE above this are the incoming code changes +//~^ NOTE this marker concludes the conflict region } } diff --git a/tests/ui/parser/diff-markers/unclosed-delims.stderr b/tests/ui/parser/diff-markers/unclosed-delims.stderr index d4636150e66b7..1eab96442b4f2 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/unclosed-delims.rs:3:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into ... LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code ... LL | >>>>>>> 7a4f13c blah blah blah - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error diff --git a/tests/ui/parser/diff-markers/use-statement.stderr b/tests/ui/parser/diff-markers/use-statement.stderr index 6d376166a7f7a..3eac7bebb5af1 100644 --- a/tests/ui/parser/diff-markers/use-statement.stderr +++ b/tests/ui/parser/diff-markers/use-statement.stderr @@ -2,17 +2,22 @@ error: encountered diff marker --> $DIR/use-statement.rs:2:1 | LL | <<<<<<< HEAD - | ^^^^^^^ after this is the code before the merge + | ^^^^^^^ between this marker and `=======` is the code that we're merging into LL | bar, LL | ======= - | ------- + | ------- between this marker and `>>>>>>>` is the incoming code LL | baz, LL | >>>>>>> branch - | ^^^^^^^ above this are the incoming code changes + | ^^^^^^^ this marker concludes the conflict region | - = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code - = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased - = note: for an explanation on these markers from the `git` documentation, visit + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you're having merge conflicts after pulling new code: + the top section is the code you already had and the bottom section is the remote code + if you're in the middle of a rebase: + the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation: + visit error: aborting due to 1 previous error From 9f6371236f516ac2a883eb8707839ab80fc7f9f7 Mon Sep 17 00:00:00 2001 From: ardi Date: Mon, 10 Jun 2024 10:16:51 +0200 Subject: [PATCH 06/12] make this comment correct --- compiler/rustc_parse/src/parser/diagnostics.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index e4630bbceb9bb..db23ce6fb7b39 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2958,9 +2958,10 @@ impl<'a> Parser<'a> { /// This checks if this is a conflict marker, depending of the parameter passed. /// - /// * `>>>>>` - /// * `=====` - /// * `<<<<<` + /// * `<<<<<<<` + /// * `|||||||` + /// * `=======` + /// * `>>>>>>>` /// pub(super) fn is_vcs_conflict_marker( &mut self, From b6d20d1a1fcd37dcc47c4f2839d80bea4b5cdd85 Mon Sep 17 00:00:00 2001 From: Sayantan Chakraborty <142906350+sayantn@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:03:14 +0530 Subject: [PATCH 07/12] Add the target-features --- compiler/rustc_target/src/target_features.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d9812540e497d..017fd3072fdb7 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -208,6 +208,11 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("avx512vnni", Unstable(sym::avx512_target_feature)), ("avx512vp2intersect", Unstable(sym::avx512_target_feature)), ("avx512vpopcntdq", Unstable(sym::avx512_target_feature)), + ("avxifma", Unstable(sym::avx512_target_feature)), + ("avxneconvert", Unstable(sym::avx512_target_feature)), + ("avxvnni", Unstable(sym::avx512_target_feature)), + ("avxvnniint16", Unstable(sym::avx512_target_feature)), + ("avxvnniint8", Unstable(sym::avx512_target_feature)), ("bmi1", Stable), ("bmi2", Stable), ("cmpxchg16b", Stable), From 1e1b3fcadafdb28f25f7e19bd05652bd8aa98084 Mon Sep 17 00:00:00 2001 From: sayantn Date: Wed, 19 Jun 2024 00:51:45 +0530 Subject: [PATCH 08/12] Fix stderr cases --- tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index b3d0046fc1788..cc63466585a6a 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, and `bulk-memory` and 186 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, and `avxvnniint8` and 191 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index d2026a68450eb..8a99ace75d852 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 50d1efa3e2aa3c1e91f9f7869225897800ce1cce Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Jun 2024 12:33:25 -0400 Subject: [PATCH 09/12] Add a test demonstrating the problem --- tests/ui/macros/auxiliary/expr_2021_implicit.rs | 9 +++++++++ tests/ui/macros/expr_2021_implicit_in_2024.rs | 10 ++++++++++ tests/ui/macros/expr_2021_implicit_in_2024.stderr | 10 ++++++++++ 3 files changed, 29 insertions(+) create mode 100644 tests/ui/macros/auxiliary/expr_2021_implicit.rs create mode 100644 tests/ui/macros/expr_2021_implicit_in_2024.rs create mode 100644 tests/ui/macros/expr_2021_implicit_in_2024.stderr diff --git a/tests/ui/macros/auxiliary/expr_2021_implicit.rs b/tests/ui/macros/auxiliary/expr_2021_implicit.rs new file mode 100644 index 0000000000000..61762e41dee0c --- /dev/null +++ b/tests/ui/macros/auxiliary/expr_2021_implicit.rs @@ -0,0 +1,9 @@ +//@ edition:2021 + +#[macro_export] +macro_rules! m { + ($expr:expr) => { + compile_error!("did not expect an expression to be parsed"); + }; + (const { }) => {}; +} diff --git a/tests/ui/macros/expr_2021_implicit_in_2024.rs b/tests/ui/macros/expr_2021_implicit_in_2024.rs new file mode 100644 index 0000000000000..d612c03650df6 --- /dev/null +++ b/tests/ui/macros/expr_2021_implicit_in_2024.rs @@ -0,0 +1,10 @@ +//@ compile-flags: --edition=2024 -Zunstable-options +//@ aux-build:expr_2021_implicit.rs + +extern crate expr_2021_implicit; + +// Makes sure that a `:expr` fragment matcher defined in a edition 2021 crate +// still parses like an `expr_2021` fragment matcher in a 2024 user crate. +expr_2021_implicit::m!(const {}); + +fn main() {} diff --git a/tests/ui/macros/expr_2021_implicit_in_2024.stderr b/tests/ui/macros/expr_2021_implicit_in_2024.stderr new file mode 100644 index 0000000000000..962d572ca07e4 --- /dev/null +++ b/tests/ui/macros/expr_2021_implicit_in_2024.stderr @@ -0,0 +1,10 @@ +error: did not expect an expression to be parsed + --> $DIR/expr_2021_implicit_in_2024.rs:8:1 + | +LL | expr_2021_implicit::m!(const {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `expr_2021_implicit::m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + From 3e8898a4e1afd44f09a5a80d466cd5b1a87e0fa8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Jun 2024 12:21:09 -0400 Subject: [PATCH 10/12] Allow naming expr_2021 in all editions --- compiler/rustc_ast/src/token.rs | 19 ++++++++++---- compiler/rustc_expand/src/mbe/macro_rules.rs | 4 ++- compiler/rustc_expand/src/mbe/quoted.rs | 3 ++- .../rustc_parse/src/parser/nonterminal.rs | 5 ++-- tests/ui/macros/expr_2021_implicit_in_2024.rs | 2 ++ .../macros/expr_2021_implicit_in_2024.stderr | 10 ------- tests/ui/macros/expr_2021_old_edition.rs | 13 ---------- tests/ui/macros/expr_2021_old_edition.stderr | 26 ------------------- 8 files changed, 23 insertions(+), 59 deletions(-) delete mode 100644 tests/ui/macros/expr_2021_implicit_in_2024.stderr delete mode 100644 tests/ui/macros/expr_2021_old_edition.rs delete mode 100644 tests/ui/macros/expr_2021_old_edition.stderr diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 109c401bb6a20..9c8b2451b7986 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -884,7 +884,11 @@ pub enum NonterminalKind { PatWithOr, Expr, /// Matches an expression using the rules from edition 2021 and earlier. - Expr2021, + Expr2021 { + /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the + /// edition of the span. This is used for diagnostics AND feature gating. + inferred: bool, + }, Ty, Ident, Lifetime, @@ -913,8 +917,13 @@ impl NonterminalKind { Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, - sym::expr => NonterminalKind::Expr, - sym::expr_2021 if edition().at_least_rust_2021() => NonterminalKind::Expr2021, + sym::expr => match edition() { + Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => { + NonterminalKind::Expr2021 { inferred: true } + } + Edition::Edition2024 => NonterminalKind::Expr, + }, + sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false }, sym::ty => NonterminalKind::Ty, sym::ident => NonterminalKind::Ident, sym::lifetime => NonterminalKind::Lifetime, @@ -933,8 +942,8 @@ impl NonterminalKind { NonterminalKind::Stmt => sym::stmt, NonterminalKind::PatParam { inferred: false } => sym::pat_param, NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat, - NonterminalKind::Expr => sym::expr, - NonterminalKind::Expr2021 => sym::expr_2021, + NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr, + NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021, NonterminalKind::Ty => sym::ty, NonterminalKind::Ident => sym::ident, NonterminalKind::Lifetime => sym::lifetime, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 49b1f5ce0e3ea..0050ff10539a8 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1292,7 +1292,9 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { // maintain IsInFollow::Yes } - NonterminalKind::Stmt | NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NonterminalKind::Stmt + | NonterminalKind::Expr + | NonterminalKind::Expr2021 { inferred: _ } => { const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; match tok { TokenTree::Token(token) => match token.kind { diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 74f78c0ef7857..fdf187438d3d7 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -113,7 +113,8 @@ pub(super) fn parse( ); token::NonterminalKind::Ident }); - if kind == token::NonterminalKind::Expr2021 + if kind + == (token::NonterminalKind::Expr2021 { inferred: false }) && !features.expr_fragment_specifier_2024 { rustc_session::parse::feature_err( diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index a0b704aeea5fb..59f6eff07b320 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -36,7 +36,7 @@ impl<'a> Parser<'a> { } match kind { - NonterminalKind::Expr2021 => { + NonterminalKind::Expr2021 { inferred: _ } => { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) @@ -47,7 +47,6 @@ impl<'a> Parser<'a> { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) - && (!token.is_keyword(kw::Const) || token.span.edition().at_least_rust_2024()) } NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(), @@ -149,7 +148,7 @@ impl<'a> Parser<'a> { })?) } - NonterminalKind::Expr | NonterminalKind::Expr2021 => { + NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => { NtExpr(self.parse_expr_force_collect()?) } NonterminalKind::Literal => { diff --git a/tests/ui/macros/expr_2021_implicit_in_2024.rs b/tests/ui/macros/expr_2021_implicit_in_2024.rs index d612c03650df6..b3f7a31a802dd 100644 --- a/tests/ui/macros/expr_2021_implicit_in_2024.rs +++ b/tests/ui/macros/expr_2021_implicit_in_2024.rs @@ -1,6 +1,8 @@ //@ compile-flags: --edition=2024 -Zunstable-options //@ aux-build:expr_2021_implicit.rs +//@ check-pass + extern crate expr_2021_implicit; // Makes sure that a `:expr` fragment matcher defined in a edition 2021 crate diff --git a/tests/ui/macros/expr_2021_implicit_in_2024.stderr b/tests/ui/macros/expr_2021_implicit_in_2024.stderr deleted file mode 100644 index 962d572ca07e4..0000000000000 --- a/tests/ui/macros/expr_2021_implicit_in_2024.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: did not expect an expression to be parsed - --> $DIR/expr_2021_implicit_in_2024.rs:8:1 - | -LL | expr_2021_implicit::m!(const {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `expr_2021_implicit::m` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - diff --git a/tests/ui/macros/expr_2021_old_edition.rs b/tests/ui/macros/expr_2021_old_edition.rs deleted file mode 100644 index a771126610686..0000000000000 --- a/tests/ui/macros/expr_2021_old_edition.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ compile-flags: --edition=2018 - -// This test ensures that expr_2021 is not allowed on pre-2021 editions - -macro_rules! m { - ($e:expr_2021) => { //~ ERROR: invalid fragment specifier `expr_2021` - $e - }; -} - -fn main() { - m!(()); //~ ERROR: no rules expected the token `(` -} diff --git a/tests/ui/macros/expr_2021_old_edition.stderr b/tests/ui/macros/expr_2021_old_edition.stderr deleted file mode 100644 index bffa8a1ca1759..0000000000000 --- a/tests/ui/macros/expr_2021_old_edition.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: invalid fragment specifier `expr_2021` - --> $DIR/expr_2021_old_edition.rs:6:6 - | -LL | ($e:expr_2021) => { - | ^^^^^^^^^^^^ - | - = help: fragment specifier `expr_2021` requires Rust 2021 or later - valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis` - -error: no rules expected the token `(` - --> $DIR/expr_2021_old_edition.rs:12:8 - | -LL | macro_rules! m { - | -------------- when calling this macro -... -LL | m!(()); - | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$e:ident` - --> $DIR/expr_2021_old_edition.rs:6:6 - | -LL | ($e:expr_2021) => { - | ^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - From a656bb6eb26d9ba63eac5f619b885230b97e8a4a Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Wed, 19 Jun 2024 11:57:03 -0700 Subject: [PATCH 11/12] Specify target for inaccessible-temp-dir rmake test --- tests/run-make/inaccessible-temp-dir/rmake.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/run-make/inaccessible-temp-dir/rmake.rs b/tests/run-make/inaccessible-temp-dir/rmake.rs index be24e47b6decc..c6bfae4cc01db 100644 --- a/tests/run-make/inaccessible-temp-dir/rmake.rs +++ b/tests/run-make/inaccessible-temp-dir/rmake.rs @@ -19,7 +19,7 @@ // Reason: `set_readonly` has no effect on directories // and does not prevent modification. -use run_make_support::{fs_wrapper, rustc, test_while_readonly}; +use run_make_support::{fs_wrapper, rustc, target, test_while_readonly}; fn main() { // Create an inaccessible directory. @@ -28,6 +28,7 @@ fn main() { // Run rustc with `-Z temps-dir` set to a directory *inside* the inaccessible one, // so that it can't create `tmp`. rustc() + .target(&target()) .input("program.rs") .arg("-Ztemps-dir=inaccessible/tmp") .run_fail() From 3e59f0c3c5b4e23057dcfbe9da784164e2410a78 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Jun 2024 19:50:57 -0400 Subject: [PATCH 12/12] StaticForeignItem and StaticItem are the same --- compiler/rustc_ast/src/ast.rs | 34 +------------------ compiler/rustc_ast/src/mut_visit.rs | 7 +--- compiler/rustc_ast/src/visit.rs | 7 +--- compiler/rustc_ast_lowering/src/item.rs | 7 +--- .../rustc_ast_passes/src/ast_validation.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/item.rs | 7 +--- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 7 +--- .../clippy/clippy_utils/src/ast_utils.rs | 4 +-- 9 files changed, 10 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 71932f02017ca..30c54ef2d3c41 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3184,38 +3184,6 @@ pub struct StaticItem { pub expr: Option>, } -/// A static item in `extern` block. -// This struct is identical to StaticItem for now but it's going to have a safety attribute. -#[derive(Clone, Encodable, Decodable, Debug)] -pub struct StaticForeignItem { - pub ty: P, - pub safety: Safety, - pub mutability: Mutability, - pub expr: Option>, -} - -impl From for StaticForeignItem { - fn from(static_item: StaticItem) -> StaticForeignItem { - StaticForeignItem { - ty: static_item.ty, - safety: static_item.safety, - mutability: static_item.mutability, - expr: static_item.expr, - } - } -} - -impl From for StaticItem { - fn from(static_item: StaticForeignItem) -> StaticItem { - StaticItem { - ty: static_item.ty, - safety: static_item.safety, - mutability: static_item.mutability, - expr: static_item.expr, - } - } -} - #[derive(Clone, Encodable, Decodable, Debug)] pub struct ConstItem { pub defaultness: Defaultness, @@ -3430,7 +3398,7 @@ impl TryFrom for AssocItemKind { #[derive(Clone, Encodable, Decodable, Debug)] pub enum ForeignItemKind { /// A foreign static item (`static FOO: u8`). - Static(Box), + Static(Box), /// An foreign function. Fn(Box), /// An foreign type. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 35aa53e978c15..c9d2f5c779bb6 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1310,12 +1310,7 @@ pub fn noop_flat_map_item( impl NoopVisitItemKind for ForeignItemKind { fn noop_visit(&mut self, visitor: &mut impl MutVisitor) { match self { - ForeignItemKind::Static(box StaticForeignItem { - ty, - mutability: _, - expr, - safety: _, - }) => { + ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ed34a44db677f..ce38a67ea69ab 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -672,12 +672,7 @@ impl WalkItemKind for ForeignItemKind { ) -> V::Result { let &Item { id, span, ident, ref vis, .. } = item; match self { - ForeignItemKind::Static(box StaticForeignItem { - ty, - mutability: _, - expr, - safety: _, - }) => { + ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c6c0d9a2e608e..4c7e8c24d32a9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -664,12 +664,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety) } - ForeignItemKind::Static(box StaticForeignItem { - ty, - mutability, - expr: _, - safety, - }) => { + ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => { let ty = self .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); let safety = self.lower_safety(*safety, hir::Safety::Unsafe); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b274a9b9114ac..cad1fc79d7f4f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1232,7 +1232,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_ty_genericless(generics, where_clauses); self.check_foreign_item_ascii_only(fi.ident); } - ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => { + ForeignItemKind::Static(box StaticItem { expr, safety, .. }) => { self.check_foreign_item_safety(fi.span, *safety); self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); self.check_foreign_item_ascii_only(fi.ident); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 49ac5ece337f0..d8382057d3f64 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -37,12 +37,7 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } - ast::ForeignItemKind::Static(box ast::StaticForeignItem { - ty, - mutability, - expr, - safety, - }) => { + ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => { self.print_safety(*safety); self.print_item_const( ident, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3e1ea7b129de0..abb6b51cebd68 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1228,7 +1228,7 @@ impl<'a> Parser<'a> { ident_span: ident.span, const_span, }); - ForeignItemKind::Static(Box::new(StaticForeignItem { + ForeignItemKind::Static(Box::new(StaticItem { ty, mutability: Mutability::Not, expr, diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index fb6e55f2b7bdf..ad1ec4438cc85 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -217,12 +217,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(box StaticForeignItem { - ty: _, - mutability, - expr: _, - safety, - }) => { + ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => { let safety = match safety { ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, ast::Safety::Safe(_) => hir::Safety::Safe, diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index fb43f7d80afff..785d5ed5dbeba 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -449,13 +449,13 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { use ForeignItemKind::*; match (l, r) { ( - Static(box StaticForeignItem { + Static(box StaticItem { ty: lt, mutability: lm, expr: le, safety: ls, }), - Static(box StaticForeignItem { + Static(box StaticItem { ty: rt, mutability: rm, expr: re,