From a9ecd0fa8141e7614ca35d5a4d2fe5c96b1a7890 Mon Sep 17 00:00:00 2001 From: Peter Gervai Date: Thu, 22 Aug 2024 14:29:57 +0200 Subject: [PATCH 001/330] Expand std::os::unix::fs::chown() doc with a warning Include warning about losing setuid/gid when chowning, per POSIX. --- library/std/src/os/unix/fs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index caf6980afd91..f063fa06cc95 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -985,6 +985,10 @@ impl DirBuilderExt for fs::DirBuilder { /// Changing the owner typically requires privileges, such as root or a specific capability. /// Changing the group typically requires either being the owner and a member of the group, or /// having privileges. +/// +/// Be aware that changing owner clears the `suid` and `sgid` permission bits in most cases +/// according to POSIX, usually even if the user is root. The sgid is not cleared when +/// the file is non-group-executable. /// /// If called on a symbolic link, this will change the owner and group of the link target. To /// change the owner and group of the link itself, see [`lchown`]. From 3408dc1eb5f8d744b4d7d5a4392ae6456f036ad9 Mon Sep 17 00:00:00 2001 From: Peter Gervai Date: Thu, 22 Aug 2024 18:38:27 +0200 Subject: [PATCH 002/330] Update chown help with a link and adding cap warning Linked to chown(2) manpage on the web which expands on chown call behaviour. --- library/std/src/os/unix/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index f063fa06cc95..92613d9b004c 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -988,7 +988,8 @@ impl DirBuilderExt for fs::DirBuilder { /// /// Be aware that changing owner clears the `suid` and `sgid` permission bits in most cases /// according to POSIX, usually even if the user is root. The sgid is not cleared when -/// the file is non-group-executable. +/// the file is non-group-executable. See: +/// This call may also clear file capabilities, if there was any. /// /// If called on a symbolic link, this will change the owner and group of the link target. To /// change the owner and group of the link itself, see [`lchown`]. From 528b37a738abf6cb0166fb60701dc2841ad54ebf Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 28 Oct 2024 16:56:22 +0100 Subject: [PATCH 003/330] std: refactor `pthread`-based synchronization The non-trivial code for `pthread_condvar` is duplicated across the thread parking and the `Mutex`/`Condvar` implementations. This PR moves that code into `sys::pal`, which now exposes a non-movable wrapper type for `pthread_mutex_t` and `pthread_condvar_t`. --- library/std/src/sys/pal/teeos/mod.rs | 8 + library/std/src/sys/pal/unix/mod.rs | 1 + library/std/src/sys/pal/unix/sync/condvar.rs | 172 ++++++++++++++ library/std/src/sys/pal/unix/sync/mod.rs | 16 ++ library/std/src/sys/pal/unix/sync/mutex.rs | 133 +++++++++++ library/std/src/sys/sync/condvar/pthread.rs | 218 +++++------------- library/std/src/sys/sync/condvar/sgx.rs | 8 +- library/std/src/sys/sync/mutex/pthread.rs | 157 +++---------- library/std/src/sys/sync/mutex/sgx.rs | 4 +- library/std/src/sys/sync/once_box.rs | 25 +- .../src/sys/sync/thread_parking/pthread.rs | 167 +++----------- 11 files changed, 467 insertions(+), 442 deletions(-) create mode 100644 library/std/src/sys/pal/unix/sync/condvar.rs create mode 100644 library/std/src/sys/pal/unix/sync/mod.rs create mode 100644 library/std/src/sys/pal/unix/sync/mutex.rs diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 60a227afb84e..2bf2e2ceb314 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -27,6 +27,14 @@ pub mod thread; #[path = "../unix/time.rs"] pub mod time; +#[path = "../unix/sync"] +pub mod sync { + mod condvar; + mod mutex; + pub use condvar::Condvar; + pub use mutex::Mutex; +} + use crate::io::ErrorKind; pub fn abort_internal() -> ! { diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 4fe18daa2040..8eaa50d7f81d 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -27,6 +27,7 @@ pub mod pipe; pub mod process; pub mod stack_overflow; pub mod stdio; +pub mod sync; pub mod thread; pub mod thread_parking; pub mod time; diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs new file mode 100644 index 000000000000..13eeba9c8807 --- /dev/null +++ b/library/std/src/sys/pal/unix/sync/condvar.rs @@ -0,0 +1,172 @@ +use super::Mutex; +use crate::cell::UnsafeCell; +use crate::pin::Pin; +#[cfg(not(target_os = "nto"))] +use crate::sys::pal::time::TIMESPEC_MAX; +#[cfg(target_os = "nto")] +use crate::sys::pal::time::TIMESPEC_MAX_CAPPED; +use crate::sys::pal::time::Timespec; +use crate::time::Duration; + +pub struct Condvar { + inner: UnsafeCell, +} + +impl Condvar { + pub fn new() -> Condvar { + Condvar { inner: UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER) } + } + + #[inline] + fn raw(&self) -> *mut libc::pthread_cond_t { + self.inner.get() + } + + /// # Safety + /// `init` must have been called. + #[inline] + pub unsafe fn notify_one(self: Pin<&Self>) { + let r = unsafe { libc::pthread_cond_signal(self.raw()) }; + debug_assert_eq!(r, 0); + } + + /// # Safety + /// `init` must have been called. + #[inline] + pub unsafe fn notify_all(self: Pin<&Self>) { + let r = unsafe { libc::pthread_cond_broadcast(self.raw()) }; + debug_assert_eq!(r, 0); + } + + /// # Safety + /// * `init` must have been called. + /// * `mutex` must be locked by the current thread. + /// * This condition variable may only be used with the same mutex. + #[inline] + pub unsafe fn wait(self: Pin<&Self>, mutex: Pin<&Mutex>) { + let r = unsafe { libc::pthread_cond_wait(self.raw(), mutex.raw()) }; + debug_assert_eq!(r, 0); + } + + /// # Safety + /// * `init` must have been called. + /// * `mutex` must be locked by the current thread. + /// * This condition variable may only be used with the same mutex. + pub unsafe fn wait_timeout(&self, mutex: Pin<&Mutex>, dur: Duration) -> bool { + let mutex = mutex.raw(); + + // OSX implementation of `pthread_cond_timedwait` is buggy + // with super long durations. When duration is greater than + // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` + // in macOS Sierra returns error 316. + // + // This program demonstrates the issue: + // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c + // + // To work around this issue, the timeout is clamped to 1000 years. + #[cfg(target_vendor = "apple")] + let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400)); + + let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur); + + #[cfg(not(target_os = "nto"))] + let timeout = timeout.and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); + + #[cfg(target_os = "nto")] + let timeout = timeout.and_then(|t| t.to_timespec_capped()).unwrap_or(TIMESPEC_MAX_CAPPED); + + let r = unsafe { libc::pthread_cond_timedwait(self.raw(), mutex, &timeout) }; + assert!(r == libc::ETIMEDOUT || r == 0); + r == 0 + } +} + +#[cfg(not(any( + target_os = "android", + target_vendor = "apple", + target_os = "espidf", + target_os = "horizon", + target_os = "l4re", + target_os = "redox", + target_os = "teeos", +)))] +impl Condvar { + pub const PRECISE_TIMEOUT: bool = true; + const CLOCK: libc::clockid_t = libc::CLOCK_MONOTONIC; + + /// # Safety + /// May only be called once. + pub unsafe fn init(self: Pin<&mut Self>) { + use crate::mem::MaybeUninit; + + struct AttrGuard<'a>(pub &'a mut MaybeUninit); + impl Drop for AttrGuard<'_> { + fn drop(&mut self) { + unsafe { + let result = libc::pthread_condattr_destroy(self.0.as_mut_ptr()); + assert_eq!(result, 0); + } + } + } + + unsafe { + let mut attr = MaybeUninit::::uninit(); + let r = libc::pthread_condattr_init(attr.as_mut_ptr()); + assert_eq!(r, 0); + let attr = AttrGuard(&mut attr); + let r = libc::pthread_condattr_setclock(attr.0.as_mut_ptr(), Self::CLOCK); + assert_eq!(r, 0); + let r = libc::pthread_cond_init(self.raw(), attr.0.as_ptr()); + assert_eq!(r, 0); + } + } +} + +// `pthread_condattr_setclock` is unfortunately not supported on these platforms. +#[cfg(any( + target_os = "android", + target_vendor = "apple", + target_os = "espidf", + target_os = "horizon", + target_os = "l4re", + target_os = "redox", + target_os = "teeos", +))] +impl Condvar { + pub const PRECISE_TIMEOUT: bool = false; + const CLOCK: libc::clockid_t = libc::CLOCK_REALTIME; + + /// # Safety + /// May only be called once. + pub unsafe fn init(self: Pin<&mut Self>) { + if cfg!(any(target_os = "espidf", target_os = "horizon", target_os = "teeos")) { + // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet + // So on that platform, init() should always be called. + // + // Similar story for the 3DS (horizon) and for TEEOS. + let r = unsafe { libc::pthread_cond_init(self.raw(), crate::ptr::null()) }; + assert_eq!(r, 0); + } + } +} + +impl !Unpin for Condvar {} + +unsafe impl Sync for Condvar {} +unsafe impl Send for Condvar {} + +impl Drop for Condvar { + #[inline] + fn drop(&mut self) { + let r = unsafe { libc::pthread_cond_destroy(self.raw()) }; + if cfg!(target_os = "dragonfly") { + // On DragonFly pthread_cond_destroy() returns EINVAL if called on + // a condvar that was just initialized with + // libc::PTHREAD_COND_INITIALIZER. Once it is used or + // pthread_cond_init() is called, this behaviour no longer occurs. + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } + } +} diff --git a/library/std/src/sys/pal/unix/sync/mod.rs b/library/std/src/sys/pal/unix/sync/mod.rs new file mode 100644 index 000000000000..b430ff5d8ef5 --- /dev/null +++ b/library/std/src/sys/pal/unix/sync/mod.rs @@ -0,0 +1,16 @@ +#![cfg(not(any( + target_os = "linux", + target_os = "android", + all(target_os = "emscripten", target_feature = "atomics"), + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonfly", + target_os = "fuchsia", +)))] +#![forbid(unsafe_op_in_unsafe_fn)] + +mod condvar; +mod mutex; + +pub use condvar::Condvar; +pub use mutex::Mutex; diff --git a/library/std/src/sys/pal/unix/sync/mutex.rs b/library/std/src/sys/pal/unix/sync/mutex.rs new file mode 100644 index 000000000000..8ffd375bf91b --- /dev/null +++ b/library/std/src/sys/pal/unix/sync/mutex.rs @@ -0,0 +1,133 @@ +use super::super::cvt_nz; +use crate::cell::UnsafeCell; +use crate::io::Error; +use crate::mem::MaybeUninit; +use crate::pin::Pin; + +pub struct Mutex { + inner: UnsafeCell, +} + +impl Mutex { + pub fn new() -> Mutex { + Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) } + } + + pub(super) fn raw(&self) -> *mut libc::pthread_mutex_t { + self.inner.get() + } + + /// # Safety + /// Must only be called once. + pub unsafe fn init(self: Pin<&mut Self>) { + // Issue #33770 + // + // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have + // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you + // try to re-lock it from the same thread when you already hold a lock + // (https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html). + // This is the case even if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL + // (https://github.com/rust-lang/rust/issues/33770#issuecomment-220847521) -- in that + // case, `pthread_mutexattr_settype(PTHREAD_MUTEX_DEFAULT)` will of course be the same + // as setting it to `PTHREAD_MUTEX_NORMAL`, but not setting any mode will result in + // a Mutex where re-locking is UB. + // + // In practice, glibc takes advantage of this undefined behavior to + // implement hardware lock elision, which uses hardware transactional + // memory to avoid acquiring the lock. While a transaction is in + // progress, the lock appears to be unlocked. This isn't a problem for + // other threads since the transactional memory will abort if a conflict + // is detected, however no abort is generated when re-locking from the + // same thread. + // + // Since locking the same mutex twice will result in two aliasing &mut + // references, we instead create the mutex with type + // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to + // re-lock it from the same thread, thus avoiding undefined behavior. + unsafe { + let mut attr = MaybeUninit::::uninit(); + cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); + let attr = AttrGuard(&mut attr); + cvt_nz(libc::pthread_mutexattr_settype( + attr.0.as_mut_ptr(), + libc::PTHREAD_MUTEX_NORMAL, + )) + .unwrap(); + cvt_nz(libc::pthread_mutex_init(self.raw(), attr.0.as_ptr())).unwrap(); + } + } + + /// # Safety + /// * If `init` was not called, reentrant locking causes undefined behaviour. + /// * Destroying a locked mutex causes undefined behaviour. + pub unsafe fn lock(self: Pin<&Self>) { + #[cold] + #[inline(never)] + fn fail(r: i32) -> ! { + let error = Error::from_raw_os_error(r); + panic!("failed to lock mutex: {error}"); + } + + let r = unsafe { libc::pthread_mutex_lock(self.raw()) }; + // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect + // the lock call to never fail. Unfortunately however, some platforms + // (Solaris) do not conform to the standard, and instead always provide + // deadlock detection. How kind of them! Unfortunately that means that + // we need to check the error code here. To save us from UB on other + // less well-behaved platforms in the future, we do it even on "good" + // platforms like macOS. See #120147 for more context. + if r != 0 { + fail(r) + } + } + + /// # Safety + /// * If `init` was not called, reentrant locking causes undefined behaviour. + /// * Destroying a locked mutex causes undefined behaviour. + pub unsafe fn try_lock(self: Pin<&Self>) -> bool { + unsafe { libc::pthread_mutex_trylock(self.raw()) == 0 } + } + + /// # Safety + /// The mutex must be locked by the current thread. + pub unsafe fn unlock(self: Pin<&Self>) { + let r = unsafe { libc::pthread_mutex_unlock(self.raw()) }; + debug_assert_eq!(r, 0); + } +} + +impl !Unpin for Mutex {} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +impl Drop for Mutex { + fn drop(&mut self) { + // SAFETY: + // If `lock` or `init` was called, the mutex must have been pinned, so + // it is still at the same location. Otherwise, `inner` must contain + // `PTHREAD_MUTEX_INITIALIZER`, which is valid at all locations. Thus, + // this call always destroys a valid mutex. + let r = unsafe { libc::pthread_mutex_destroy(self.raw()) }; + if cfg!(target_os = "dragonfly") { + // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a + // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. + // Once it is used (locked/unlocked) or pthread_mutex_init() is called, + // this behaviour no longer occurs. + debug_assert!(r == 0 || r == libc::EINVAL); + } else { + debug_assert_eq!(r, 0); + } + } +} + +struct AttrGuard<'a>(pub &'a mut MaybeUninit); + +impl Drop for AttrGuard<'_> { + fn drop(&mut self) { + unsafe { + let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr()); + assert_eq!(result, 0); + } + } +} diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs index cee728e35cdf..4d2f9c0aaba4 100644 --- a/library/std/src/sys/sync/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -1,196 +1,88 @@ -use crate::cell::UnsafeCell; -use crate::ptr; -use crate::sync::atomic::AtomicPtr; -use crate::sync::atomic::Ordering::Relaxed; -use crate::sys::sync::{Mutex, OnceBox}; -#[cfg(not(target_os = "nto"))] -use crate::sys::time::TIMESPEC_MAX; -#[cfg(target_os = "nto")] -use crate::sys::time::TIMESPEC_MAX_CAPPED; -use crate::time::Duration; +#![forbid(unsafe_op_in_unsafe_fn)] -struct AllocatedCondvar(UnsafeCell); +use crate::pin::Pin; +use crate::ptr; +use crate::sync::atomic::AtomicUsize; +use crate::sync::atomic::Ordering::Relaxed; +use crate::sys::pal::sync as pal; +use crate::sys::sync::{Mutex, OnceBox}; +use crate::time::{Duration, Instant}; pub struct Condvar { - inner: OnceBox, - mutex: AtomicPtr, -} - -unsafe impl Send for AllocatedCondvar {} -unsafe impl Sync for AllocatedCondvar {} - -impl AllocatedCondvar { - fn new() -> Box { - let condvar = Box::new(AllocatedCondvar(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER))); - - cfg_if::cfg_if! { - if #[cfg(any( - target_os = "l4re", - target_os = "android", - target_os = "redox", - target_vendor = "apple", - ))] { - // `pthread_condattr_setclock` is unfortunately not supported on these platforms. - } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "teeos"))] { - // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet - // So on that platform, init() should always be called - // Moreover, that platform does not have pthread_condattr_setclock support, - // hence that initialization should be skipped as well - // - // Similar story for the 3DS (horizon). - let r = unsafe { libc::pthread_cond_init(condvar.0.get(), crate::ptr::null()) }; - assert_eq!(r, 0); - } else { - use crate::mem::MaybeUninit; - let mut attr = MaybeUninit::::uninit(); - let r = unsafe { libc::pthread_condattr_init(attr.as_mut_ptr()) }; - assert_eq!(r, 0); - let r = unsafe { libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC) }; - assert_eq!(r, 0); - let r = unsafe { libc::pthread_cond_init(condvar.0.get(), attr.as_ptr()) }; - assert_eq!(r, 0); - let r = unsafe { libc::pthread_condattr_destroy(attr.as_mut_ptr()) }; - assert_eq!(r, 0); - } - } - - condvar - } -} - -impl Drop for AllocatedCondvar { - #[inline] - fn drop(&mut self) { - let r = unsafe { libc::pthread_cond_destroy(self.0.get()) }; - if cfg!(target_os = "dragonfly") { - // On DragonFly pthread_cond_destroy() returns EINVAL if called on - // a condvar that was just initialized with - // libc::PTHREAD_COND_INITIALIZER. Once it is used or - // pthread_cond_init() is called, this behavior no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } - } + cvar: OnceBox, + mutex: AtomicUsize, } impl Condvar { pub const fn new() -> Condvar { - Condvar { inner: OnceBox::new(), mutex: AtomicPtr::new(ptr::null_mut()) } - } - - fn get(&self) -> *mut libc::pthread_cond_t { - self.inner.get_or_init(AllocatedCondvar::new).0.get() + Condvar { cvar: OnceBox::new(), mutex: AtomicUsize::new(0) } } #[inline] - fn verify(&self, mutex: *mut libc::pthread_mutex_t) { - // Relaxed is okay here because we never read through `self.addr`, and only use it to + fn get(&self) -> Pin<&pal::Condvar> { + self.cvar.get_or_init(|| { + let mut cvar = Box::pin(pal::Condvar::new()); + // SAFETY: we only call `init` once, namely here. + unsafe { cvar.as_mut().init() }; + cvar + }) + } + + #[inline] + fn verify(&self, mutex: Pin<&pal::Mutex>) { + let addr = ptr::from_ref::(&mutex).addr(); + // Relaxed is okay here because we never read through `self.mutex`, and only use it to // compare addresses. - match self.mutex.compare_exchange(ptr::null_mut(), mutex, Relaxed, Relaxed) { - Ok(_) => {} // Stored the address - Err(n) if n == mutex => {} // Lost a race to store the same address + match self.mutex.compare_exchange(0, addr, Relaxed, Relaxed) { + Ok(_) => {} // Stored the address + Err(n) if n == addr => {} // Lost a race to store the same address _ => panic!("attempted to use a condition variable with two mutexes"), } } #[inline] pub fn notify_one(&self) { - let r = unsafe { libc::pthread_cond_signal(self.get()) }; - debug_assert_eq!(r, 0); + // SAFETY: we called `init` above. + unsafe { self.get().notify_one() } } #[inline] pub fn notify_all(&self) { - let r = unsafe { libc::pthread_cond_broadcast(self.get()) }; - debug_assert_eq!(r, 0); + // SAFETY: we called `init` above. + unsafe { self.get().notify_all() } } #[inline] pub unsafe fn wait(&self, mutex: &Mutex) { - let mutex = mutex.get_assert_locked(); + // SAFETY: the caller guarantees that the lock is owned, thus the mutex + // must have been initialized already. + let mutex = unsafe { mutex.pal.get_unchecked() }; self.verify(mutex); - let r = libc::pthread_cond_wait(self.get(), mutex); - debug_assert_eq!(r, 0); + // SAFETY: we called `init` above, we verified that this condition + // variable is only used with `mutex` and the caller guarantees that + // `mutex` is locked by the current thread. + unsafe { self.get().wait(mutex) } } - // This implementation is used on systems that support pthread_condattr_setclock - // where we configure condition variable to use monotonic clock (instead of - // default system clock). This approach avoids all problems that result - // from changes made to the system time. - #[cfg(not(any( - target_os = "android", - target_os = "espidf", - target_os = "horizon", - target_vendor = "apple", - )))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - use crate::sys::time::Timespec; - - let mutex = mutex.get_assert_locked(); + // SAFETY: the caller guarantees that the lock is owned, thus the mutex + // must have been initialized already. + let mutex = unsafe { mutex.pal.get_unchecked() }; self.verify(mutex); - #[cfg(not(target_os = "nto"))] - let timeout = Timespec::now(libc::CLOCK_MONOTONIC) - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec()) - .unwrap_or(TIMESPEC_MAX); - - #[cfg(target_os = "nto")] - let timeout = Timespec::now(libc::CLOCK_MONOTONIC) - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec_capped()) - .unwrap_or(TIMESPEC_MAX_CAPPED); - - let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout); - assert!(r == libc::ETIMEDOUT || r == 0); - r == 0 - } - - // This implementation is modeled after libcxx's condition_variable - // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 - // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 - #[cfg(any( - target_os = "android", - target_os = "espidf", - target_os = "horizon", - target_vendor = "apple", - ))] - pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - use crate::sys::time::SystemTime; - use crate::time::Instant; - - let mutex = mutex.get_assert_locked(); - self.verify(mutex); - - // OSX implementation of `pthread_cond_timedwait` is buggy - // with super long durations. When duration is greater than - // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` - // in macOS Sierra returns error 316. - // - // This program demonstrates the issue: - // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c - // - // To work around this issue, and possible bugs of other OSes, timeout - // is clamped to 1000 years, which is allowable per the API of `wait_timeout` - // because of spurious wakeups. - let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400)); - - // pthread_cond_timedwait uses system time, but we want to report timeout - // based on stable time. - let now = Instant::now(); - - let timeout = SystemTime::now() - .t - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec()) - .unwrap_or(TIMESPEC_MAX); - - let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout); - debug_assert!(r == libc::ETIMEDOUT || r == 0); - - // ETIMEDOUT is not a totally reliable method of determining timeout due - // to clock shifts, so do the check ourselves - now.elapsed() < dur + if pal::Condvar::PRECISE_TIMEOUT { + // SAFETY: we called `init` above, we verified that this condition + // variable is only used with `mutex` and the caller guarantees that + // `mutex` is locked by the current thread. + unsafe { self.get().wait_timeout(mutex, dur) } + } else { + // Timeout reports are not reliable, so do the check ourselves. + let now = Instant::now(); + // SAFETY: we called `init` above, we verified that this condition + // variable is only used with `mutex` and the caller guarantees that + // `mutex` is locked by the current thread. + let woken = unsafe { self.get().wait_timeout(mutex, dur) }; + woken || now.elapsed() < dur + } } } diff --git a/library/std/src/sys/sync/condvar/sgx.rs b/library/std/src/sys/sync/condvar/sgx.rs index e60715e4b592..2bde9d0694ed 100644 --- a/library/std/src/sys/sync/condvar/sgx.rs +++ b/library/std/src/sys/sync/condvar/sgx.rs @@ -13,17 +13,19 @@ impl Condvar { } fn get(&self) -> &SpinMutex> { - self.inner.get_or_init(|| Box::new(SpinMutex::new(WaitVariable::new(())))) + self.inner.get_or_init(|| Box::pin(SpinMutex::new(WaitVariable::new(())))).get_ref() } #[inline] pub fn notify_one(&self) { - let _ = WaitQueue::notify_one(self.get().lock()); + let guard = self.get().lock(); + let _ = WaitQueue::notify_one(guard); } #[inline] pub fn notify_all(&self) { - let _ = WaitQueue::notify_all(self.get().lock()); + let guard = self.get().lock(); + let _ = WaitQueue::notify_all(guard); } pub unsafe fn wait(&self, mutex: &Mutex) { diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs index abd58122523c..5719bb10f7f9 100644 --- a/library/std/src/sys/sync/mutex/pthread.rs +++ b/library/std/src/sys/sync/mutex/pthread.rs @@ -1,163 +1,66 @@ -use crate::cell::UnsafeCell; -use crate::io::Error; -use crate::mem::{MaybeUninit, forget}; -use crate::sys::cvt_nz; +#![forbid(unsafe_op_in_unsafe_fn)] + +use crate::mem::forget; +use crate::pin::Pin; +use crate::sys::pal::sync as pal; use crate::sys::sync::OnceBox; -struct AllocatedMutex(UnsafeCell); - pub struct Mutex { - inner: OnceBox, -} - -unsafe impl Send for AllocatedMutex {} -unsafe impl Sync for AllocatedMutex {} - -impl AllocatedMutex { - fn new() -> Box { - let mutex = Box::new(AllocatedMutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))); - - // Issue #33770 - // - // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have - // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you - // try to re-lock it from the same thread when you already hold a lock - // (https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html). - // This is the case even if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL - // (https://github.com/rust-lang/rust/issues/33770#issuecomment-220847521) -- in that - // case, `pthread_mutexattr_settype(PTHREAD_MUTEX_DEFAULT)` will of course be the same - // as setting it to `PTHREAD_MUTEX_NORMAL`, but not setting any mode will result in - // a Mutex where re-locking is UB. - // - // In practice, glibc takes advantage of this undefined behavior to - // implement hardware lock elision, which uses hardware transactional - // memory to avoid acquiring the lock. While a transaction is in - // progress, the lock appears to be unlocked. This isn't a problem for - // other threads since the transactional memory will abort if a conflict - // is detected, however no abort is generated when re-locking from the - // same thread. - // - // Since locking the same mutex twice will result in two aliasing &mut - // references, we instead create the mutex with type - // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to - // re-lock it from the same thread, thus avoiding undefined behavior. - unsafe { - let mut attr = MaybeUninit::::uninit(); - cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); - let attr = PthreadMutexAttr(&mut attr); - cvt_nz(libc::pthread_mutexattr_settype( - attr.0.as_mut_ptr(), - libc::PTHREAD_MUTEX_NORMAL, - )) - .unwrap(); - cvt_nz(libc::pthread_mutex_init(mutex.0.get(), attr.0.as_ptr())).unwrap(); - } - - mutex - } -} - -impl Drop for AllocatedMutex { - #[inline] - fn drop(&mut self) { - let r = unsafe { libc::pthread_mutex_destroy(self.0.get()) }; - if cfg!(target_os = "dragonfly") { - // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a - // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. - // Once it is used (locked/unlocked) or pthread_mutex_init() is called, - // this behavior no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } - } + pub pal: OnceBox, } impl Mutex { #[inline] pub const fn new() -> Mutex { - Mutex { inner: OnceBox::new() } - } - - /// Gets access to the pthread mutex under the assumption that the mutex is - /// locked. - /// - /// This allows skipping the initialization check, as the mutex can only be - /// locked if it is already initialized, and allows relaxing the ordering - /// on the pointer load, since the allocation cannot have been modified - /// since the `lock` and the lock must have occurred on the current thread. - /// - /// # Safety - /// Causes undefined behavior if the mutex is not locked. - #[inline] - pub(crate) unsafe fn get_assert_locked(&self) -> *mut libc::pthread_mutex_t { - unsafe { self.inner.get_unchecked().0.get() } + Mutex { pal: OnceBox::new() } } #[inline] - fn get(&self) -> *mut libc::pthread_mutex_t { - // If initialization fails, the mutex is destroyed. This is always sound, - // however, as the mutex cannot have been locked yet. - self.inner.get_or_init(AllocatedMutex::new).0.get() + fn get(&self) -> Pin<&pal::Mutex> { + // If the initialization race is lost, the new mutex is destroyed. + // This is sound however, as it cannot have been locked. + self.pal.get_or_init(|| { + let mut pal = Box::pin(pal::Mutex::new()); + // SAFETY: we only call `init` once, namely here. + unsafe { pal.as_mut().init() }; + pal + }) } #[inline] pub fn lock(&self) { - #[cold] - #[inline(never)] - fn fail(r: i32) -> ! { - let error = Error::from_raw_os_error(r); - panic!("failed to lock mutex: {error}"); - } - - let r = unsafe { libc::pthread_mutex_lock(self.get()) }; - // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect - // the lock call to never fail. Unfortunately however, some platforms - // (Solaris) do not conform to the standard, and instead always provide - // deadlock detection. How kind of them! Unfortunately that means that - // we need to check the error code here. To save us from UB on other - // less well-behaved platforms in the future, we do it even on "good" - // platforms like macOS. See #120147 for more context. - if r != 0 { - fail(r) - } + // SAFETY: we call `init` above, therefore reentrant locking is safe. + // In `drop` we ensure that the mutex is not destroyed while locked. + unsafe { self.get().lock() } } #[inline] pub unsafe fn unlock(&self) { - let r = libc::pthread_mutex_unlock(self.get_assert_locked()); - debug_assert_eq!(r, 0); + // SAFETY: the mutex can only be locked if it is already initialized + // and we observed this initialization since we observed the locking. + unsafe { self.pal.get_unchecked().unlock() } } #[inline] pub fn try_lock(&self) -> bool { - unsafe { libc::pthread_mutex_trylock(self.get()) == 0 } + // SAFETY: we call `init` above, therefore reentrant locking is safe. + // In `drop` we ensure that the mutex is not destroyed while locked. + unsafe { self.get().try_lock() } } } impl Drop for Mutex { fn drop(&mut self) { - let Some(mutex) = self.inner.take() else { return }; + let Some(pal) = self.pal.take() else { return }; // We're not allowed to pthread_mutex_destroy a locked mutex, // so check first if it's unlocked. - if unsafe { libc::pthread_mutex_trylock(mutex.0.get()) == 0 } { - unsafe { libc::pthread_mutex_unlock(mutex.0.get()) }; - drop(mutex); + if unsafe { pal.as_ref().try_lock() } { + unsafe { pal.as_ref().unlock() }; + drop(pal) } else { // The mutex is locked. This happens if a MutexGuard is leaked. // In this case, we just leak the Mutex too. - forget(mutex); - } - } -} - -pub(super) struct PthreadMutexAttr<'a>(pub &'a mut MaybeUninit); - -impl Drop for PthreadMutexAttr<'_> { - fn drop(&mut self) { - unsafe { - let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr()); - debug_assert_eq!(result, 0); + forget(pal) } } } diff --git a/library/std/src/sys/sync/mutex/sgx.rs b/library/std/src/sys/sync/mutex/sgx.rs index 8529e8579704..3eb981bc65af 100644 --- a/library/std/src/sys/sync/mutex/sgx.rs +++ b/library/std/src/sys/sync/mutex/sgx.rs @@ -13,7 +13,7 @@ impl Mutex { } fn get(&self) -> &SpinMutex> { - self.inner.get_or_init(|| Box::new(SpinMutex::new(WaitVariable::new(false)))) + self.inner.get_or_init(|| Box::pin(SpinMutex::new(WaitVariable::new(false)))).get_ref() } #[inline] @@ -33,7 +33,7 @@ impl Mutex { pub unsafe fn unlock(&self) { // SAFETY: the mutex was locked by the current thread, so it has been // initialized already. - let guard = unsafe { self.inner.get_unchecked().lock() }; + let guard = unsafe { self.inner.get_unchecked().get_ref().lock() }; if let Err(mut guard) = WaitQueue::notify_one(guard) { // No other waiters, unlock *guard.lock_var_mut() = false; diff --git a/library/std/src/sys/sync/once_box.rs b/library/std/src/sys/sync/once_box.rs index 4105af503295..6953b91999ad 100644 --- a/library/std/src/sys/sync/once_box.rs +++ b/library/std/src/sys/sync/once_box.rs @@ -6,6 +6,7 @@ #![allow(dead_code)] // Only used on some platforms. use crate::mem::replace; +use crate::pin::Pin; use crate::ptr::null_mut; use crate::sync::atomic::AtomicPtr; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; @@ -27,46 +28,46 @@ impl OnceBox { /// pointer load in this function can be performed with relaxed ordering, /// potentially allowing the optimizer to turn code like this: /// ```rust, ignore - /// once_box.get_or_init(|| Box::new(42)); + /// once_box.get_or_init(|| Box::pin(42)); /// unsafe { once_box.get_unchecked() } /// ``` /// into /// ```rust, ignore - /// once_box.get_or_init(|| Box::new(42)) + /// once_box.get_or_init(|| Box::pin(42)) /// ``` /// /// # Safety /// This causes undefined behavior if the assumption above is violated. #[inline] - pub unsafe fn get_unchecked(&self) -> &T { - unsafe { &*self.ptr.load(Relaxed) } + pub unsafe fn get_unchecked(&self) -> Pin<&T> { + unsafe { Pin::new_unchecked(&*self.ptr.load(Relaxed)) } } #[inline] - pub fn get_or_init(&self, f: impl FnOnce() -> Box) -> &T { + pub fn get_or_init(&self, f: impl FnOnce() -> Pin>) -> Pin<&T> { let ptr = self.ptr.load(Acquire); match unsafe { ptr.as_ref() } { - Some(val) => val, + Some(val) => unsafe { Pin::new_unchecked(val) }, None => self.initialize(f), } } #[inline] - pub fn take(&mut self) -> Option> { + pub fn take(&mut self) -> Option>> { let ptr = replace(self.ptr.get_mut(), null_mut()); - if !ptr.is_null() { Some(unsafe { Box::from_raw(ptr) }) } else { None } + if !ptr.is_null() { Some(unsafe { Pin::new_unchecked(Box::from_raw(ptr)) }) } else { None } } #[cold] - fn initialize(&self, f: impl FnOnce() -> Box) -> &T { - let new_ptr = Box::into_raw(f()); + fn initialize(&self, f: impl FnOnce() -> Pin>) -> Pin<&T> { + let new_ptr = Box::into_raw(unsafe { Pin::into_inner_unchecked(f()) }); match self.ptr.compare_exchange(null_mut(), new_ptr, Release, Acquire) { - Ok(_) => unsafe { &*new_ptr }, + Ok(_) => unsafe { Pin::new_unchecked(&*new_ptr) }, Err(ptr) => { // Lost the race to another thread. // Drop the value we created, and use the one from the other thread instead. drop(unsafe { Box::from_raw(new_ptr) }); - unsafe { &*ptr } + unsafe { Pin::new_unchecked(&*ptr) } } } } diff --git a/library/std/src/sys/sync/thread_parking/pthread.rs b/library/std/src/sys/sync/thread_parking/pthread.rs index 76df73b2a8e0..19cabd7dd75c 100644 --- a/library/std/src/sys/sync/thread_parking/pthread.rs +++ b/library/std/src/sys/sync/thread_parking/pthread.rs @@ -1,93 +1,19 @@ //! Thread parking without `futex` using the `pthread` synchronization primitives. -use crate::cell::UnsafeCell; -use crate::marker::PhantomPinned; use crate::pin::Pin; use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -#[cfg(not(target_os = "nto"))] -use crate::sys::time::TIMESPEC_MAX; -#[cfg(target_os = "nto")] -use crate::sys::time::TIMESPEC_MAX_CAPPED; +use crate::sys::pal::sync::{Condvar, Mutex}; use crate::time::Duration; const EMPTY: usize = 0; const PARKED: usize = 1; const NOTIFIED: usize = 2; -unsafe fn lock(lock: *mut libc::pthread_mutex_t) { - let r = libc::pthread_mutex_lock(lock); - debug_assert_eq!(r, 0); -} - -unsafe fn unlock(lock: *mut libc::pthread_mutex_t) { - let r = libc::pthread_mutex_unlock(lock); - debug_assert_eq!(r, 0); -} - -unsafe fn notify_one(cond: *mut libc::pthread_cond_t) { - let r = libc::pthread_cond_signal(cond); - debug_assert_eq!(r, 0); -} - -unsafe fn wait(cond: *mut libc::pthread_cond_t, lock: *mut libc::pthread_mutex_t) { - let r = libc::pthread_cond_wait(cond, lock); - debug_assert_eq!(r, 0); -} - -unsafe fn wait_timeout( - cond: *mut libc::pthread_cond_t, - lock: *mut libc::pthread_mutex_t, - dur: Duration, -) { - // Use the system clock on systems that do not support pthread_condattr_setclock. - // This unfortunately results in problems when the system time changes. - #[cfg(any(target_os = "espidf", target_os = "horizon", target_vendor = "apple"))] - let (now, dur) = { - use crate::cmp::min; - use crate::sys::time::SystemTime; - - // OSX implementation of `pthread_cond_timedwait` is buggy - // with super long durations. When duration is greater than - // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` - // in macOS Sierra return error 316. - // - // This program demonstrates the issue: - // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c - // - // To work around this issue, and possible bugs of other OSes, timeout - // is clamped to 1000 years, which is allowable per the API of `park_timeout` - // because of spurious wakeups. - let dur = min(dur, Duration::from_secs(1000 * 365 * 86400)); - let now = SystemTime::now().t; - (now, dur) - }; - // Use the monotonic clock on other systems. - #[cfg(not(any(target_os = "espidf", target_os = "horizon", target_vendor = "apple")))] - let (now, dur) = { - use crate::sys::time::Timespec; - - (Timespec::now(libc::CLOCK_MONOTONIC), dur) - }; - - #[cfg(not(target_os = "nto"))] - let timeout = - now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX); - #[cfg(target_os = "nto")] - let timeout = now - .checked_add_duration(&dur) - .and_then(|t| t.to_timespec_capped()) - .unwrap_or(TIMESPEC_MAX_CAPPED); - let r = libc::pthread_cond_timedwait(cond, lock, &timeout); - debug_assert!(r == libc::ETIMEDOUT || r == 0); -} - pub struct Parker { state: AtomicUsize, - lock: UnsafeCell, - cvar: UnsafeCell, - // The `pthread` primitives require a stable address, so make this struct `!Unpin`. - _pinned: PhantomPinned, + lock: Mutex, + cvar: Condvar, } impl Parker { @@ -96,38 +22,21 @@ impl Parker { /// # Safety /// The constructed parker must never be moved. pub unsafe fn new_in_place(parker: *mut Parker) { - // Use the default mutex implementation to allow for simpler initialization. - // This could lead to undefined behavior when deadlocking. This is avoided - // by not deadlocking. Note in particular the unlocking operation before any - // panic, as code after the panic could try to park again. - (&raw mut (*parker).state).write(AtomicUsize::new(EMPTY)); - (&raw mut (*parker).lock).write(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER)); + parker.write(Parker { + state: AtomicUsize::new(EMPTY), + lock: Mutex::new(), + cvar: Condvar::new(), + }); - cfg_if::cfg_if! { - if #[cfg(any( - target_os = "l4re", - target_os = "android", - target_os = "redox", - target_os = "vita", - target_vendor = "apple", - ))] { - (&raw mut (*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER)); - } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] { - let r = libc::pthread_cond_init((&raw mut (*parker).cvar).cast(), crate::ptr::null()); - assert_eq!(r, 0); - } else { - use crate::mem::MaybeUninit; - let mut attr = MaybeUninit::::uninit(); - let r = libc::pthread_condattr_init(attr.as_mut_ptr()); - assert_eq!(r, 0); - let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC); - assert_eq!(r, 0); - let r = libc::pthread_cond_init((&raw mut (*parker).cvar).cast(), attr.as_ptr()); - assert_eq!(r, 0); - let r = libc::pthread_condattr_destroy(attr.as_mut_ptr()); - assert_eq!(r, 0); - } - } + Pin::new_unchecked(&mut (*parker).cvar).init(); + } + + fn lock(self: Pin<&Self>) -> Pin<&Mutex> { + unsafe { self.map_unchecked(|p| &p.lock) } + } + + fn cvar(self: Pin<&Self>) -> Pin<&Condvar> { + unsafe { self.map_unchecked(|p| &p.cvar) } } // This implementation doesn't require `unsafe`, but other implementations @@ -142,7 +51,7 @@ impl Parker { } // Otherwise we need to coordinate going to sleep - lock(self.lock.get()); + self.lock().lock(); match self.state.compare_exchange(EMPTY, PARKED, Relaxed, Relaxed) { Ok(_) => {} Err(NOTIFIED) => { @@ -154,20 +63,20 @@ impl Parker { // read from the write it made to `state`. let old = self.state.swap(EMPTY, Acquire); - unlock(self.lock.get()); + self.lock().unlock(); assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); return; } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => { - unlock(self.lock.get()); + self.lock().unlock(); panic!("inconsistent park state") } } loop { - wait(self.cvar.get(), self.lock.get()); + self.cvar().wait(self.lock()); match self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed) { Ok(_) => break, // got a notification @@ -175,7 +84,7 @@ impl Parker { } } - unlock(self.lock.get()); + self.lock().unlock(); } // This implementation doesn't require `unsafe`, but other implementations @@ -189,19 +98,19 @@ impl Parker { return; } - lock(self.lock.get()); + self.lock().lock(); match self.state.compare_exchange(EMPTY, PARKED, Relaxed, Relaxed) { Ok(_) => {} Err(NOTIFIED) => { // We must read again here, see `park`. let old = self.state.swap(EMPTY, Acquire); - unlock(self.lock.get()); + self.lock().unlock(); assert_eq!(old, NOTIFIED, "park state changed unexpectedly"); return; } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => { - unlock(self.lock.get()); + self.lock().unlock(); panic!("inconsistent park_timeout state") } } @@ -210,13 +119,13 @@ impl Parker { // from a notification we just want to unconditionally set the state back to // empty, either consuming a notification or un-flagging ourselves as // parked. - wait_timeout(self.cvar.get(), self.lock.get(), dur); + self.cvar().wait_timeout(self.lock(), dur); match self.state.swap(EMPTY, Acquire) { - NOTIFIED => unlock(self.lock.get()), // got a notification, hurray! - PARKED => unlock(self.lock.get()), // no notification, alas + NOTIFIED => self.lock().unlock(), // got a notification, hurray! + PARKED => self.lock().unlock(), // no notification, alas n => { - unlock(self.lock.get()); + self.lock().unlock(); panic!("inconsistent park_timeout state: {n}") } } @@ -248,21 +157,9 @@ impl Parker { // parked thread wakes it doesn't get woken only to have to wait for us // to release `lock`. unsafe { - lock(self.lock.get()); - unlock(self.lock.get()); - notify_one(self.cvar.get()); + self.lock().lock(); + self.lock().unlock(); + self.cvar().notify_one(); } } } - -impl Drop for Parker { - fn drop(&mut self) { - unsafe { - libc::pthread_cond_destroy(self.cvar.get_mut()); - libc::pthread_mutex_destroy(self.lock.get_mut()); - } - } -} - -unsafe impl Sync for Parker {} -unsafe impl Send for Parker {} From 3e3fd4aabeb7b71ae634677413e38f7acfb2d724 Mon Sep 17 00:00:00 2001 From: Giga Bowser <45986823+Giga-Bowser@users.noreply.github.com> Date: Fri, 1 Nov 2024 12:35:01 -0400 Subject: [PATCH 004/330] Use snippet placeholders for generated match arms --- .../src/handlers/add_missing_match_arms.rs | 218 +++++++++--------- .../crates/ide-assists/src/tests/generated.rs | 4 +- 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index a211ca8f2d67..71756def1456 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -30,8 +30,8 @@ use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; // // fn handle(action: Action) { // match action { -// $0Action::Move { distance } => todo!(), -// Action::Stop => todo!(), +// Action::Move { distance } => ${1:todo!()}, +// Action::Stop => ${0:todo!()}, // } // } // ``` @@ -234,8 +234,10 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) } } + let mut todo_placeholders = Vec::new(); let mut first_new_arm = None; for arm in missing_arms { + todo_placeholders.push(arm.expr().unwrap()); first_new_arm.get_or_insert_with(|| arm.clone()); new_match_arm_list.add_arm(arm); } @@ -248,14 +250,18 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) make::ext::expr_todo(), ) .clone_for_update(); + todo_placeholders.push(arm.expr().unwrap()); first_new_arm.get_or_insert_with(|| arm.clone()); new_match_arm_list.add_arm(arm); } if let (Some(first_new_arm), Some(cap)) = (first_new_arm, ctx.config.snippet_cap) { - match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast) { - Some(it) => edit.add_placeholder_snippet(cap, it), - None => edit.add_tabstop_before(cap, first_new_arm), + if let Some(it) = first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast) { + edit.add_placeholder_snippet(cap, it); + } + + for placeholder in todo_placeholders { + edit.add_placeholder_snippet(cap, placeholder); } } @@ -581,8 +587,8 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match a { - $0true => todo!(), - false => todo!(), + true => ${1:todo!()}, + false => ${0:todo!()}, } } "#, @@ -604,7 +610,7 @@ fn foo(a: bool) { fn foo(a: bool) { match a { true => {} - $0false => todo!(), + false => ${0:todo!()}, } } "#, @@ -654,10 +660,10 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match (a, a) { - $0(true, true) => todo!(), - (true, false) => todo!(), - (false, true) => todo!(), - (false, false) => todo!(), + (true, true) => ${1:todo!()}, + (true, false) => ${2:todo!()}, + (false, true) => ${3:todo!()}, + (false, false) => ${0:todo!()}, } } "#, @@ -677,8 +683,8 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match [a] { - $0[true] => todo!(), - [false] => todo!(), + [true] => ${1:todo!()}, + [false] => ${0:todo!()}, } } "#, @@ -695,8 +701,8 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match [a,] { - $0[true] => todo!(), - [false] => todo!(), + [true] => ${1:todo!()}, + [false] => ${0:todo!()}, } } "#, @@ -715,9 +721,9 @@ fn foo(a: bool) { fn foo(a: bool) { match [a, a] { [true, true] => todo!(), - $0[true, false] => todo!(), - [false, true] => todo!(), - [false, false] => todo!(), + [true, false] => ${1:todo!()}, + [false, true] => ${2:todo!()}, + [false, false] => ${0:todo!()}, } } "#, @@ -734,10 +740,10 @@ fn foo(a: bool) { r#" fn foo(a: bool) { match [a, a] { - $0[true, true] => todo!(), - [true, false] => todo!(), - [false, true] => todo!(), - [false, false] => todo!(), + [true, true] => ${1:todo!()}, + [true, false] => ${2:todo!()}, + [false, true] => ${3:todo!()}, + [false, false] => ${0:todo!()}, } } "#, @@ -759,8 +765,8 @@ fn foo(a: bool) { fn foo(a: bool) { match (a, a) { (true | false, true) => {} - $0(true, false) => todo!(), - (false, false) => todo!(), + (true, false) => ${1:todo!()}, + (false, false) => ${0:todo!()}, } } "#, @@ -779,9 +785,9 @@ fn foo(a: bool) { fn foo(a: bool) { match (a, a) { (false, true) => {} - $0(true, true) => todo!(), - (true, false) => todo!(), - (false, false) => todo!(), + (true, true) => ${1:todo!()}, + (true, false) => ${2:todo!()}, + (false, false) => ${0:todo!()}, } } "#, @@ -815,7 +821,7 @@ fn main() { match A::As { A::Bs { x, y: Some(_) } => {} A::Cs(_, Some(_)) => {} - $0A::As => todo!(), + A::As => ${0:todo!()}, } } "#, @@ -838,7 +844,7 @@ fn main() { fn main() { match None { None => {} - Some(${0:_}) => todo!(), + Some(${1:_}) => ${0:todo!()}, } } "#, @@ -862,7 +868,7 @@ enum A { As, Bs, Cs(Option) } fn main() { match A::As { A::Cs(_) | A::Bs => {} - $0A::As => todo!(), + A::As => ${0:todo!()}, } } "#, @@ -892,8 +898,8 @@ fn main() { A::Bs if 0 < 1 => {} A::Ds(_value) => { let x = 1; } A::Es(B::Xs) => (), - $0A::As => todo!(), - A::Cs => todo!(), + A::As => ${1:todo!()}, + A::Cs => ${0:todo!()}, } } "#, @@ -919,7 +925,7 @@ fn main() { match A::As { A::As(_) => {} a @ A::Bs(_) => {} - A::Cs(${0:_}) => todo!(), + A::Cs(${1:_}) => ${0:todo!()}, } } "#, @@ -945,11 +951,11 @@ enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } } fn main() { let a = A::As; match a { - $0A::As => todo!(), - A::Bs => todo!(), - A::Cs(_) => todo!(), - A::Ds(_, _) => todo!(), - A::Es { x, y } => todo!(), + A::As => ${1:todo!()}, + A::Bs => ${2:todo!()}, + A::Cs(_) => ${3:todo!()}, + A::Ds(_, _) => ${4:todo!()}, + A::Es { x, y } => ${0:todo!()}, } } "#, @@ -982,9 +988,9 @@ fn main() { let b = B::One; match (a, b) { (A::Two, B::One) => {}, - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::Two) => ${0:todo!()}, } } "#, @@ -1013,10 +1019,10 @@ fn main() { let a = A::One; let b = B::One; match (a, b) { - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::One) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::One) => ${3:todo!()}, + (A::Two, B::Two) => ${0:todo!()}, } } "#, @@ -1045,10 +1051,10 @@ fn main() { let a = A::One; let b = B::One; match (&a, &b) { - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::One) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::One) => ${3:todo!()}, + (A::Two, B::Two) => ${0:todo!()}, } } "#, @@ -1080,9 +1086,9 @@ fn main() { let b = B::One; match (a, b) { (A::Two, B::One) => {} - $0(A::One, B::One) => todo!(), - (A::One, B::Two) => todo!(), - (A::Two, B::Two) => todo!(), + (A::One, B::One) => ${1:todo!()}, + (A::One, B::Two) => ${2:todo!()}, + (A::Two, B::Two) => ${0:todo!()}, } } "#, @@ -1107,9 +1113,9 @@ fn main() { match (A, B, C) { (A | B , A, A | B | C) => (), (A | B | C , B | C, A | B | C) => (), - $0(C, A, A) => todo!(), - (C, A, B) => todo!(), - (C, A, C) => todo!(), + (C, A, A) => ${1:todo!()}, + (C, A, B) => ${2:todo!()}, + (C, A, C) => ${0:todo!()}, } } "#, @@ -1138,7 +1144,7 @@ fn main() { match (a, b) { (Some(_), _) => {} (None, Some(_)) => {} - $0(None, None) => todo!(), + (None, None) => ${0:todo!()}, } } "#, @@ -1203,8 +1209,8 @@ enum A { One, Two } fn main() { let a = A::One; match (a, ) { - $0(A::One,) => todo!(), - (A::Two,) => todo!(), + (A::One,) => ${1:todo!()}, + (A::Two,) => ${0:todo!()}, } } "#, @@ -1228,7 +1234,7 @@ enum A { As } fn foo(a: &A) { match a { - $0A::As => todo!(), + A::As => ${0:todo!()}, } } "#, @@ -1253,7 +1259,7 @@ enum A { fn foo(a: &mut A) { match a { - $0A::Es { x, y } => todo!(), + A::Es { x, y } => ${0:todo!()}, } } "#, @@ -1313,8 +1319,8 @@ enum E { X, Y } fn main() { match E::X { - $0E::X => todo!(), - E::Y => todo!(), + E::X => ${1:todo!()}, + E::Y => ${0:todo!()}, } } "#, @@ -1360,8 +1366,8 @@ use foo::E::X; fn main() { match X { - $0X => todo!(), - foo::E::Y => todo!(), + X => ${1:todo!()}, + foo::E::Y => ${0:todo!()}, } } "#, @@ -1388,7 +1394,7 @@ fn foo(a: A) { match a { // foo bar baz A::One => {} - $0A::Two => todo!(), + A::Two => ${0:todo!()}, // This is where the rest should be } } @@ -1412,8 +1418,8 @@ fn foo(a: A) { enum A { One, Two } fn foo(a: A) { match a { - $0A::One => todo!(), - A::Two => todo!(), + A::One => ${1:todo!()}, + A::Two => ${0:todo!()}, // foo bar baz } } @@ -1437,8 +1443,8 @@ fn foo(a: A) { enum A { One, Two, } fn foo(a: A) { match a { - $0A::One => todo!(), - A::Two => todo!(), + A::One => ${1:todo!()}, + A::Two => ${0:todo!()}, } } "#, @@ -1460,8 +1466,8 @@ fn foo(opt: Option) { r#" fn foo(opt: Option) { match opt { - Some(${0:_}) => todo!(), - None => todo!(), + Some(${1:_}) => ${2:todo!()}, + None => ${0:todo!()}, } } "#, @@ -1493,9 +1499,9 @@ enum Test { fn foo(t: Test) { m!(match t { - $0Test::A => todo!(), - Test::B => todo!(), - Test::C => todo!(), + Test::A => ${1:todo!()}, + Test::B => ${2:todo!()}, + Test::C => ${0:todo!()}, }); }"#, ); @@ -1530,7 +1536,7 @@ fn foo(t: bool) { fn foo(t: bool) { match t { true => 1 + 2, - $0false => todo!(), + false => ${0:todo!()}, } }"#, ); @@ -1550,7 +1556,7 @@ fn foo(t: bool) { fn foo(t: bool) { match t { true => 1 + 2, - $0false => todo!(), + false => ${0:todo!()}, } }"#, ); @@ -1571,8 +1577,8 @@ fn foo(t: bool) { fn foo(t: bool) { match t { _ => 1 + 2, - $0true => todo!(), - false => todo!(), + true => ${1:todo!()}, + false => ${0:todo!()}, } }"#, ); @@ -1595,8 +1601,8 @@ pub enum E { A, #[doc(hidden)] B, } r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${0:todo!()}, } } "#, @@ -1620,9 +1626,9 @@ pub enum E { A, #[doc(hidden)] B, } r#" fn foo(t: (bool, ::e::E)) { match t { - $0(true, e::E::A) => todo!(), - (false, e::E::A) => todo!(), - _ => todo!(), + (true, e::E::A) => ${1:todo!()}, + (false, e::E::A) => ${2:todo!()}, + _ => ${0:todo!()}, } } "#, @@ -1646,7 +1652,7 @@ pub enum E { #[doc(hidden)] A, } r#" fn foo(t: ::e::E) { match t { - ${0:_} => todo!(), + ${1:_} => ${0:todo!()}, } } "#, @@ -1707,7 +1713,7 @@ pub enum E { A, } fn foo(t: ::e::E) { match t { e::E::A => todo!(), - ${0:_} => todo!(), + ${1:_} => ${0:todo!()}, } } "#, @@ -1732,8 +1738,8 @@ pub enum E { A, } r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${0:todo!()}, } } "#, @@ -1757,8 +1763,8 @@ pub enum E { A, #[doc(hidden)] B }"#, r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${0:todo!()}, } } "#, @@ -1784,7 +1790,7 @@ pub enum E { A, #[doc(hidden)] B }"#, fn foo(t: ::e::E) { match t { e::E::A => todo!(), - ${0:_} => todo!(), + ${1:_} => ${0:todo!()}, } } "#, @@ -1809,7 +1815,7 @@ pub enum E { #[doc(hidden)] A, }"#, fn foo(t: ::e::E, b: bool) { match t { _ if b => todo!(), - ${0:_} => todo!(), + ${1:_} => ${0:todo!()}, } } "#, @@ -1850,8 +1856,8 @@ pub enum E { A, #[doc(hidden)] B, }"#, r#" fn foo(t: ::e::E) { match t { - $0e::E::A => todo!(), - _ => todo!(), + e::E::A => ${1:todo!()}, + _ => ${0:todo!()}, } } "#, @@ -1874,8 +1880,8 @@ enum E { A, #[doc(hidden)] B, } fn foo(t: E) { match t { - $0E::A => todo!(), - E::B => todo!(), + E::A => ${1:todo!()}, + E::B => ${0:todo!()}, } }"#, ); @@ -1899,8 +1905,8 @@ enum E { A, B, } fn foo(t: E) { match t { - $0E::A => todo!(), - E::B => todo!(), + E::A => ${1:todo!()}, + E::B => ${0:todo!()}, } }"#, ); @@ -1924,8 +1930,8 @@ enum E { A, #[doc(hidden)] B, } fn foo(t: E) { match t { - $0E::A => todo!(), - E::B => todo!(), + E::A => ${1:todo!()}, + E::B => ${0:todo!()}, } }"#, ); @@ -1975,8 +1981,8 @@ enum A { fn a() { let b = A::A; match b { - $0A::A => todo!(), - A::Missing { a, u32, c } => todo!(), + A::A => ${1:todo!()}, + A::Missing { a, u32, c } => ${0:todo!()}, } }"#, ) @@ -2013,8 +2019,8 @@ pub enum E { fn f() { let value = E::A; match value { - $0E::A => todo!(), - E::B(s) => todo!(), + E::A => ${1:todo!()}, + E::B(s) => ${0:todo!()}, } } "#, @@ -2051,8 +2057,8 @@ pub enum E { fn f() { let value = E::A; match value { - $0E::A => todo!(), - E::B(s1, s2) => todo!(), + E::A => ${1:todo!()}, + E::B(s1, s2) => ${0:todo!()}, } } "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 64b7ab1a1230..8fffe7713f95 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -187,8 +187,8 @@ enum Action { Move { distance: u32 }, Stop } fn handle(action: Action) { match action { - $0Action::Move { distance } => todo!(), - Action::Stop => todo!(), + Action::Move { distance } => ${1:todo!()}, + Action::Stop => ${0:todo!()}, } } "#####, From 4b7f56ac9dd3db6163f26ab7b5e28b55756fef79 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 2 Nov 2024 11:05:01 +0000 Subject: [PATCH 005/330] Fix and undeprecate home_dir() --- library/std/src/env.rs | 16 ++++++---------- library/std/src/sys/pal/windows/os.rs | 4 ++-- library/std/tests/env.rs | 14 +++++++------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index d732a15117e9..eefae253e9b6 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -608,20 +608,16 @@ impl Error for JoinPathsError { /// /// # Windows /// -/// - Returns the value of the 'HOME' environment variable if it is set -/// (including to an empty string). -/// - Otherwise, returns the value of the 'USERPROFILE' environment variable if it is set -/// (including to an empty string). -/// - If both do not exist, [`GetUserProfileDirectory`][msdn] is used to return the path. +/// - Returns the value of the 'USERPROFILE' environment variable if it is set, and is not an empty string. +/// - Otherwise, [`GetUserProfileDirectory`][msdn] is used to return the path. This may change in the future. /// /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya /// -/// # Deprecation +/// In UWP (Universal Windows Platform) targets this function is unimplemented and always returns `None`. /// -/// This function is deprecated because the behavior on Windows is not correct. -/// The 'HOME' environment variable is not standard on Windows, and may not produce -/// desired results; for instance, under Cygwin or Mingw it will return `/home/you` -/// when it should return `C:\Users\you`. +/// Before Rust CURRENT_RUSTC_VERSION, this function used to return the value of the 'HOME' environment variable +/// on Windows, which in Cygwin or Mingw environments could return non-standard paths like `/home/you` +/// instead of `C:\Users\you`. /// /// # Examples /// diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 5242bc9da31f..5231a34469ab 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -377,8 +377,8 @@ fn home_dir_crt() -> Option { } pub fn home_dir() -> Option { - crate::env::var_os("HOME") - .or_else(|| crate::env::var_os("USERPROFILE")) + crate::env::var_os("USERPROFILE") + .filter(|s| !s.is_empty()) .map(PathBuf::from) .or_else(home_dir_crt) } diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index 4e472b4ce995..44fe84c989fb 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -122,19 +122,19 @@ fn env_home_dir() { assert!(home_dir().is_some()); - set_var("HOME", "/home/MountainView"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - remove_var("HOME"); + set_var("HOME", "/home/PaloAlto"); + assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used"); set_var("USERPROFILE", "/home/MountainView"); assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - set_var("HOME", "/home/MountainView"); - set_var("USERPROFILE", "/home/PaloAlto"); + remove_var("HOME"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - remove_var("HOME"); + set_var("USERPROFILE", ""); + assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored"); + remove_var("USERPROFILE"); if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } From bbfee6010464618aa381380c7f4e4013449c6910 Mon Sep 17 00:00:00 2001 From: Giga Bowser <45986823+Giga-Bowser@users.noreply.github.com> Date: Tue, 5 Nov 2024 12:13:42 -0500 Subject: [PATCH 006/330] Properly use final tabstop when adding missing match arms --- .../src/handlers/add_missing_match_arms.rs | 121 ++++++++++-------- .../crates/ide-assists/src/tests/generated.rs | 2 +- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 71756def1456..236d33878edc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -31,7 +31,7 @@ use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; // fn handle(action: Action) { // match action { // Action::Move { distance } => ${1:todo!()}, -// Action::Stop => ${0:todo!()}, +// Action::Stop => ${2:todo!()},$0 // } // } // ``` @@ -234,12 +234,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) } } + let mut added_arms = Vec::new(); let mut todo_placeholders = Vec::new(); - let mut first_new_arm = None; for arm in missing_arms { todo_placeholders.push(arm.expr().unwrap()); - first_new_arm.get_or_insert_with(|| arm.clone()); - new_match_arm_list.add_arm(arm); + added_arms.push(arm); } if needs_catch_all_arm && !has_catch_all_arm { @@ -251,18 +250,28 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) ) .clone_for_update(); todo_placeholders.push(arm.expr().unwrap()); - first_new_arm.get_or_insert_with(|| arm.clone()); + added_arms.push(arm); + } + + let first_new_arm = added_arms.first().cloned(); + let last_new_arm = added_arms.last().cloned(); + + for arm in added_arms { new_match_arm_list.add_arm(arm); } - if let (Some(first_new_arm), Some(cap)) = (first_new_arm, ctx.config.snippet_cap) { - if let Some(it) = first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast) { + if let Some(cap) = ctx.config.snippet_cap { + if let Some(it) = first_new_arm.and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast)) { edit.add_placeholder_snippet(cap, it); } for placeholder in todo_placeholders { edit.add_placeholder_snippet(cap, placeholder); } + + if let Some(arm) = last_new_arm { + edit.add_tabstop_after(cap, arm); + } } // FIXME: Hack for mutable syntax trees not having great support for macros @@ -588,7 +597,7 @@ fn foo(a: bool) { fn foo(a: bool) { match a { true => ${1:todo!()}, - false => ${0:todo!()}, + false => ${2:todo!()},$0 } } "#, @@ -610,7 +619,7 @@ fn foo(a: bool) { fn foo(a: bool) { match a { true => {} - false => ${0:todo!()}, + false => ${1:todo!()},$0 } } "#, @@ -663,7 +672,7 @@ fn foo(a: bool) { (true, true) => ${1:todo!()}, (true, false) => ${2:todo!()}, (false, true) => ${3:todo!()}, - (false, false) => ${0:todo!()}, + (false, false) => ${4:todo!()},$0 } } "#, @@ -684,7 +693,7 @@ fn foo(a: bool) { fn foo(a: bool) { match [a] { [true] => ${1:todo!()}, - [false] => ${0:todo!()}, + [false] => ${2:todo!()},$0 } } "#, @@ -702,7 +711,7 @@ fn foo(a: bool) { fn foo(a: bool) { match [a,] { [true] => ${1:todo!()}, - [false] => ${0:todo!()}, + [false] => ${2:todo!()},$0 } } "#, @@ -723,7 +732,7 @@ fn foo(a: bool) { [true, true] => todo!(), [true, false] => ${1:todo!()}, [false, true] => ${2:todo!()}, - [false, false] => ${0:todo!()}, + [false, false] => ${3:todo!()},$0 } } "#, @@ -743,7 +752,7 @@ fn foo(a: bool) { [true, true] => ${1:todo!()}, [true, false] => ${2:todo!()}, [false, true] => ${3:todo!()}, - [false, false] => ${0:todo!()}, + [false, false] => ${4:todo!()},$0 } } "#, @@ -766,7 +775,7 @@ fn foo(a: bool) { match (a, a) { (true | false, true) => {} (true, false) => ${1:todo!()}, - (false, false) => ${0:todo!()}, + (false, false) => ${2:todo!()},$0 } } "#, @@ -787,7 +796,7 @@ fn foo(a: bool) { (false, true) => {} (true, true) => ${1:todo!()}, (true, false) => ${2:todo!()}, - (false, false) => ${0:todo!()}, + (false, false) => ${3:todo!()},$0 } } "#, @@ -821,7 +830,7 @@ fn main() { match A::As { A::Bs { x, y: Some(_) } => {} A::Cs(_, Some(_)) => {} - A::As => ${0:todo!()}, + A::As => ${1:todo!()},$0 } } "#, @@ -844,7 +853,7 @@ fn main() { fn main() { match None { None => {} - Some(${1:_}) => ${0:todo!()}, + Some(${1:_}) => ${2:todo!()},$0 } } "#, @@ -868,7 +877,7 @@ enum A { As, Bs, Cs(Option) } fn main() { match A::As { A::Cs(_) | A::Bs => {} - A::As => ${0:todo!()}, + A::As => ${1:todo!()},$0 } } "#, @@ -899,7 +908,7 @@ fn main() { A::Ds(_value) => { let x = 1; } A::Es(B::Xs) => (), A::As => ${1:todo!()}, - A::Cs => ${0:todo!()}, + A::Cs => ${2:todo!()},$0 } } "#, @@ -925,7 +934,7 @@ fn main() { match A::As { A::As(_) => {} a @ A::Bs(_) => {} - A::Cs(${1:_}) => ${0:todo!()}, + A::Cs(${1:_}) => ${2:todo!()},$0 } } "#, @@ -955,7 +964,7 @@ fn main() { A::Bs => ${2:todo!()}, A::Cs(_) => ${3:todo!()}, A::Ds(_, _) => ${4:todo!()}, - A::Es { x, y } => ${0:todo!()}, + A::Es { x, y } => ${5:todo!()},$0 } } "#, @@ -990,7 +999,7 @@ fn main() { (A::Two, B::One) => {}, (A::One, B::One) => ${1:todo!()}, (A::One, B::Two) => ${2:todo!()}, - (A::Two, B::Two) => ${0:todo!()}, + (A::Two, B::Two) => ${3:todo!()},$0 } } "#, @@ -1022,7 +1031,7 @@ fn main() { (A::One, B::One) => ${1:todo!()}, (A::One, B::Two) => ${2:todo!()}, (A::Two, B::One) => ${3:todo!()}, - (A::Two, B::Two) => ${0:todo!()}, + (A::Two, B::Two) => ${4:todo!()},$0 } } "#, @@ -1054,7 +1063,7 @@ fn main() { (A::One, B::One) => ${1:todo!()}, (A::One, B::Two) => ${2:todo!()}, (A::Two, B::One) => ${3:todo!()}, - (A::Two, B::Two) => ${0:todo!()}, + (A::Two, B::Two) => ${4:todo!()},$0 } } "#, @@ -1088,7 +1097,7 @@ fn main() { (A::Two, B::One) => {} (A::One, B::One) => ${1:todo!()}, (A::One, B::Two) => ${2:todo!()}, - (A::Two, B::Two) => ${0:todo!()}, + (A::Two, B::Two) => ${3:todo!()},$0 } } "#, @@ -1115,7 +1124,7 @@ fn main() { (A | B | C , B | C, A | B | C) => (), (C, A, A) => ${1:todo!()}, (C, A, B) => ${2:todo!()}, - (C, A, C) => ${0:todo!()}, + (C, A, C) => ${3:todo!()},$0 } } "#, @@ -1144,7 +1153,7 @@ fn main() { match (a, b) { (Some(_), _) => {} (None, Some(_)) => {} - (None, None) => ${0:todo!()}, + (None, None) => ${1:todo!()},$0 } } "#, @@ -1210,7 +1219,7 @@ fn main() { let a = A::One; match (a, ) { (A::One,) => ${1:todo!()}, - (A::Two,) => ${0:todo!()}, + (A::Two,) => ${2:todo!()},$0 } } "#, @@ -1234,7 +1243,7 @@ enum A { As } fn foo(a: &A) { match a { - A::As => ${0:todo!()}, + A::As => ${1:todo!()},$0 } } "#, @@ -1259,7 +1268,7 @@ enum A { fn foo(a: &mut A) { match a { - A::Es { x, y } => ${0:todo!()}, + A::Es { x, y } => ${1:todo!()},$0 } } "#, @@ -1320,7 +1329,7 @@ enum E { X, Y } fn main() { match E::X { E::X => ${1:todo!()}, - E::Y => ${0:todo!()}, + E::Y => ${2:todo!()},$0 } } "#, @@ -1367,7 +1376,7 @@ use foo::E::X; fn main() { match X { X => ${1:todo!()}, - foo::E::Y => ${0:todo!()}, + foo::E::Y => ${2:todo!()},$0 } } "#, @@ -1394,7 +1403,7 @@ fn foo(a: A) { match a { // foo bar baz A::One => {} - A::Two => ${0:todo!()}, + A::Two => ${1:todo!()},$0 // This is where the rest should be } } @@ -1419,7 +1428,7 @@ enum A { One, Two } fn foo(a: A) { match a { A::One => ${1:todo!()}, - A::Two => ${0:todo!()}, + A::Two => ${2:todo!()},$0 // foo bar baz } } @@ -1444,7 +1453,7 @@ enum A { One, Two, } fn foo(a: A) { match a { A::One => ${1:todo!()}, - A::Two => ${0:todo!()}, + A::Two => ${2:todo!()},$0 } } "#, @@ -1467,7 +1476,7 @@ fn foo(opt: Option) { fn foo(opt: Option) { match opt { Some(${1:_}) => ${2:todo!()}, - None => ${0:todo!()}, + None => ${3:todo!()},$0 } } "#, @@ -1501,7 +1510,7 @@ fn foo(t: Test) { m!(match t { Test::A => ${1:todo!()}, Test::B => ${2:todo!()}, - Test::C => ${0:todo!()}, + Test::C => ${3:todo!()},$0 }); }"#, ); @@ -1536,7 +1545,7 @@ fn foo(t: bool) { fn foo(t: bool) { match t { true => 1 + 2, - false => ${0:todo!()}, + false => ${1:todo!()},$0 } }"#, ); @@ -1556,7 +1565,7 @@ fn foo(t: bool) { fn foo(t: bool) { match t { true => 1 + 2, - false => ${0:todo!()}, + false => ${1:todo!()},$0 } }"#, ); @@ -1578,7 +1587,7 @@ fn foo(t: bool) { match t { _ => 1 + 2, true => ${1:todo!()}, - false => ${0:todo!()}, + false => ${2:todo!()},$0 } }"#, ); @@ -1602,7 +1611,7 @@ pub enum E { A, #[doc(hidden)] B, } fn foo(t: ::e::E) { match t { e::E::A => ${1:todo!()}, - _ => ${0:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1628,7 +1637,7 @@ fn foo(t: (bool, ::e::E)) { match t { (true, e::E::A) => ${1:todo!()}, (false, e::E::A) => ${2:todo!()}, - _ => ${0:todo!()}, + _ => ${3:todo!()},$0 } } "#, @@ -1652,7 +1661,7 @@ pub enum E { #[doc(hidden)] A, } r#" fn foo(t: ::e::E) { match t { - ${1:_} => ${0:todo!()}, + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1713,7 +1722,7 @@ pub enum E { A, } fn foo(t: ::e::E) { match t { e::E::A => todo!(), - ${1:_} => ${0:todo!()}, + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1739,7 +1748,7 @@ pub enum E { A, } fn foo(t: ::e::E) { match t { e::E::A => ${1:todo!()}, - _ => ${0:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1764,7 +1773,7 @@ pub enum E { A, #[doc(hidden)] B }"#, fn foo(t: ::e::E) { match t { e::E::A => ${1:todo!()}, - _ => ${0:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1790,7 +1799,7 @@ pub enum E { A, #[doc(hidden)] B }"#, fn foo(t: ::e::E) { match t { e::E::A => todo!(), - ${1:_} => ${0:todo!()}, + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1815,7 +1824,7 @@ pub enum E { #[doc(hidden)] A, }"#, fn foo(t: ::e::E, b: bool) { match t { _ if b => todo!(), - ${1:_} => ${0:todo!()}, + ${1:_} => ${2:todo!()},$0 } } "#, @@ -1857,7 +1866,7 @@ pub enum E { A, #[doc(hidden)] B, }"#, fn foo(t: ::e::E) { match t { e::E::A => ${1:todo!()}, - _ => ${0:todo!()}, + _ => ${2:todo!()},$0 } } "#, @@ -1881,7 +1890,7 @@ enum E { A, #[doc(hidden)] B, } fn foo(t: E) { match t { E::A => ${1:todo!()}, - E::B => ${0:todo!()}, + E::B => ${2:todo!()},$0 } }"#, ); @@ -1906,7 +1915,7 @@ enum E { A, B, } fn foo(t: E) { match t { E::A => ${1:todo!()}, - E::B => ${0:todo!()}, + E::B => ${2:todo!()},$0 } }"#, ); @@ -1931,7 +1940,7 @@ enum E { A, #[doc(hidden)] B, } fn foo(t: E) { match t { E::A => ${1:todo!()}, - E::B => ${0:todo!()}, + E::B => ${2:todo!()},$0 } }"#, ); @@ -1982,7 +1991,7 @@ fn a() { let b = A::A; match b { A::A => ${1:todo!()}, - A::Missing { a, u32, c } => ${0:todo!()}, + A::Missing { a, u32, c } => ${2:todo!()},$0 } }"#, ) @@ -2020,7 +2029,7 @@ fn f() { let value = E::A; match value { E::A => ${1:todo!()}, - E::B(s) => ${0:todo!()}, + E::B(s) => ${2:todo!()},$0 } } "#, @@ -2058,7 +2067,7 @@ fn f() { let value = E::A; match value { E::A => ${1:todo!()}, - E::B(s1, s2) => ${0:todo!()}, + E::B(s1, s2) => ${2:todo!()},$0 } } "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 8fffe7713f95..eef4da55e94a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -188,7 +188,7 @@ enum Action { Move { distance: u32 }, Stop } fn handle(action: Action) { match action { Action::Move { distance } => ${1:todo!()}, - Action::Stop => ${0:todo!()}, + Action::Stop => ${2:todo!()},$0 } } "#####, From c588849044a09ba5e3c7dd74a31cd8038342f6cb Mon Sep 17 00:00:00 2001 From: David Kurilla <130074511+davidkurilla@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:45:00 +0000 Subject: [PATCH 007/330] feat: convert add_braces to SyntaxFactory SyntaxEditor abstraction --- .../crates/ide-assists/src/handlers/add_braces.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index 2f4a263ee070..c96ae7a16bc1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -1,5 +1,5 @@ use syntax::{ - ast::{self, edit::AstNodeEdit, make}, + ast::{self, edit::AstNodeEdit, make, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxEditor, AstNode, }; @@ -39,12 +39,19 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( }, expr.syntax().text_range(), |builder| { + + let make = SyntaxFactory::new(); + let mut editor = builder.make_editor(&expr.syntax()); + let block_expr = AstNodeEdit::indent( - &make::block_expr(None, Some(expr.clone())), + &make.block_expr(None, Some(expr.clone())), AstNodeEdit::indent_level(&expr), ); - builder.replace(expr.syntax().text_range(), block_expr.syntax().text()); + editor.replace(expr.syntax(), block_expr.syntax()); + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } From 2f00b6affda7b25cb2721422d7adad39154ce9d1 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Thu, 10 Nov 2022 12:12:02 -0500 Subject: [PATCH 008/330] Require `type_map::stub` callers to supply file information This change attaches file information (`DIFile` reference and line number) to struct debug info nodes. Before: ``` ; foo.ll ... !5 = !DIFile(filename: "", directory: "") ... !16 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyType", scope: !2, file: !5, size: 32, align: 32, elements: !17, templateParams: !19, identifier: "4cb373851db92e732c4cb5651b886dd0") ... ``` After: ``` ; foo.ll ... !3 = !DIFile(filename: "foo.rs", directory: "/home/matt/src/rust98678", checksumkind: CSK_SHA1, checksum: "bcb9f08512c8f3b8181ef4726012bc6807bc9be4") ... !16 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyType", scope: !2, file: !3, line: 3, size: 32, align: 32, elements: !17, templateParams: !19, identifier: "9e5968c7af39c148acb253912b7f409f") ... ``` Fixes #98678 --- .../src/debuginfo/metadata.rs | 25 +++++++++++++++++++ .../src/debuginfo/metadata/enums/cpp_like.rs | 6 +++++ .../src/debuginfo/metadata/enums/mod.rs | 10 +++++++- .../src/debuginfo/metadata/enums/native.rs | 4 +++ .../src/debuginfo/metadata/type_map.rs | 12 +++++---- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 151923a3bd28..6b5f53e40bd5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -204,6 +204,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &ptr_type_debuginfo_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, cx.size_and_align_of(ptr_type), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -371,6 +373,8 @@ fn build_dyn_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, cx.size_and_align_of(dyn_type), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -841,6 +845,8 @@ fn build_foreign_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, t, false), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, cx.size_and_align_of(t), Some(get_namespace_for_item(cx, def_id)), DIFlags::FlagZero, @@ -1044,6 +1050,15 @@ fn build_struct_type_di_node<'ll, 'tcx>( let struct_type_and_layout = cx.layout_of(struct_type); let variant_def = adt_def.non_enum_variant(); + let tcx = cx.tcx; + let struct_span = tcx.def_span(adt_def.did()); + let (file_metadata, line_number) = if !struct_span.is_dummy() { + let loc = cx.lookup_debug_loc(struct_span.lo()); + (file_metadata(cx, &loc.file), loc.line) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -1051,6 +1066,8 @@ fn build_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, struct_type, false), + file_metadata, + line_number, size_and_align_of(struct_type_and_layout), Some(containing_scope), visibility_di_flags(cx, adt_def.did(), adt_def.did()), @@ -1154,6 +1171,8 @@ fn build_tuple_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, size_and_align_of(tuple_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -1200,6 +1219,8 @@ fn build_closure_env_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, cx.size_and_align_of(closure_env_type), Some(containing_scope), DIFlags::FlagZero, @@ -1231,6 +1252,8 @@ fn build_union_type_di_node<'ll, 'tcx>( Stub::Union, unique_type_id, &type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, size_and_align_of(union_ty_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -1423,6 +1446,8 @@ fn build_vtable_type_di_node<'ll, 'tcx>( Stub::VTableTy { vtable_holder }, unique_type_id, &vtable_type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, (size, pointer_align), NO_SCOPE_METADATA, DIFlags::FlagArtificial, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 100b046cee21..a33347aa2832 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -199,6 +199,8 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &enum_type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, cx.size_and_align_of(enum_type), NO_SCOPE_METADATA, visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()), @@ -274,6 +276,8 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &coroutine_type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, size_and_align_of(coroutine_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -481,6 +485,8 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( variant_index, ), &variant_struct_wrapper_type_name(variant_index), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_or_coroutine_type_and_layout), Some(enum_or_coroutine_type_di_node), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index b3d4a6642a16..4402f2894545 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -204,6 +204,8 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_index, ), variant_def.name.as_str(), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), @@ -286,6 +288,8 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &variant_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, size_and_align_of(coroutine_type_and_layout), Some(coroutine_type_di_node), DIFlags::FlagZero, @@ -351,7 +355,11 @@ enum DiscrResult { impl DiscrResult { fn opt_single_val(&self) -> Option { - if let Self::Value(d) = *self { Some(d) } else { None } + if let Self::Value(d) = *self { + Some(d) + } else { + None + } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index d4006691d377..07c3784efe73 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -62,6 +62,8 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &enum_type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, size_and_align_of(enum_type_and_layout), Some(containing_scope), visibility_flags, @@ -141,6 +143,8 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &coroutine_type_name, + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, size_and_align_of(coroutine_type_and_layout), Some(containing_scope), DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 5120b63d173b..f8f8cf914bae 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::utils::{DIB, create_DIArray, debug_context}; -use crate::llvm::debuginfo::{DIFlags, DIScope, DIType}; +use crate::llvm::debuginfo::{DIFile, DIFlags, DIScope, DIType}; use crate::llvm::{self}; mod private { @@ -174,6 +174,8 @@ pub(super) fn stub<'ll, 'tcx>( kind: Stub<'ll>, unique_type_id: UniqueTypeId<'tcx>, name: &str, + file_metadata: &'ll DIFile, + line_number: u32, (size, align): (Size, Align), containing_scope: Option<&'ll DIScope>, flags: DIFlags, @@ -193,8 +195,8 @@ pub(super) fn stub<'ll, 'tcx>( containing_scope, name.as_c_char_ptr(), name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size.bits(), align.bits() as u32, flags, @@ -213,8 +215,8 @@ pub(super) fn stub<'ll, 'tcx>( containing_scope, name.as_c_char_ptr(), name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size.bits(), align.bits() as u32, flags, From 5b23c38dd56b2695c5af9b801ad14f795d138b1c Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 16 Nov 2022 14:50:31 -0500 Subject: [PATCH 009/330] Add codegen test to validate IR for debuginfo --- tests/codegen/issue-98678.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/codegen/issue-98678.rs diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs new file mode 100644 index 000000000000..72ccbddc59b8 --- /dev/null +++ b/tests/codegen/issue-98678.rs @@ -0,0 +1,11 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata. +// +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] + +// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}src/test/codegen/issue-98678.rs{{".*}}) + +// CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub struct MyType; + +pub fn foo(_: MyType) {} From 94669d9d47e3a594f4179a2aca9997fa1aeea7ad Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 16 Nov 2022 15:37:31 -0500 Subject: [PATCH 010/330] Add file and line metadata for closures --- .../rustc_codegen_llvm/src/debuginfo/metadata.rs | 12 ++++++++++-- tests/codegen/issue-98678.rs | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 6b5f53e40bd5..ebc452286b6e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1212,6 +1212,14 @@ fn build_closure_env_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, def_id); let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false); + let closure_span = cx.tcx.def_span(def_id); + let (file_metadata, line_number) = if !closure_span.is_dummy() { + let loc = cx.lookup_debug_loc(closure_span.lo()); + (file_metadata(cx, &loc.file), loc.line) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -1219,8 +1227,8 @@ fn build_closure_env_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, cx.size_and_align_of(closure_env_type), Some(containing_scope), DIFlags::FlagZero, diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs index 72ccbddc59b8..a6143117b9fd 100644 --- a/tests/codegen/issue-98678.rs +++ b/tests/codegen/issue-98678.rs @@ -8,4 +8,8 @@ // CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], pub struct MyType; -pub fn foo(_: MyType) {} +pub fn foo(_: MyType) { + // CHECK: !DICompositeType({{.*"[{]}}closure_env#0{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let closure = |x| x; + closure(0); +} From f3da8281853bce792a6a4220ccb432500b6b1da5 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 16 Nov 2022 21:31:30 -0500 Subject: [PATCH 011/330] Refactor `type_map::stub` parameters Push span lookup into `type_map::stub` and pass the `DefId` instead of doing the lookup outside and passing in the location metadata. --- .../src/debuginfo/metadata.rs | 41 ++++--------------- .../src/debuginfo/metadata/enums/cpp_like.rs | 14 ++++--- .../src/debuginfo/metadata/enums/mod.rs | 24 +++++------ .../src/debuginfo/metadata/enums/native.rs | 6 +-- .../src/debuginfo/metadata/type_map.rs | 19 +++++++-- tests/codegen/issue-98678.rs | 23 ++++++++++- 6 files changed, 65 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index ebc452286b6e..b8fbedb9d67a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -204,8 +204,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &ptr_type_debuginfo_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, cx.size_and_align_of(ptr_type), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -373,8 +372,7 @@ fn build_dyn_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, cx.size_and_align_of(dyn_type), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -845,8 +843,7 @@ fn build_foreign_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, t, false), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, cx.size_and_align_of(t), Some(get_namespace_for_item(cx, def_id)), DIFlags::FlagZero, @@ -1050,15 +1047,6 @@ fn build_struct_type_di_node<'ll, 'tcx>( let struct_type_and_layout = cx.layout_of(struct_type); let variant_def = adt_def.non_enum_variant(); - let tcx = cx.tcx; - let struct_span = tcx.def_span(adt_def.did()); - let (file_metadata, line_number) = if !struct_span.is_dummy() { - let loc = cx.lookup_debug_loc(struct_span.lo()); - (file_metadata(cx, &loc.file), loc.line) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; - type_map::build_type_with_children( cx, type_map::stub( @@ -1066,8 +1054,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, struct_type, false), - file_metadata, - line_number, + Some(adt_def.did()), size_and_align_of(struct_type_and_layout), Some(containing_scope), visibility_di_flags(cx, adt_def.did(), adt_def.did()), @@ -1171,8 +1158,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, size_and_align_of(tuple_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -1212,14 +1198,6 @@ fn build_closure_env_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, def_id); let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false); - let closure_span = cx.tcx.def_span(def_id); - let (file_metadata, line_number) = if !closure_span.is_dummy() { - let loc = cx.lookup_debug_loc(closure_span.lo()); - (file_metadata(cx, &loc.file), loc.line) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; - type_map::build_type_with_children( cx, type_map::stub( @@ -1227,8 +1205,7 @@ fn build_closure_env_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, - file_metadata, - line_number, + Some(def_id), cx.size_and_align_of(closure_env_type), Some(containing_scope), DIFlags::FlagZero, @@ -1260,8 +1237,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Stub::Union, unique_type_id, &type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + Some(union_def_id), size_and_align_of(union_ty_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -1454,8 +1430,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( Stub::VTableTy { vtable_holder }, unique_type_id, &vtable_type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, (size, pointer_align), NO_SCOPE_METADATA, DIFlags::FlagArtificial, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index a33347aa2832..751880b0cb7d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -199,8 +199,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &enum_type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + Some(enum_adt_def.did()), cx.size_and_align_of(enum_type), NO_SCOPE_METADATA, visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()), @@ -276,8 +275,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &coroutine_type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, size_and_align_of(coroutine_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -332,6 +330,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( variant_index, Cow::from(enum_adt_def.variant(variant_index).name.as_str()), )), + enum_adt_def.did(), ); let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node( @@ -394,6 +393,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (variant_index, variant_name) }), + enum_adt_def.did(), ); let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()); @@ -451,6 +451,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, containing_scope: &'ll DIType, variants: impl Iterator)>, + enum_def_id: rustc_span::def_id::DefId, ) -> &'ll DIType { // Create an enumerator for each variant. super::build_enumeration_type_di_node( @@ -458,6 +459,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( "VariantNames", variant_names_enum_base_type(cx), variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())), + enum_def_id, containing_scope, ) } @@ -485,8 +487,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( variant_index, ), &variant_struct_wrapper_type_name(variant_index), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_or_coroutine_type_and_layout), Some(enum_or_coroutine_type_di_node), @@ -690,6 +691,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( variant_range .clone() .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))), + coroutine_def_id, ); let discriminants: IndexVec = { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 4402f2894545..2a6a21061a3a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -16,8 +16,8 @@ use super::{SmallVec, size_and_align_of}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::metadata::type_map::{self, Stub}; use crate::debuginfo::metadata::{ - UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, type_di_node, - unknown_file_metadata, + UNKNOWN_LINE_NUMBER, build_field_di_node, build_generic_type_param_di_nodes, + file_metadata_from_def_id, type_di_node, unknown_file_metadata, }; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; use crate::llvm::debuginfo::{DIFlags, DIType}; @@ -77,6 +77,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (name, discr.val) }), + enum_adt_def.did(), containing_scope, ), already_stored_in_typemap: false, @@ -92,6 +93,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( type_name: &str, base_type: Ty<'tcx>, enumerators: impl Iterator, u128)>, + def_id: rustc_span::def_id::DefId, containing_scope: &'ll DIType, ) -> &'ll DIType { let is_unsigned = match base_type.kind() { @@ -115,14 +117,16 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( }) .collect(); + let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id)); + unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), containing_scope, type_name.as_c_char_ptr(), type_name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size.bits(), align.bits() as u32, create_DIArray(DIB(cx), &enumerator_di_nodes[..]), @@ -204,8 +208,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_index, ), variant_def.name.as_str(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), @@ -288,8 +291,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &variant_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, size_and_align_of(coroutine_type_and_layout), Some(coroutine_type_di_node), DIFlags::FlagZero, @@ -355,11 +357,7 @@ enum DiscrResult { impl DiscrResult { fn opt_single_val(&self) -> Option { - if let Self::Value(d) = *self { - Some(d) - } else { - None - } + if let Self::Value(d) = *self { Some(d) } else { None } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 07c3784efe73..7e7de7101cf9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -62,8 +62,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &enum_type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + Some(enum_adt_def.did()), size_and_align_of(enum_type_and_layout), Some(containing_scope), visibility_flags, @@ -143,8 +142,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &coroutine_type_name, - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + None, size_and_align_of(coroutine_type_and_layout), Some(containing_scope), DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index f8f8cf914bae..70cc476c93e4 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -8,10 +8,10 @@ use rustc_macros::HashStable; use rustc_middle::bug; use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; -use super::{SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; +use super::{SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::utils::{DIB, create_DIArray, debug_context}; -use crate::llvm::debuginfo::{DIFile, DIFlags, DIScope, DIType}; +use crate::llvm::debuginfo::{DIFlags, DIScope, DIType}; use crate::llvm::{self}; mod private { @@ -174,8 +174,7 @@ pub(super) fn stub<'ll, 'tcx>( kind: Stub<'ll>, unique_type_id: UniqueTypeId<'tcx>, name: &str, - file_metadata: &'ll DIFile, - line_number: u32, + def_id: Option, (size, align): (Size, Align), containing_scope: Option<&'ll DIScope>, flags: DIFlags, @@ -183,6 +182,18 @@ pub(super) fn stub<'ll, 'tcx>( let empty_array = create_DIArray(DIB(cx), &[]); let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx); + let (file_metadata, line_number) = if let Some(def_id) = def_id { + let span = cx.tcx.def_span(def_id); + if !span.is_dummy() { + let loc = cx.lookup_debug_loc(span.lo()); + (file_metadata(cx, &loc.file), loc.line) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + } + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + let metadata = match kind { Stub::Struct | Stub::VTableTy { .. } => { let vtable_holder = match kind { diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs index a6143117b9fd..60283a9dd306 100644 --- a/tests/codegen/issue-98678.rs +++ b/tests/codegen/issue-98678.rs @@ -3,12 +3,31 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] -// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}src/test/codegen/issue-98678.rs{{".*}}) +// The use of CHECK-DAG here is because the C++-like enum is emitted before the `DIFile` node + +// CHECK-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}src/test/codegen/issue-98678.rs{{".*}}) + +// CHECK-DAG: !DICompositeType({{.*"}}MyCppLikeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +#[repr(C)] +pub enum MyCppLikeEnum { + One, +} // CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], pub struct MyType; -pub fn foo(_: MyType) { +// CHECK: !DICompositeType({{.*"}}MyUnion{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub union MyUnion { + i: i32, // TODO fields are still wrong + f: f32, +} + +// CHECK: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum MyNativeEnum { + One, +} + +pub fn foo(_: MyType, _: MyUnion, _: MyNativeEnum, _: MyCppLikeEnum) { // CHECK: !DICompositeType({{.*"[{]}}closure_env#0{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], let closure = |x| x; closure(0); From c07797a85479143c711582f5548aa78d65a1dce0 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 16 Nov 2022 23:12:44 -0500 Subject: [PATCH 012/330] Add file and line metadata for coroutines --- .../src/debuginfo/metadata/enums/cpp_like.rs | 5 ++++- .../src/debuginfo/metadata/enums/native.rs | 2 +- tests/codegen/issue-98678.rs | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 751880b0cb7d..3dd274fbd780 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -263,6 +263,9 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let coroutine_type = unique_type_id.expect_ty(); + let &ty::Coroutine(coroutine_def_id, _, _) = coroutine_type.kind() else { + bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type) + }; let coroutine_type_and_layout = cx.layout_of(coroutine_type); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); @@ -275,7 +278,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &coroutine_type_name, - None, + Some(coroutine_def_id), size_and_align_of(coroutine_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 7e7de7101cf9..4bd7852b55e0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -142,7 +142,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &coroutine_type_name, - None, + Some(coroutine_def_id), size_and_align_of(coroutine_type_and_layout), Some(containing_scope), DIFlags::FlagZero, diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs index 60283a9dd306..2858452670bd 100644 --- a/tests/codegen/issue-98678.rs +++ b/tests/codegen/issue-98678.rs @@ -2,6 +2,7 @@ // // compile-flags: -C debuginfo=2 #![crate_type = "lib"] +#![feature(generators, stmt_expr_attributes)] // The use of CHECK-DAG here is because the C++-like enum is emitted before the `DIFile` node @@ -31,4 +32,8 @@ pub fn foo(_: MyType, _: MyUnion, _: MyNativeEnum, _: MyCppLikeEnum) { // CHECK: !DICompositeType({{.*"[{]}}closure_env#0{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], let closure = |x| x; closure(0); + + // CHECK: !DICompositeType({{.*"[{]}}generator_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let generator = #[coroutine] + || yield 1; } From af6b0deaf38f482c25f4553da24a83e3a18c48cb Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Fri, 18 Nov 2022 13:41:53 -0500 Subject: [PATCH 013/330] Add file and line metadata for struct/union members --- .../src/debuginfo/metadata.rs | 37 ++++++++++++++----- .../src/debuginfo/metadata/enums/cpp_like.rs | 5 +++ .../src/debuginfo/metadata/enums/mod.rs | 3 ++ tests/codegen/issue-98678.rs | 9 ++++- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index b8fbedb9d67a..e9865dee61f9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -261,6 +261,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( layout.fields.offset(abi::WIDE_PTR_ADDR), DIFlags::FlagZero, data_ptr_type_di_node, + None, ), build_field_di_node( cx, @@ -270,6 +271,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( layout.fields.offset(abi::WIDE_PTR_EXTRA), DIFlags::FlagZero, type_di_node(cx, extra_field.ty), + None, ), ] }, @@ -994,15 +996,17 @@ fn build_field_di_node<'ll, 'tcx>( offset: Size, flags: DIFlags, type_di_node: &'ll DIType, + def_id: Option, ) -> &'ll DIType { + let (file_metadata, line_number) = file_metadata_from_def_id(cx, def_id); unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), owner, name.as_c_char_ptr(), name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, size_and_align.0.bits(), size_and_align.1.bits() as u32, offset.bits(), @@ -1082,6 +1086,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( struct_type_and_layout.fields.offset(i), visibility_di_flags(cx, f.did, adt_def.did()), type_di_node(cx, field_layout.ty), + Some(f.did), ) }) .collect() @@ -1133,6 +1138,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, up_var_ty), + None, ) }) .collect() @@ -1177,6 +1183,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>( tuple_type_and_layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, component_type), + None, ) }) .collect() @@ -1258,6 +1265,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Size::ZERO, DIFlags::FlagZero, type_di_node(cx, field_layout.ty), + Some(f.did), ) }) .collect() @@ -1333,14 +1341,7 @@ pub(crate) fn build_global_var_di_node<'ll>( // We may want to remove the namespace scope if we're in an extern block (see // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952). let var_scope = get_namespace_for_item(cx, def_id); - let span = hygiene::walk_chain_collapsed(tcx.def_span(def_id), DUMMY_SP); - - let (file_metadata, line_number) = if !span.is_dummy() { - let loc = cx.lookup_debug_loc(span.lo()); - (file_metadata(cx, &loc.file), loc.line) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; + let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id)); let is_local_to_unit = is_node_local_to_unit(cx, def_id); @@ -1468,6 +1469,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( field_offset, DIFlags::FlagZero, field_type_di_node, + None, )) }) .collect() @@ -1619,3 +1621,18 @@ fn tuple_field_name(field_index: usize) -> Cow<'static, str> { .map(|s| Cow::from(*s)) .unwrap_or_else(|| Cow::from(format!("__{field_index}"))) } + +pub(crate) fn file_metadata_from_def_id<'ll>( + cx: &CodegenCx<'ll, '_>, + def_id: Option, +) -> (&'ll DIFile, c_uint) { + if let Some(def_id) = def_id + && let span = hygiene::walk_chain_collapsed(cx.tcx.def_span(def_id), DUMMY_SP) + && !span.is_dummy() + { + let loc = cx.lookup_debug_loc(span.lo()); + (file_metadata(cx, &loc.file), loc.line) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + } +} diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 3dd274fbd780..6be72bb5055e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -360,6 +360,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( Size::ZERO, visibility_flags, variant_struct_type_wrapper_di_node, + None, ), unsafe { llvm::LLVMRustDIBuilderCreateStaticMemberType( @@ -540,6 +541,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( Size::ZERO, DIFlags::FlagZero, variant_struct_type_di_node, + None, )); let build_assoc_const = @@ -842,6 +844,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( lo_offset, di_flags, type_di_node, + None, )); unions_fields.push(build_field_di_node( @@ -852,6 +855,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( hi_offset, DIFlags::FlagZero, type_di_node, + None, )); } else { unions_fields.push(build_field_di_node( @@ -862,6 +866,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( enum_type_and_layout.fields.offset(tag_field), di_flags, tag_base_type_di_node, + None, )); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 2a6a21061a3a..9b4e992a729d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -236,6 +236,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_layout.fields.offset(field_index), di_flags, type_di_node(cx, field_layout.ty), + None, ) }) .collect::>() @@ -318,6 +319,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( variant_layout.fields.offset(field_index), DIFlags::FlagZero, type_di_node(cx, field_type), + None, ) }) .collect(); @@ -337,6 +339,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( coroutine_type_and_layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, upvar_ty), + None, ) }) .collect(); diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs index 2858452670bd..f67a1e1908d3 100644 --- a/tests/codegen/issue-98678.rs +++ b/tests/codegen/issue-98678.rs @@ -15,11 +15,16 @@ pub enum MyCppLikeEnum { } // CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], -pub struct MyType; +pub struct MyType { + // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + i: i32, +} // CHECK: !DICompositeType({{.*"}}MyUnion{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], pub union MyUnion { - i: i32, // TODO fields are still wrong + // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + i: i32, + // CHECK: !DIDerivedType({{.*"}}f{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], f: f32, } From aa485fc2a1924c71036fa465e7bac6918ab6b275 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 19 Nov 2022 14:44:13 -0500 Subject: [PATCH 014/330] Add file and line metadata for enum variant and fields --- .../src/debuginfo/metadata/enums/cpp_like.rs | 9 ++++++++- .../src/debuginfo/metadata/enums/mod.rs | 2 +- .../src/debuginfo/metadata/enums/native.rs | 17 +++++++++++++---- .../src/debuginfo/metadata/type_map.rs | 12 +----------- tests/codegen/issue-98678.rs | 6 ++++-- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 6be72bb5055e..489530df3a15 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -338,6 +338,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node( cx, + enum_adt_def, enum_type_and_layout, enum_type_di_node, variant_index, @@ -470,6 +471,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, + enum_adt_def: AdtDef<'tcx>, enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>, enum_or_coroutine_type_di_node: &'ll DIType, variant_index: VariantIdx, @@ -491,7 +493,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( variant_index, ), &variant_struct_wrapper_type_name(variant_index), - None, + Some(enum_adt_def.variant(variant_index).def_id), // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_or_coroutine_type_and_layout), Some(enum_or_coroutine_type_di_node), @@ -778,8 +780,13 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( let field_name = variant_union_field_name(variant_member_info.variant_index); let (size, align) = size_and_align_of(enum_type_and_layout); + let ty::Adt(enum_adt_def, _) = enum_type_and_layout.ty.kind() else { + unreachable!(); + }; + let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node( cx, + *enum_adt_def, enum_type_and_layout, enum_type_di_node, variant_member_info.variant_index, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 9b4e992a729d..9974dac5a1de 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -208,7 +208,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_index, ), variant_def.name.as_str(), - None, + Some(variant_def.def_id), // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 4bd7852b55e0..4a7981ddc882 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -14,7 +14,8 @@ use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId}; use crate::debuginfo::metadata::{ DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, - size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags, + file_metadata_from_def_id, size_and_align_of, type_di_node, unknown_file_metadata, + visibility_di_flags, }; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; @@ -85,7 +86,10 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( enum_type_and_layout.for_variant(cx, variant_index), visibility_flags, ), - source_info: None, + source_info: Some(file_metadata_from_def_id( + cx, + Some(enum_adt_def.variant(variant_index).def_id), + )), }) .collect(); @@ -93,6 +97,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( cx, enum_type_and_layout, enum_type_di_node, + enum_adt_def.did(), &variant_member_infos[..], )] }, @@ -203,6 +208,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( cx, coroutine_type_and_layout, coroutine_type_di_node, + coroutine_def_id, &variant_struct_type_di_nodes[..], )] }, @@ -230,6 +236,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, enum_type_di_node: &'ll DIType, + enum_type_def_id: rustc_span::def_id::DefId, variant_member_infos: &[VariantMemberInfo<'_, 'll>], ) -> &'ll DIType { let tag_member_di_node = @@ -238,6 +245,8 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( let variant_part_unique_type_id = UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty); + let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(enum_type_def_id)); + let stub = StubInfo::new( cx, variant_part_unique_type_id, @@ -248,8 +257,8 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( enum_type_di_node, variant_part_name.as_c_char_ptr(), variant_part_name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file_metadata, + line_number, enum_type_and_layout.size.bits(), enum_type_and_layout.align.abi.bits() as u32, DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 70cc476c93e4..1cd86d732eb0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -182,17 +182,7 @@ pub(super) fn stub<'ll, 'tcx>( let empty_array = create_DIArray(DIB(cx), &[]); let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx); - let (file_metadata, line_number) = if let Some(def_id) = def_id { - let span = cx.tcx.def_span(def_id); - if !span.is_dummy() { - let loc = cx.lookup_debug_loc(span.lo()); - (file_metadata(cx, &loc.file), loc.line) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - } - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; + let (file_metadata, line_number) = super::file_metadata_from_def_id(cx, def_id); let metadata = match kind { Stub::Struct | Stub::VTableTy { .. } => { diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs index f67a1e1908d3..ab4e085a317a 100644 --- a/tests/codegen/issue-98678.rs +++ b/tests/codegen/issue-98678.rs @@ -6,7 +6,7 @@ // The use of CHECK-DAG here is because the C++-like enum is emitted before the `DIFile` node -// CHECK-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}src/test/codegen/issue-98678.rs{{".*}}) +// CHECK-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678.rs{{".*}}) // CHECK-DAG: !DICompositeType({{.*"}}MyCppLikeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], #[repr(C)] @@ -28,8 +28,10 @@ pub union MyUnion { f: f32, } -// CHECK: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +// CHECK: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// CHECK: !DICompositeType({{.*}}DW_TAG_variant_part{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], pub enum MyNativeEnum { + // CHECK: !DIDerivedType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], One, } From 27b1b01daa99cd3cb9338e120cc1a26ca31f8833 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 23 Nov 2022 00:02:00 -0500 Subject: [PATCH 015/330] Refactor `type_stub` from `DefId` to tuple --- .../src/debuginfo/metadata.rs | 10 ++++++---- .../src/debuginfo/metadata/enums/cpp_like.rs | 20 ++++++++----------- .../src/debuginfo/metadata/enums/mod.rs | 2 +- .../src/debuginfo/metadata/enums/native.rs | 4 ++-- .../src/debuginfo/metadata/type_map.rs | 12 ++++++++--- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index e9865dee61f9..6099b8ddd422 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1058,7 +1058,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, struct_type, false), - Some(adt_def.did()), + Some(file_metadata_from_def_id(cx, Some(adt_def.did()))), size_and_align_of(struct_type_and_layout), Some(containing_scope), visibility_di_flags(cx, adt_def.did(), adt_def.did()), @@ -1212,7 +1212,7 @@ fn build_closure_env_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, - Some(def_id), + Some(file_metadata_from_def_id(cx, Some(def_id))), cx.size_and_align_of(closure_env_type), Some(containing_scope), DIFlags::FlagZero, @@ -1244,7 +1244,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Stub::Union, unique_type_id, &type_name, - Some(union_def_id), + Some(file_metadata_from_def_id(cx, Some(union_def_id))), size_and_align_of(union_ty_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -1622,10 +1622,12 @@ fn tuple_field_name(field_index: usize) -> Cow<'static, str> { .unwrap_or_else(|| Cow::from(format!("__{field_index}"))) } +pub(crate) type DefinitionLocation<'ll> = (&'ll DIFile, c_uint); + pub(crate) fn file_metadata_from_def_id<'ll>( cx: &CodegenCx<'ll, '_>, def_id: Option, -) -> (&'ll DIFile, c_uint) { +) -> DefinitionLocation<'ll> { if let Some(def_id) = def_id && let span = hygiene::walk_chain_collapsed(cx.tcx.def_span(def_id), DUMMY_SP) && !span.is_dummy() diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 489530df3a15..62e0f9d92be6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -16,8 +16,8 @@ use crate::debuginfo::metadata::enums::DiscrResult; use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId}; use crate::debuginfo::metadata::{ DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER, - build_field_di_node, file_metadata, size_and_align_of, type_di_node, unknown_file_metadata, - visibility_di_flags, + build_field_di_node, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node, + unknown_file_metadata, visibility_di_flags, }; use crate::debuginfo::utils::DIB; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; @@ -199,7 +199,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &enum_type_name, - Some(enum_adt_def.did()), + Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))), cx.size_and_align_of(enum_type), NO_SCOPE_METADATA, visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()), @@ -278,7 +278,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &coroutine_type_name, - Some(coroutine_def_id), + Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))), size_and_align_of(coroutine_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -338,7 +338,6 @@ fn build_single_variant_union_fields<'ll, 'tcx>( let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node( cx, - enum_adt_def, enum_type_and_layout, enum_type_di_node, variant_index, @@ -348,6 +347,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( tag_base_type_di_node, tag_base_type, DiscrResult::NoDiscriminant, + None, ); smallvec![ @@ -471,7 +471,6 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - enum_adt_def: AdtDef<'tcx>, enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>, enum_or_coroutine_type_di_node: &'ll DIType, variant_index: VariantIdx, @@ -481,6 +480,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( tag_base_type_di_node: &'ll DIType, tag_base_type: Ty<'tcx>, discr: DiscrResult, + source_info: Option<(&'ll DIFile, c_uint)>, ) -> &'ll DIType { type_map::build_type_with_children( cx, @@ -493,7 +493,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( variant_index, ), &variant_struct_wrapper_type_name(variant_index), - Some(enum_adt_def.variant(variant_index).def_id), + source_info, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_or_coroutine_type_and_layout), Some(enum_or_coroutine_type_di_node), @@ -780,13 +780,8 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( let field_name = variant_union_field_name(variant_member_info.variant_index); let (size, align) = size_and_align_of(enum_type_and_layout); - let ty::Adt(enum_adt_def, _) = enum_type_and_layout.ty.kind() else { - unreachable!(); - }; - let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node( cx, - *enum_adt_def, enum_type_and_layout, enum_type_di_node, variant_member_info.variant_index, @@ -796,6 +791,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( tag_base_type_di_node, tag_base_type, variant_member_info.discr, + variant_member_info.source_info, ); // We use LLVMRustDIBuilderCreateMemberType() member type directly because diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 9974dac5a1de..754395257ee6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -208,7 +208,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_index, ), variant_def.name.as_str(), - Some(variant_def.def_id), + Some(file_metadata_from_def_id(cx, Some(variant_def.def_id))), // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 4a7981ddc882..604e9bab0778 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -63,7 +63,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &enum_type_name, - Some(enum_adt_def.did()), + Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))), size_and_align_of(enum_type_and_layout), Some(containing_scope), visibility_flags, @@ -147,7 +147,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &coroutine_type_name, - Some(coroutine_def_id), + Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))), size_and_align_of(coroutine_type_and_layout), Some(containing_scope), DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 1cd86d732eb0..a6b399d76696 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -8,7 +8,9 @@ use rustc_macros::HashStable; use rustc_middle::bug; use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; -use super::{SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, unknown_file_metadata}; +use super::{ + DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, unknown_file_metadata, +}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::utils::{DIB, create_DIArray, debug_context}; use crate::llvm::debuginfo::{DIFlags, DIScope, DIType}; @@ -174,7 +176,7 @@ pub(super) fn stub<'ll, 'tcx>( kind: Stub<'ll>, unique_type_id: UniqueTypeId<'tcx>, name: &str, - def_id: Option, + def_location: Option>, (size, align): (Size, Align), containing_scope: Option<&'ll DIScope>, flags: DIFlags, @@ -182,7 +184,11 @@ pub(super) fn stub<'ll, 'tcx>( let empty_array = create_DIArray(DIB(cx), &[]); let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx); - let (file_metadata, line_number) = super::file_metadata_from_def_id(cx, def_id); + let (file_metadata, line_number) = if let Some(def_location) = def_location { + (def_location.0, def_location.1) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; let metadata = match kind { Stub::Struct | Stub::VTableTy { .. } => { From cc4f214a785643198dbaf34d21b2b0836ff3dda6 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 21 Jan 2023 13:57:16 -0500 Subject: [PATCH 016/330] Split metadata testing into multiple files This helps with the fact that the order in which debuginfo is emitted differs between platforms, and is probably not guaranteed to be stable in general. --- .../codegen/issue-98678-closure-generator.rs | 18 ++++++++ tests/codegen/issue-98678-cpp-like-enum.rs | 17 +++++++ tests/codegen/issue-98678-native-enum.rs | 16 +++++++ tests/codegen/issue-98678-struct-union.rs | 23 ++++++++++ tests/codegen/issue-98678.rs | 46 ------------------- 5 files changed, 74 insertions(+), 46 deletions(-) create mode 100644 tests/codegen/issue-98678-closure-generator.rs create mode 100644 tests/codegen/issue-98678-cpp-like-enum.rs create mode 100644 tests/codegen/issue-98678-native-enum.rs create mode 100644 tests/codegen/issue-98678-struct-union.rs delete mode 100644 tests/codegen/issue-98678.rs diff --git a/tests/codegen/issue-98678-closure-generator.rs b/tests/codegen/issue-98678-closure-generator.rs new file mode 100644 index 000000000000..b24f6e21c93e --- /dev/null +++ b/tests/codegen/issue-98678-closure-generator.rs @@ -0,0 +1,18 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for closures and +// generators. +// +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] +#![feature(generators, stmt_expr_attributes)] + +// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-closure-generator.rs{{".*}}) + +pub fn foo() { + // CHECK: !DICompositeType({{.*"[{]}}closure_env#0{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let closure = |x| x; + closure(0); + + // CHECK: !DICompositeType({{.*"[{]}}generator_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let generator = #[coroutine] + || yield 1; +} diff --git a/tests/codegen/issue-98678-cpp-like-enum.rs b/tests/codegen/issue-98678-cpp-like-enum.rs new file mode 100644 index 000000000000..30ea6cd9577a --- /dev/null +++ b/tests/codegen/issue-98678-cpp-like-enum.rs @@ -0,0 +1,17 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for C++-like +// enumerations. +// +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] + +// The use of CHECK-DAG here is because the C++-like enum is emitted before the `DIFile` node + +// CHECK-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-cpp-like-enum.rs{{".*}}) + +// CHECK-DAG: !DICompositeType({{.*"}}MyCppLikeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +#[repr(C)] +pub enum MyCppLikeEnum { + One, +} + +pub fn foo(_: MyCppLikeEnum) {} diff --git a/tests/codegen/issue-98678-native-enum.rs b/tests/codegen/issue-98678-native-enum.rs new file mode 100644 index 000000000000..073cc60f77a4 --- /dev/null +++ b/tests/codegen/issue-98678-native-enum.rs @@ -0,0 +1,16 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for native +// enumerations. +// +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] + +// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-native-enum.rs{{".*}}) + +// CHECK: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// CHECK: !DICompositeType({{.*}}DW_TAG_variant_part{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum MyNativeEnum { + // CHECK: !DIDerivedType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + One, +} + +pub fn foo(_: MyNativeEnum) {} diff --git a/tests/codegen/issue-98678-struct-union.rs b/tests/codegen/issue-98678-struct-union.rs new file mode 100644 index 000000000000..4b6106eb1da8 --- /dev/null +++ b/tests/codegen/issue-98678-struct-union.rs @@ -0,0 +1,23 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for structs and +// unions. +// +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] + +// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-struct-union.rs{{".*}}) + +// CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub struct MyType { + // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + i: i32, +} + +// CHECK: !DICompositeType({{.*"}}MyUnion{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub union MyUnion { + // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + i: i32, + // CHECK: !DIDerivedType({{.*"}}f{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + f: f32, +} + +pub fn foo(_: MyType, _: MyUnion) {} diff --git a/tests/codegen/issue-98678.rs b/tests/codegen/issue-98678.rs deleted file mode 100644 index ab4e085a317a..000000000000 --- a/tests/codegen/issue-98678.rs +++ /dev/null @@ -1,46 +0,0 @@ -// This test verifies the accuracy of emitted file and line debuginfo metadata. -// -// compile-flags: -C debuginfo=2 -#![crate_type = "lib"] -#![feature(generators, stmt_expr_attributes)] - -// The use of CHECK-DAG here is because the C++-like enum is emitted before the `DIFile` node - -// CHECK-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678.rs{{".*}}) - -// CHECK-DAG: !DICompositeType({{.*"}}MyCppLikeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], -#[repr(C)] -pub enum MyCppLikeEnum { - One, -} - -// CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], -pub struct MyType { - // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - i: i32, -} - -// CHECK: !DICompositeType({{.*"}}MyUnion{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], -pub union MyUnion { - // CHECK: !DIDerivedType({{.*"}}i{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - i: i32, - // CHECK: !DIDerivedType({{.*"}}f{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - f: f32, -} - -// CHECK: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], -// CHECK: !DICompositeType({{.*}}DW_TAG_variant_part{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], -pub enum MyNativeEnum { - // CHECK: !DIDerivedType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - One, -} - -pub fn foo(_: MyType, _: MyUnion, _: MyNativeEnum, _: MyCppLikeEnum) { - // CHECK: !DICompositeType({{.*"[{]}}closure_env#0{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - let closure = |x| x; - closure(0); - - // CHECK: !DICompositeType({{.*"[{]}}generator_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - let generator = #[coroutine] - || yield 1; -} From 937a00b78cd5ddda46b1917666f3fc5477814476 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 21 Jan 2023 14:00:35 -0500 Subject: [PATCH 017/330] Separate NONMSVC and MSVC checks --- tests/codegen/issue-98678-closure-generator.rs | 9 ++++++--- tests/codegen/issue-98678-cpp-like-enum.rs | 5 ++--- tests/codegen/issue-98678-native-enum.rs | 12 ++++++++---- tests/codegen/issue-98678-struct-union.rs | 3 ++- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/codegen/issue-98678-closure-generator.rs b/tests/codegen/issue-98678-closure-generator.rs index b24f6e21c93e..e5272d560a94 100644 --- a/tests/codegen/issue-98678-closure-generator.rs +++ b/tests/codegen/issue-98678-closure-generator.rs @@ -5,14 +5,17 @@ #![crate_type = "lib"] #![feature(generators, stmt_expr_attributes)] -// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-closure-generator.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-closure-generator.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-closure-generator.rs{{".*}}) pub fn foo() { - // CHECK: !DICompositeType({{.*"[{]}}closure_env#0{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + // NONMSVC: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*"}}closure_env$0{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], let closure = |x| x; closure(0); - // CHECK: !DICompositeType({{.*"[{]}}generator_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + // NONMSVC: !DICompositeType({{.*"[{]}}generator_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*".*foo::}}generator_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], let generator = #[coroutine] || yield 1; } diff --git a/tests/codegen/issue-98678-cpp-like-enum.rs b/tests/codegen/issue-98678-cpp-like-enum.rs index 30ea6cd9577a..fe6dfe8dc874 100644 --- a/tests/codegen/issue-98678-cpp-like-enum.rs +++ b/tests/codegen/issue-98678-cpp-like-enum.rs @@ -4,9 +4,8 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] -// The use of CHECK-DAG here is because the C++-like enum is emitted before the `DIFile` node - -// CHECK-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-cpp-like-enum.rs{{".*}}) +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-cpp-like-enum.rs{{".*}}) +// MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-cpp-like-enum.rs{{".*}}) // CHECK-DAG: !DICompositeType({{.*"}}MyCppLikeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], #[repr(C)] diff --git a/tests/codegen/issue-98678-native-enum.rs b/tests/codegen/issue-98678-native-enum.rs index 073cc60f77a4..295e83f25a93 100644 --- a/tests/codegen/issue-98678-native-enum.rs +++ b/tests/codegen/issue-98678-native-enum.rs @@ -4,12 +4,16 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] -// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-native-enum.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-native-enum.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-native-enum.rs{{".*}}) -// CHECK: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], -// CHECK: !DICompositeType({{.*}}DW_TAG_variant_part{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +// NONMSVC: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 4]], +// MSVC: !DICompositeType({{.*::}}MyNativeEnum>{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 3]], +// NONMSVC: !DICompositeType({{.*}}DW_TAG_variant_part{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// COM: MSVC: currently no DW_TAG_variant_part from MSVC pub enum MyNativeEnum { - // CHECK: !DIDerivedType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + // NONMSVC: !DIDerivedType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC: !DICompositeType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], One, } diff --git a/tests/codegen/issue-98678-struct-union.rs b/tests/codegen/issue-98678-struct-union.rs index 4b6106eb1da8..904eea8d16f0 100644 --- a/tests/codegen/issue-98678-struct-union.rs +++ b/tests/codegen/issue-98678-struct-union.rs @@ -4,7 +4,8 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] -// CHECK: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-struct-union.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-struct-union.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-struct-union.rs{{".*}}) // CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], pub struct MyType { From f92fc886f447c29242e0fa7856dbfc810801ed62 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 21 Jan 2023 14:02:34 -0500 Subject: [PATCH 018/330] Allow check lines to exceed normal length limit --- tests/codegen/issue-98678-closure-generator.rs | 2 ++ tests/codegen/issue-98678-cpp-like-enum.rs | 2 ++ tests/codegen/issue-98678-native-enum.rs | 2 ++ tests/codegen/issue-98678-struct-union.rs | 2 ++ 4 files changed, 8 insertions(+) diff --git a/tests/codegen/issue-98678-closure-generator.rs b/tests/codegen/issue-98678-closure-generator.rs index e5272d560a94..140515e7a9e0 100644 --- a/tests/codegen/issue-98678-closure-generator.rs +++ b/tests/codegen/issue-98678-closure-generator.rs @@ -5,6 +5,8 @@ #![crate_type = "lib"] #![feature(generators, stmt_expr_attributes)] +// ignore-tidy-linelength + // NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-closure-generator.rs{{".*}}) // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-closure-generator.rs{{".*}}) diff --git a/tests/codegen/issue-98678-cpp-like-enum.rs b/tests/codegen/issue-98678-cpp-like-enum.rs index fe6dfe8dc874..fb3da3d8dbc8 100644 --- a/tests/codegen/issue-98678-cpp-like-enum.rs +++ b/tests/codegen/issue-98678-cpp-like-enum.rs @@ -4,6 +4,8 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] +// ignore-tidy-linelength + // NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-cpp-like-enum.rs{{".*}}) // MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-cpp-like-enum.rs{{".*}}) diff --git a/tests/codegen/issue-98678-native-enum.rs b/tests/codegen/issue-98678-native-enum.rs index 295e83f25a93..0a520c185578 100644 --- a/tests/codegen/issue-98678-native-enum.rs +++ b/tests/codegen/issue-98678-native-enum.rs @@ -4,6 +4,8 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] +// ignore-tidy-linelength + // NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-native-enum.rs{{".*}}) // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-native-enum.rs{{".*}}) diff --git a/tests/codegen/issue-98678-struct-union.rs b/tests/codegen/issue-98678-struct-union.rs index 904eea8d16f0..36f37c0e826e 100644 --- a/tests/codegen/issue-98678-struct-union.rs +++ b/tests/codegen/issue-98678-struct-union.rs @@ -4,6 +4,8 @@ // compile-flags: -C debuginfo=2 #![crate_type = "lib"] +// ignore-tidy-linelength + // NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-struct-union.rs{{".*}}) // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-struct-union.rs{{".*}}) From aa1a16a359345502bc4bf2186accf6871dc06b2d Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 21 Jan 2023 16:04:42 -0500 Subject: [PATCH 019/330] Add test for async function and async block --- tests/codegen/issue-98678-async.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/codegen/issue-98678-async.rs diff --git a/tests/codegen/issue-98678-async.rs b/tests/codegen/issue-98678-async.rs new file mode 100644 index 000000000000..e937cfaddc67 --- /dev/null +++ b/tests/codegen/issue-98678-async.rs @@ -0,0 +1,25 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata for async blocks and +// async functions. +// +// edition: 2021 +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] + +// ignore-tidy-linelength + +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-async.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-async.rs{{".*}}) + +// NONMSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub async fn foo() -> u8 { 5 } + +pub fn bar() -> impl std::future::Future { + // NONMSVC: !DICompositeType({{.*"}}{async_block_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*"}}enum2${{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + async { + let x: u8 = foo().await; + x + 5 + } + +} From fc59f2c28cd72fe9976c1310b243720f9d1acdea Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 21 Jan 2023 19:06:13 -0500 Subject: [PATCH 020/330] Refactor and expand enum test --- tests/codegen/issue-98678-cpp-like-enum.rs | 18 ---------- tests/codegen/issue-98678-enum.rs | 41 ++++++++++++++++++++++ tests/codegen/issue-98678-native-enum.rs | 22 ------------ 3 files changed, 41 insertions(+), 40 deletions(-) delete mode 100644 tests/codegen/issue-98678-cpp-like-enum.rs create mode 100644 tests/codegen/issue-98678-enum.rs delete mode 100644 tests/codegen/issue-98678-native-enum.rs diff --git a/tests/codegen/issue-98678-cpp-like-enum.rs b/tests/codegen/issue-98678-cpp-like-enum.rs deleted file mode 100644 index fb3da3d8dbc8..000000000000 --- a/tests/codegen/issue-98678-cpp-like-enum.rs +++ /dev/null @@ -1,18 +0,0 @@ -// This test verifies the accuracy of emitted file and line debuginfo metadata for C++-like -// enumerations. -// -// compile-flags: -C debuginfo=2 -#![crate_type = "lib"] - -// ignore-tidy-linelength - -// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-cpp-like-enum.rs{{".*}}) -// MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-cpp-like-enum.rs{{".*}}) - -// CHECK-DAG: !DICompositeType({{.*"}}MyCppLikeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], -#[repr(C)] -pub enum MyCppLikeEnum { - One, -} - -pub fn foo(_: MyCppLikeEnum) {} diff --git a/tests/codegen/issue-98678-enum.rs b/tests/codegen/issue-98678-enum.rs new file mode 100644 index 000000000000..a5bc6688b304 --- /dev/null +++ b/tests/codegen/issue-98678-enum.rs @@ -0,0 +1,41 @@ +// This test verifies the accuracy of emitted file and line debuginfo metadata enums. +// +// compile-flags: -C debuginfo=2 +#![crate_type = "lib"] + +// ignore-tidy-linelength + +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-enum.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-enum.rs{{".*}}) + +// NONMSVC: !DICompositeType({{.*"}}SingleCase{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC: !DICompositeType({{.*"}}enum2${{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum SingleCase { + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "One",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "One",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + One, +} + +// NONMSVC: !DICompositeType({{.*"}}MultipleDataCases{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC: !DICompositeType({{.*"}}enum2${{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum MultipleDataCases { + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Case1",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Case1",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Case1(u32), + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Case2",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Case2",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Case2(i64), +} + +// NONMSVC: !DICompositeType({{.*"}}NicheLayout{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], +// MSVC: !DICompositeType({{.*"}}enum2${{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], +pub enum NicheLayout { + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Something",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Something",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Something(&'static u32), + // NONMSVC: !DIDerivedType(tag: DW_TAG_member, name: "Nothing",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Nothing",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + Nothing, +} + +pub fn foo(_: SingleCase, _: MultipleDataCases, _: NicheLayout) {} diff --git a/tests/codegen/issue-98678-native-enum.rs b/tests/codegen/issue-98678-native-enum.rs deleted file mode 100644 index 0a520c185578..000000000000 --- a/tests/codegen/issue-98678-native-enum.rs +++ /dev/null @@ -1,22 +0,0 @@ -// This test verifies the accuracy of emitted file and line debuginfo metadata for native -// enumerations. -// -// compile-flags: -C debuginfo=2 -#![crate_type = "lib"] - -// ignore-tidy-linelength - -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-native-enum.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-native-enum.rs{{".*}}) - -// NONMSVC: !DICompositeType({{.*"}}MyNativeEnum{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 4]], -// MSVC: !DICompositeType({{.*::}}MyNativeEnum>{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 3]], -// NONMSVC: !DICompositeType({{.*}}DW_TAG_variant_part{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], -// COM: MSVC: currently no DW_TAG_variant_part from MSVC -pub enum MyNativeEnum { - // NONMSVC: !DIDerivedType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], - // MSVC: !DICompositeType({{.*"}}One{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - One, -} - -pub fn foo(_: MyNativeEnum) {} From b6659b062141c0902acedbc9d8e500cc17433453 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 29 Jul 2023 22:39:44 -0400 Subject: [PATCH 021/330] Move tests into issues directory --- tests/codegen/{ => issues}/issue-98678-async.rs | 0 tests/codegen/{ => issues}/issue-98678-closure-generator.rs | 0 tests/codegen/{ => issues}/issue-98678-enum.rs | 0 tests/codegen/{ => issues}/issue-98678-struct-union.rs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename tests/codegen/{ => issues}/issue-98678-async.rs (100%) rename tests/codegen/{ => issues}/issue-98678-closure-generator.rs (100%) rename tests/codegen/{ => issues}/issue-98678-enum.rs (100%) rename tests/codegen/{ => issues}/issue-98678-struct-union.rs (100%) diff --git a/tests/codegen/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs similarity index 100% rename from tests/codegen/issue-98678-async.rs rename to tests/codegen/issues/issue-98678-async.rs diff --git a/tests/codegen/issue-98678-closure-generator.rs b/tests/codegen/issues/issue-98678-closure-generator.rs similarity index 100% rename from tests/codegen/issue-98678-closure-generator.rs rename to tests/codegen/issues/issue-98678-closure-generator.rs diff --git a/tests/codegen/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs similarity index 100% rename from tests/codegen/issue-98678-enum.rs rename to tests/codegen/issues/issue-98678-enum.rs diff --git a/tests/codegen/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs similarity index 100% rename from tests/codegen/issue-98678-struct-union.rs rename to tests/codegen/issues/issue-98678-struct-union.rs From a4833a80893612a8e97b65777caa1c5f87d38c2c Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 29 Jul 2023 23:48:54 -0400 Subject: [PATCH 022/330] Move additional source location info behind -Z option --- .../src/debuginfo/metadata.rs | 37 ++++++++++++-- .../src/debuginfo/metadata/enums/cpp_like.rs | 49 +++++++++++++++---- .../src/debuginfo/metadata/enums/mod.rs | 24 +++++++-- .../src/debuginfo/metadata/enums/native.rs | 15 +++++- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 + tests/codegen/issues/issue-98678-async.rs | 11 +++-- .../issues/issue-98678-closure-generator.rs | 6 +-- tests/codegen/issues/issue-98678-enum.rs | 6 +-- .../issues/issue-98678-struct-union.rs | 6 +-- 10 files changed, 123 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 6099b8ddd422..10264af65f40 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -998,7 +998,12 @@ fn build_field_di_node<'ll, 'tcx>( type_di_node: &'ll DIType, def_id: Option, ) -> &'ll DIType { - let (file_metadata, line_number) = file_metadata_from_def_id(cx, def_id); + let (file_metadata, line_number) = + if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + file_metadata_from_def_id(cx, def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), @@ -1050,6 +1055,11 @@ fn build_struct_type_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, adt_def.did()); let struct_type_and_layout = cx.layout_of(struct_type); let variant_def = adt_def.non_enum_variant(); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(adt_def.did()))) + } else { + None + }; type_map::build_type_with_children( cx, @@ -1058,7 +1068,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &compute_debuginfo_type_name(cx.tcx, struct_type, false), - Some(file_metadata_from_def_id(cx, Some(adt_def.did()))), + def_location, size_and_align_of(struct_type_and_layout), Some(containing_scope), visibility_di_flags(cx, adt_def.did(), adt_def.did()), @@ -1078,6 +1088,12 @@ fn build_struct_type_di_node<'ll, 'tcx>( Cow::Borrowed(f.name.as_str()) }; let field_layout = struct_type_and_layout.field(cx, i); + let def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo + { + Some(f.did) + } else { + None + }; build_field_di_node( cx, owner, @@ -1086,7 +1102,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( struct_type_and_layout.fields.offset(i), visibility_di_flags(cx, f.did, adt_def.did()), type_di_node(cx, field_layout.ty), - Some(f.did), + def_id, ) }) .collect() @@ -1236,6 +1252,11 @@ fn build_union_type_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, union_def_id); let union_ty_and_layout = cx.layout_of(union_type); let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(union_def_id))) + } else { + None + }; type_map::build_type_with_children( cx, @@ -1244,7 +1265,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Stub::Union, unique_type_id, &type_name, - Some(file_metadata_from_def_id(cx, Some(union_def_id))), + def_location, size_and_align_of(union_ty_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -1257,6 +1278,12 @@ fn build_union_type_di_node<'ll, 'tcx>( .enumerate() .map(|(i, f)| { let field_layout = union_ty_and_layout.field(cx, i); + let def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo + { + Some(f.did) + } else { + None + }; build_field_di_node( cx, owner, @@ -1265,7 +1292,7 @@ fn build_union_type_di_node<'ll, 'tcx>( Size::ZERO, DIFlags::FlagZero, type_di_node(cx, field_layout.ty), - Some(f.did), + def_id, ) }) .collect() diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 62e0f9d92be6..83a0af851bd9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -192,6 +192,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -199,7 +205,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &enum_type_name, - Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))), + def_location, cx.size_and_align_of(enum_type), NO_SCOPE_METADATA, visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()), @@ -263,8 +269,13 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let coroutine_type = unique_type_id.expect_ty(); - let &ty::Coroutine(coroutine_def_id, _, _) = coroutine_type.kind() else { - bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type) + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else { + bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type) + }; + Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))) + } else { + None }; let coroutine_type_and_layout = cx.layout_of(coroutine_type); let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); @@ -278,7 +289,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( type_map::Stub::Union, unique_type_id, &coroutine_type_name, - Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))), + def_location, size_and_align_of(coroutine_type_and_layout), NO_SCOPE_METADATA, DIFlags::FlagZero, @@ -326,6 +337,12 @@ fn build_single_variant_union_fields<'ll, 'tcx>( let tag_base_type_di_node = type_di_node(cx, tag_base_type); let tag_base_type_align = cx.align_of(tag_base_type); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(enum_adt_def.did()) + } else { + None + }; + let variant_names_type_di_node = build_variant_names_type_di_node( cx, enum_type_di_node, @@ -333,7 +350,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( variant_index, Cow::from(enum_adt_def.variant(variant_index).name.as_str()), )), - enum_adt_def.did(), + enum_adt_def_id, ); let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node( @@ -391,6 +408,12 @@ fn build_union_fields_for_enum<'ll, 'tcx>( ) -> SmallVec<&'ll DIType> { let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(enum_adt_def.did()) + } else { + None + }; + let variant_names_type_di_node = build_variant_names_type_di_node( cx, enum_type_di_node, @@ -398,7 +421,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (variant_index, variant_name) }), - enum_adt_def.did(), + enum_adt_def_id, ); let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()); @@ -456,7 +479,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, containing_scope: &'ll DIType, variants: impl Iterator)>, - enum_def_id: rustc_span::def_id::DefId, + enum_def_id: Option, ) -> &'ll DIType { // Create an enumerator for each variant. super::build_enumeration_type_di_node( @@ -698,7 +721,11 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( variant_range .clone() .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))), - coroutine_def_id, + if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(coroutine_def_id) + } else { + None + }, ); let discriminants: IndexVec = { @@ -791,7 +818,11 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( tag_base_type_di_node, tag_base_type, variant_member_info.discr, - variant_member_info.source_info, + if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + variant_member_info.source_info + } else { + None + }, ); // We use LLVMRustDIBuilderCreateMemberType() member type directly because diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 754395257ee6..16ae8dc37e53 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -68,6 +68,11 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( enum_type_and_layout: TyAndLayout<'tcx>, ) -> DINodeCreationResult<'ll> { let containing_scope = get_namespace_for_item(cx, enum_adt_def.did()); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(enum_adt_def.did()) + } else { + None + }; DINodeCreationResult { di_node: build_enumeration_type_di_node( cx, @@ -77,7 +82,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); (name, discr.val) }), - enum_adt_def.did(), + enum_adt_def_id, containing_scope, ), already_stored_in_typemap: false, @@ -93,7 +98,7 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( type_name: &str, base_type: Ty<'tcx>, enumerators: impl Iterator, u128)>, - def_id: rustc_span::def_id::DefId, + def_id: Option, containing_scope: &'ll DIType, ) -> &'ll DIType { let is_unsigned = match base_type.kind() { @@ -117,7 +122,12 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( }) .collect(); - let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id)); + let (file_metadata, line_number) = + if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + file_metadata_from_def_id(cx, def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( @@ -197,6 +207,12 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( ) -> &'ll DIType { assert_eq!(variant_layout.ty, enum_type_and_layout.ty); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(variant_def.def_id))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -208,7 +224,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( variant_index, ), variant_def.name.as_str(), - Some(file_metadata_from_def_id(cx, Some(variant_def.def_id))), + def_location, // NOTE: We use size and align of enum_type, not from variant_layout: size_and_align_of(enum_type_and_layout), Some(enum_type_di_node), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 604e9bab0778..0d289d8995d5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -140,6 +140,12 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -147,7 +153,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &coroutine_type_name, - Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))), + def_location, size_and_align_of(coroutine_type_and_layout), Some(containing_scope), DIFlags::FlagZero, @@ -245,7 +251,12 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( let variant_part_unique_type_id = UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty); - let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(enum_type_def_id)); + let (file_metadata, line_number) = + if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + file_metadata_from_def_id(cx, Some(enum_type_def_id)) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; let stub = StubInfo::new( cx, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ce90ceeda561..732c2e3aa148 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -709,6 +709,7 @@ fn test_unstable_options_tracking_hash() { untracked!(macro_backtrace, true); untracked!(meta_stats, true); untracked!(mir_include_spans, MirIncludeSpans::On); + untracked!(more_source_locations_in_debuginfo, true); untracked!(nll_facts, true); untracked!(no_analysis, true); untracked!(no_leak_check, true); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 087ba0522ebe..883894f473c2 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1907,6 +1907,8 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")] mir_opt_level: Option = (None, parse_opt_number, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), + more_source_locations_in_debuginfo: bool = (false, parse_bool, [UNTRACKED], + "include additional source file and line number information in debuginfo (default: no)"), move_size_limit: Option = (None, parse_opt_number, [TRACKED], "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs index e937cfaddc67..92e11d055694 100644 --- a/tests/codegen/issues/issue-98678-async.rs +++ b/tests/codegen/issues/issue-98678-async.rs @@ -2,17 +2,19 @@ // async functions. // // edition: 2021 -// compile-flags: -C debuginfo=2 +// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo=true #![crate_type = "lib"] // ignore-tidy-linelength -// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-async.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-async.rs{{".*}}) +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-async.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-async.rs{{".*}}) // NONMSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], // MSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], -pub async fn foo() -> u8 { 5 } +pub async fn foo() -> u8 { + 5 +} pub fn bar() -> impl std::future::Future { // NONMSVC: !DICompositeType({{.*"}}{async_block_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], @@ -21,5 +23,4 @@ pub fn bar() -> impl std::future::Future { let x: u8 = foo().await; x + 5 } - } diff --git a/tests/codegen/issues/issue-98678-closure-generator.rs b/tests/codegen/issues/issue-98678-closure-generator.rs index 140515e7a9e0..a12efd495f9b 100644 --- a/tests/codegen/issues/issue-98678-closure-generator.rs +++ b/tests/codegen/issues/issue-98678-closure-generator.rs @@ -1,14 +1,14 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for closures and // generators. // -// compile-flags: -C debuginfo=2 +// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo #![crate_type = "lib"] #![feature(generators, stmt_expr_attributes)] // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-closure-generator.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-closure-generator.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-closure-generator.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-generator.rs{{".*}}) pub fn foo() { // NONMSVC: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs index a5bc6688b304..8005c6c24eee 100644 --- a/tests/codegen/issues/issue-98678-enum.rs +++ b/tests/codegen/issues/issue-98678-enum.rs @@ -1,12 +1,12 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata enums. // -// compile-flags: -C debuginfo=2 +// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo #![crate_type = "lib"] // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-enum.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-enum.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-enum.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-enum.rs{{".*}}) // NONMSVC: !DICompositeType({{.*"}}SingleCase{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], // MSVC: !DICompositeType({{.*"}}enum2${{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs index 36f37c0e826e..3876ae46186e 100644 --- a/tests/codegen/issues/issue-98678-struct-union.rs +++ b/tests/codegen/issues/issue-98678-struct-union.rs @@ -1,13 +1,13 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for structs and // unions. // -// compile-flags: -C debuginfo=2 +// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo #![crate_type = "lib"] // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/codegen/issue-98678-struct-union.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\codegen\\issue-98678-struct-union.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-struct-union.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-struct-union.rs{{".*}}) // CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], pub struct MyType { From 4692d46a461502ed5732a80cd0848db50cfc678a Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sun, 30 Jul 2023 00:04:47 -0400 Subject: [PATCH 023/330] Add additional option checks --- .../src/debuginfo/metadata.rs | 8 +++- .../src/debuginfo/metadata/enums/native.rs | 39 +++++++++++++++---- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 10264af65f40..0a442f44a8db 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1221,6 +1221,12 @@ fn build_closure_env_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, def_id); let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(def_id))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -1228,7 +1234,7 @@ fn build_closure_env_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &type_name, - Some(file_metadata_from_def_id(cx, Some(def_id))), + def_location, cx.size_and_align_of(closure_env_type), Some(containing_scope), DIFlags::FlagZero, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 0d289d8995d5..326aba7d2f3b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -56,6 +56,12 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); + let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))) + } else { + None + }; + type_map::build_type_with_children( cx, type_map::stub( @@ -63,7 +69,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( Stub::Struct, unique_type_id, &enum_type_name, - Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))), + def_location, size_and_align_of(enum_type_and_layout), Some(containing_scope), visibility_flags, @@ -86,18 +92,29 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( enum_type_and_layout.for_variant(cx, variant_index), visibility_flags, ), - source_info: Some(file_metadata_from_def_id( - cx, - Some(enum_adt_def.variant(variant_index).def_id), - )), + source_info: if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo + { + Some(file_metadata_from_def_id( + cx, + Some(enum_adt_def.variant(variant_index).def_id), + )) + } else { + None + }, }) .collect(); + let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo + { + Some(enum_adt_def.did()) + } else { + None + }; smallvec![build_enum_variant_part_di_node( cx, enum_type_and_layout, enum_type_di_node, - enum_adt_def.did(), + enum_adt_def_id, &variant_member_infos[..], )] }, @@ -210,6 +227,12 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( }) .collect(); + let generator_def_id = + if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + Some(generator_def_id) + } else { + None + }; smallvec![build_enum_variant_part_di_node( cx, coroutine_type_and_layout, @@ -242,7 +265,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type_and_layout: TyAndLayout<'tcx>, enum_type_di_node: &'ll DIType, - enum_type_def_id: rustc_span::def_id::DefId, + enum_type_def_id: Option, variant_member_infos: &[VariantMemberInfo<'_, 'll>], ) -> &'ll DIType { let tag_member_di_node = @@ -253,7 +276,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { - file_metadata_from_def_id(cx, Some(enum_type_def_id)) + file_metadata_from_def_id(cx, enum_type_def_id) } else { (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) }; From 21c58b1b2ca37b6a09a1302b035a30878bffd96a Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Fri, 1 Mar 2024 23:33:46 -0500 Subject: [PATCH 024/330] Rename option and add doc --- .../src/debuginfo/metadata.rs | 24 +++++++------- .../src/debuginfo/metadata/enums/cpp_like.rs | 12 +++---- .../src/debuginfo/metadata/enums/mod.rs | 16 ++++----- .../src/debuginfo/metadata/enums/native.rs | 33 +++++++++---------- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 +-- .../debug_info_type_line_numbers.md | 7 ++++ tests/codegen/issues/issue-98678-async.rs | 2 +- .../issues/issue-98678-closure-generator.rs | 2 +- tests/codegen/issues/issue-98678-enum.rs | 2 +- .../issues/issue-98678-struct-union.rs | 2 +- 11 files changed, 54 insertions(+), 52 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 0a442f44a8db..d68da52be11e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -998,12 +998,12 @@ fn build_field_di_node<'ll, 'tcx>( type_di_node: &'ll DIType, def_id: Option, ) -> &'ll DIType { - let (file_metadata, line_number) = - if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { - file_metadata_from_def_id(cx, def_id) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; + let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers + { + file_metadata_from_def_id(cx, def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), @@ -1055,7 +1055,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, adt_def.did()); let struct_type_and_layout = cx.layout_of(struct_type); let variant_def = adt_def.non_enum_variant(); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(adt_def.did()))) } else { None @@ -1088,8 +1088,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( Cow::Borrowed(f.name.as_str()) }; let field_layout = struct_type_and_layout.field(cx, i); - let def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo - { + let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(f.did) } else { None @@ -1221,7 +1220,7 @@ fn build_closure_env_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, def_id); let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(def_id))) } else { None @@ -1258,7 +1257,7 @@ fn build_union_type_di_node<'ll, 'tcx>( let containing_scope = get_namespace_for_item(cx, union_def_id); let union_ty_and_layout = cx.layout_of(union_type); let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(union_def_id))) } else { None @@ -1284,8 +1283,7 @@ fn build_union_type_di_node<'ll, 'tcx>( .enumerate() .map(|(i, f)| { let field_layout = union_ty_and_layout.field(cx, i); - let def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo - { + let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(f.did) } else { None diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 83a0af851bd9..81a77ef4e988 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -192,7 +192,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))) } else { None @@ -269,7 +269,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let coroutine_type = unique_type_id.expect_ty(); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else { bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type) }; @@ -337,7 +337,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>( let tag_base_type_di_node = type_di_node(cx, tag_base_type); let tag_base_type_align = cx.align_of(tag_base_type); - let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(enum_adt_def.did()) } else { None @@ -408,7 +408,7 @@ fn build_union_fields_for_enum<'ll, 'tcx>( ) -> SmallVec<&'ll DIType> { let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout); - let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(enum_adt_def.did()) } else { None @@ -721,7 +721,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>( variant_range .clone() .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))), - if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(coroutine_def_id) } else { None @@ -818,7 +818,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( tag_base_type_di_node, tag_base_type, variant_member_info.discr, - if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { variant_member_info.source_info } else { None diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 16ae8dc37e53..1486096ddcbb 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -68,7 +68,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( enum_type_and_layout: TyAndLayout<'tcx>, ) -> DINodeCreationResult<'ll> { let containing_scope = get_namespace_for_item(cx, enum_adt_def.did()); - let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(enum_adt_def.did()) } else { None @@ -122,12 +122,12 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( }) .collect(); - let (file_metadata, line_number) = - if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { - file_metadata_from_def_id(cx, def_id) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; + let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers + { + file_metadata_from_def_id(cx, def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( @@ -207,7 +207,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( ) -> &'ll DIType { assert_eq!(variant_layout.ty, enum_type_and_layout.ty); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(variant_def.def_id))) } else { None diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 326aba7d2f3b..3b4c6ea0893c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -56,7 +56,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did()))) } else { None @@ -92,8 +92,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( enum_type_and_layout.for_variant(cx, variant_index), visibility_flags, ), - source_info: if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo - { + source_info: if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id( cx, Some(enum_adt_def.variant(variant_index).def_id), @@ -104,8 +103,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>( }) .collect(); - let enum_adt_def_id = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo - { + let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(enum_adt_def.did()) } else { None @@ -157,7 +155,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false); - let def_location = if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { Some(file_metadata_from_def_id(cx, Some(coroutine_def_id))) } else { None @@ -227,12 +225,11 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>( }) .collect(); - let generator_def_id = - if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { - Some(generator_def_id) - } else { - None - }; + let coroutine_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + Some(coroutine_def_id) + } else { + None + }; smallvec![build_enum_variant_part_di_node( cx, coroutine_type_and_layout, @@ -274,12 +271,12 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( let variant_part_unique_type_id = UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty); - let (file_metadata, line_number) = - if cx.sess().opts.unstable_opts.more_source_locations_in_debuginfo { - file_metadata_from_def_id(cx, enum_type_def_id) - } else { - (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) - }; + let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers + { + file_metadata_from_def_id(cx, enum_type_def_id) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; let stub = StubInfo::new( cx, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 732c2e3aa148..2b710c45bf49 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -709,7 +709,6 @@ fn test_unstable_options_tracking_hash() { untracked!(macro_backtrace, true); untracked!(meta_stats, true); untracked!(mir_include_spans, MirIncludeSpans::On); - untracked!(more_source_locations_in_debuginfo, true); untracked!(nll_facts, true); untracked!(no_analysis, true); untracked!(no_leak_check, true); @@ -773,6 +772,7 @@ fn test_unstable_options_tracking_hash() { tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); + tracked!(debug_info_type_line_numbers, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); tracked!(dep_info_omit_d_target, true); tracked!(direct_access_external_data, Some(true)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 883894f473c2..ef83f40e250d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1714,6 +1714,8 @@ options! { "threshold to allow cross crate inlining of functions"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), + debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED], + "emit type and line information for additional data types (default: no)"), debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], "compress debug info sections (none, zlib, zstd, default: none)"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], @@ -1907,8 +1909,6 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")] mir_opt_level: Option = (None, parse_opt_number, [TRACKED], "MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"), - more_source_locations_in_debuginfo: bool = (false, parse_bool, [UNTRACKED], - "include additional source file and line number information in debuginfo (default: no)"), move_size_limit: Option = (None, parse_opt_number, [TRACKED], "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md new file mode 100644 index 000000000000..bea667dcf44d --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/debug_info_type_line_numbers.md @@ -0,0 +1,7 @@ +# `debug-info-type-line-numbers` + +--- + +This option causes additional type and line information to be emitted in debug +info to provide richer information to debuggers. This is currently off by +default as it causes some compilation scenarios to be noticeably slower. diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs index 92e11d055694..5872d9b054ce 100644 --- a/tests/codegen/issues/issue-98678-async.rs +++ b/tests/codegen/issues/issue-98678-async.rs @@ -2,7 +2,7 @@ // async functions. // // edition: 2021 -// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo=true +// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] // ignore-tidy-linelength diff --git a/tests/codegen/issues/issue-98678-closure-generator.rs b/tests/codegen/issues/issue-98678-closure-generator.rs index a12efd495f9b..3c63cce99b69 100644 --- a/tests/codegen/issues/issue-98678-closure-generator.rs +++ b/tests/codegen/issues/issue-98678-closure-generator.rs @@ -1,7 +1,7 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for closures and // generators. // -// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo +// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] #![feature(generators, stmt_expr_attributes)] diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs index 8005c6c24eee..eaa1a7a070b2 100644 --- a/tests/codegen/issues/issue-98678-enum.rs +++ b/tests/codegen/issues/issue-98678-enum.rs @@ -1,6 +1,6 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata enums. // -// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo +// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] // ignore-tidy-linelength diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs index 3876ae46186e..7c56209e7f06 100644 --- a/tests/codegen/issues/issue-98678-struct-union.rs +++ b/tests/codegen/issues/issue-98678-struct-union.rs @@ -1,7 +1,7 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for structs and // unions. // -// compile-flags: -C debuginfo=2 -Z more-source-locations-in-debuginfo +// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] // ignore-tidy-linelength From 8200068a1d2f8e3edb9c71508761d39a8e13edee Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Fri, 1 Mar 2024 23:56:03 -0500 Subject: [PATCH 025/330] Rename generator test file --- ...nerator.rs => issue-98678-closure-coroutine.rs} | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename tests/codegen/issues/{issue-98678-closure-generator.rs => issue-98678-closure-coroutine.rs} (72%) diff --git a/tests/codegen/issues/issue-98678-closure-generator.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs similarity index 72% rename from tests/codegen/issues/issue-98678-closure-generator.rs rename to tests/codegen/issues/issue-98678-closure-coroutine.rs index 3c63cce99b69..2c95974d71f0 100644 --- a/tests/codegen/issues/issue-98678-closure-generator.rs +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -1,14 +1,14 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for closures and -// generators. +// coroutines. // // compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] -#![feature(generators, stmt_expr_attributes)] +#![feature(coroutines, stmt_expr_attributes)] // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-closure-generator.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-generator.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-closure-coroutine.rs{{".*}}) +// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}}) pub fn foo() { // NONMSVC: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], @@ -16,8 +16,8 @@ pub fn foo() { let closure = |x| x; closure(0); - // NONMSVC: !DICompositeType({{.*"[{]}}generator_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], - // MSVC-DAG: !DICompositeType({{.*".*foo::}}generator_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - let generator = #[coroutine] + // NONMSVC: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let coroutine = #[coroutine] || yield 1; } From 73291114665aafbc5ddffeb209137567a58eac49 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 2 Mar 2024 00:36:35 -0500 Subject: [PATCH 026/330] Update compile flags formatting --- tests/codegen/issues/issue-98678-async.rs | 4 ++-- tests/codegen/issues/issue-98678-closure-coroutine.rs | 2 +- tests/codegen/issues/issue-98678-enum.rs | 2 +- tests/codegen/issues/issue-98678-struct-union.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs index 5872d9b054ce..e5cc39861d5a 100644 --- a/tests/codegen/issues/issue-98678-async.rs +++ b/tests/codegen/issues/issue-98678-async.rs @@ -1,8 +1,8 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for async blocks and // async functions. // -// edition: 2021 -// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true +//@ edition:2021 +//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] // ignore-tidy-linelength diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs index 2c95974d71f0..0d26c1d0b2ed 100644 --- a/tests/codegen/issues/issue-98678-closure-coroutine.rs +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -1,7 +1,7 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for closures and // coroutines. // -// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true +//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] #![feature(coroutines, stmt_expr_attributes)] diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs index eaa1a7a070b2..fd89d27d2e86 100644 --- a/tests/codegen/issues/issue-98678-enum.rs +++ b/tests/codegen/issues/issue-98678-enum.rs @@ -1,6 +1,6 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata enums. // -// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true +//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] // ignore-tidy-linelength diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs index 7c56209e7f06..9f7c0c6c9a6b 100644 --- a/tests/codegen/issues/issue-98678-struct-union.rs +++ b/tests/codegen/issues/issue-98678-struct-union.rs @@ -1,7 +1,7 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for structs and // unions. // -// compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true +//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true #![crate_type = "lib"] // ignore-tidy-linelength From 613ddc199d2472348604e7da097c7875735c3c35 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Sat, 2 Mar 2024 02:05:29 -0500 Subject: [PATCH 027/330] Restructure `compile-flags` for tests Optimization needs to be explicitly disabled now. --- tests/codegen/issues/issue-98678-async.rs | 3 +-- tests/codegen/issues/issue-98678-closure-coroutine.rs | 11 +++++------ tests/codegen/issues/issue-98678-enum.rs | 3 +-- tests/codegen/issues/issue-98678-struct-union.rs | 3 +-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs index e5cc39861d5a..df413537f015 100644 --- a/tests/codegen/issues/issue-98678-async.rs +++ b/tests/codegen/issues/issue-98678-async.rs @@ -2,8 +2,7 @@ // async functions. // //@ edition:2021 -//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true -#![crate_type = "lib"] +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true // ignore-tidy-linelength diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs index 0d26c1d0b2ed..15e4fbb7773c 100644 --- a/tests/codegen/issues/issue-98678-closure-coroutine.rs +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -1,8 +1,7 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for closures and // coroutines. // -//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true -#![crate_type = "lib"] +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true #![feature(coroutines, stmt_expr_attributes)] // ignore-tidy-linelength @@ -11,13 +10,13 @@ // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}}) pub fn foo() { - // NONMSVC: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // NONMSVC-DAG: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], // MSVC-DAG: !DICompositeType({{.*"}}closure_env$0{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], let closure = |x| x; closure(0); - // NONMSVC: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], - // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], - let coroutine = #[coroutine] + // NONMSVC-DAG: !DISubprogram({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DISubprogram({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + let _coroutine = #[coroutine] || yield 1; } diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs index fd89d27d2e86..aec18c2132ca 100644 --- a/tests/codegen/issues/issue-98678-enum.rs +++ b/tests/codegen/issues/issue-98678-enum.rs @@ -1,7 +1,6 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata enums. // -//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true -#![crate_type = "lib"] +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true // ignore-tidy-linelength diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs index 9f7c0c6c9a6b..4c0189dd0464 100644 --- a/tests/codegen/issues/issue-98678-struct-union.rs +++ b/tests/codegen/issues/issue-98678-struct-union.rs @@ -1,8 +1,7 @@ // This test verifies the accuracy of emitted file and line debuginfo metadata for structs and // unions. // -//@ compile-flags: -C debuginfo=2 -Z debug-info-type-line-numbers=true -#![crate_type = "lib"] +//@ compile-flags: --crate-type=lib -Copt-level=0 -Cdebuginfo=2 -Zdebug-info-type-line-numbers=true // ignore-tidy-linelength From 64dd58216682257043552673c32eced30c8ce4d9 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 14 Mar 2024 13:43:25 -0500 Subject: [PATCH 028/330] Use -DAG to handle use of file before definition Also fixup the test assertion for msvc and unix --- tests/codegen/issues/issue-98678-closure-coroutine.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs index 15e4fbb7773c..e628f04409b3 100644 --- a/tests/codegen/issues/issue-98678-closure-coroutine.rs +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -6,8 +6,8 @@ // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-closure-coroutine.rs{{".*}}) -// MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}}) +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-closure-coroutine.rs{{".*}}) +// MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}}) pub fn foo() { // NONMSVC-DAG: !DICompositeType({{.*"}}{closure_env#0}{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], @@ -15,8 +15,8 @@ pub fn foo() { let closure = |x| x; closure(0); - // NONMSVC-DAG: !DISubprogram({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], - // MSVC-DAG: !DISubprogram({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + // NONMSVC-DAG: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], + // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], let _coroutine = #[coroutine] || yield 1; } From f9ac7aca5d233c2ada84685aaea8c98471867a10 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:38:51 -0500 Subject: [PATCH 029/330] Add location info for f16 --- .../src/debuginfo/metadata.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index d68da52be11e..668ec59065d9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -728,6 +728,14 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation // `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`. let float_ty = cx.tcx.types.f16; let bits_ty = cx.tcx.types.u16; + let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + match float_ty.kind() { + ty::Adt(def, _) => Some(file_metadata_from_def_id(cx, Some(def.did()))), + _ => None, + } + } else { + None + }; type_map::build_type_with_children( cx, type_map::stub( @@ -735,12 +743,21 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation Stub::Struct, UniqueTypeId::for_ty(cx.tcx, float_ty), "f16", + def_location, cx.size_and_align_of(float_ty), NO_SCOPE_METADATA, DIFlags::FlagZero, ), // Fields: |cx, float_di_node| { + let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { + match bits_ty.kind() { + ty::Adt(def, _) => Some(def.did()), + _ => None, + } + } else { + None + }; smallvec![build_field_di_node( cx, float_di_node, @@ -749,6 +766,7 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation Size::ZERO, DIFlags::FlagZero, type_di_node(cx, bits_ty), + def_id, )] }, NO_GENERICS, From 8286299742e16b20ef7c6fbd65921cb19b79038a Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:46:42 -0500 Subject: [PATCH 030/330] Clean up use requirements after rebasing --- .../src/debuginfo/metadata/enums/cpp_like.rs | 2 +- .../rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs | 1 + .../rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs | 2 +- .../rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs | 4 +--- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 81a77ef4e988..d374767f187d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -4,7 +4,7 @@ use libc::c_uint; use rustc_abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; -use rustc_codegen_ssa::traits::ConstCodegenMethods; +use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods}; use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 1486096ddcbb..65ab22ad89e8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc_abi::{FieldIdx, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_like_debuginfo}; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; +use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_hir::def::CtorKind; use rustc_index::IndexSlice; use rustc_middle::bug; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 3b4c6ea0893c..241bf167a81a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -4,7 +4,7 @@ use libc::c_uint; use rustc_abi::{Size, TagEncoding, VariantIdx, Variants}; use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name; use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo}; -use rustc_codegen_ssa::traits::ConstCodegenMethods; +use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index a6b399d76696..2a3d50a8bff9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -8,9 +8,7 @@ use rustc_macros::HashStable; use rustc_middle::bug; use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt}; -use super::{ - DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, unknown_file_metadata, -}; +use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::utils::{DIB, create_DIArray, debug_context}; use crate::llvm::debuginfo::{DIFlags, DIScope, DIType}; From d1515937818b98c944ff85efd0f30dba8503102e Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:20:10 -0500 Subject: [PATCH 031/330] Fix relative lines in coroutine test --- tests/codegen/issues/issue-98678-closure-coroutine.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs index e628f04409b3..0ae94700c5d5 100644 --- a/tests/codegen/issues/issue-98678-closure-coroutine.rs +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -15,8 +15,8 @@ pub fn foo() { let closure = |x| x; closure(0); - // NONMSVC-DAG: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], - // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], + // NONMSVC-DAG: !DICompositeType({{.*"[{]}}coroutine_env#1{{[}]".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 3]], + // MSVC-DAG: !DICompositeType({{.*".*foo::}}coroutine_env$1>{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], let _coroutine = #[coroutine] || yield 1; } From 2ade671b4fed8100c732a3ab947787dbba60e6ed Mon Sep 17 00:00:00 2001 From: David Tenty Date: Thu, 7 Nov 2024 16:52:55 -0500 Subject: [PATCH 032/330] [AIX] handle libunwind native_libs AIX should follow a similar path here to other libunwind platforms, with regards to system vs in-tree libunwind and the native lib search directories --- compiler/rustc_metadata/src/native_libs.rs | 1 + src/bootstrap/src/core/build_steps/compile.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index b7695216f3ce..fa1e274fda9e 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -57,6 +57,7 @@ pub fn walk_native_lib_search_dirs( if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" + || sess.target.is_like_aix || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() { f(&sess.target_tlib_path.dir, false)?; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 3394f2a84a04..de714469abcc 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -330,7 +330,7 @@ fn copy_third_party_objects( if target == "x86_64-fortanix-unknown-sgx" || builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree - && (target.contains("linux") || target.contains("fuchsia")) + && (target.contains("linux") || target.contains("fuchsia") || target.contains("aix")) { let libunwind_path = copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target)); From 52c5d309da4f93bbe6188d0d747d1c0a5519a224 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 21:04:24 +0300 Subject: [PATCH 033/330] refactor initial-sysroot handling Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/config/config.rs | 14 ++++++-------- src/bootstrap/src/core/download.rs | 5 ++--- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index bcce2748c2ee..502a41028f03 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1062,7 +1062,7 @@ impl Step for Tidy { if builder.config.channel == "dev" || builder.config.channel == "nightly" { builder.info("fmt check"); if builder.initial_rustfmt().is_none() { - let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap(); + let inferred_rustfmt_dir = builder.initial_sysroot.join("bin"); eprintln!( "\ ERROR: no `rustfmt` binary found in {PATH} diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 8115aea033d9..cf8234dc599e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -360,6 +360,7 @@ pub struct Config { pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, pub initial_cargo_clippy: Option, + pub initial_sysroot: PathBuf, #[cfg(not(test))] initial_rustfmt: RefCell, @@ -1541,8 +1542,6 @@ impl Config { ); } - config.initial_cargo_clippy = cargo_clippy; - config.initial_rustc = if let Some(rustc) = rustc { if !flags.skip_stage0_validation { config.check_stage0_version(&rustc, "rustc"); @@ -1558,6 +1557,10 @@ impl Config { .join(exe("rustc", config.build)) }; + config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into(); + + config.initial_cargo_clippy = cargo_clippy; + config.initial_cargo = if let Some(cargo) = cargo { if !flags.skip_stage0_validation { config.check_stage0_version(&cargo, "cargo"); @@ -1565,12 +1568,7 @@ impl Config { cargo } else { config.download_beta_toolchain(); - config - .out - .join(config.build) - .join("stage0") - .join("bin") - .join(exe("cargo", config.build)) + config.initial_sysroot.join("bin").join(exe("cargo", config.build)) }; // NOTE: it's important this comes *after* we set `initial_rustc` just above. diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index db1f5b083382..22a2b8066037 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -427,9 +427,8 @@ impl Config { let version = &self.stage0_metadata.compiler.version; let host = self.build; - let bin_root = self.out.join(host).join("stage0"); - let clippy_stamp = bin_root.join(".clippy-stamp"); - let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host)); + let clippy_stamp = self.initial_sysroot.join(".clippy-stamp"); + let cargo_clippy = self.initial_sysroot.join("bin").join(exe("cargo-clippy", host)); if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) { return cargo_clippy; } From 27323aac9fdb905e0665fc9c43147a895ef51da6 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 21:04:41 +0300 Subject: [PATCH 034/330] improve initial target libdir finding logic Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/mod.rs | 2 +- src/bootstrap/src/lib.rs | 55 +++++++-------------------- 2 files changed, 15 insertions(+), 42 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index f1b3cf6da13e..ff9d19ec3ba9 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1260,7 +1260,7 @@ impl<'a> Builder<'a> { pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path { match self.config.libdir_relative() { Some(relative_libdir) if compiler.stage >= 1 => relative_libdir, - _ if compiler.stage == 0 => &self.build.initial_libdir, + _ if compiler.stage == 0 => &self.build.initial_relative_libdir, _ => Path::new("lib"), } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index ba74cabcd306..5d0198cecc00 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -161,7 +161,7 @@ pub struct Build { initial_rustc: PathBuf, initial_cargo: PathBuf, initial_lld: PathBuf, - initial_libdir: PathBuf, + initial_relative_libdir: PathBuf, initial_sysroot: PathBuf, // Runtime state filled in later on @@ -315,46 +315,19 @@ impl Build { let in_tree_llvm_info = config.in_tree_llvm_info.clone(); let in_tree_gcc_info = config.in_tree_gcc_info.clone(); - let initial_target_libdir_str = if config.dry_run() { - "/dummy/lib/path/to/lib/".to_string() - } else { - output( - Command::new(&config.initial_rustc) - .arg("--target") - .arg(config.build.rustc_target_arg()) - .arg("--print") - .arg("target-libdir"), - ) - }; + let initial_target_libdir_str = + config.initial_sysroot.join("lib/rustlib").join(config.build).join("lib"); + let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap(); let initial_lld = initial_target_dir.join("bin").join("rust-lld"); - let initial_sysroot = if config.dry_run() { - "/dummy".to_string() - } else { - output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot")) - } - .trim() - .to_string(); - - // FIXME(Zalathar): Determining this path occasionally fails locally for - // unknown reasons, so we print some extra context to help track down why. - let find_initial_libdir = || { - let initial_libdir = - initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?; - Some(initial_libdir.to_path_buf()) - }; - let Some(initial_libdir) = find_initial_libdir() else { - panic!( - "couldn't determine `initial_libdir`: -- config.initial_rustc: {rustc:?} -- initial_target_libdir_str: {initial_target_libdir_str:?} -- initial_target_dir: {initial_target_dir:?} -- initial_sysroot: {initial_sysroot:?} -", - rustc = config.initial_rustc, - ); - }; + let initial_relative_libdir = initial_target_dir + .ancestors() + .nth(2) + .unwrap() + .strip_prefix(&config.initial_sysroot) + .expect("Couldn’t determine initial relative libdir.") + .to_path_buf(); let version = std::fs::read_to_string(src.join("src").join("version")) .expect("failed to read src/version"); @@ -383,11 +356,11 @@ impl Build { } let mut build = Build { + initial_lld, + initial_relative_libdir, initial_rustc: config.initial_rustc.clone(), initial_cargo: config.initial_cargo.clone(), - initial_lld, - initial_libdir, - initial_sysroot: initial_sysroot.into(), + initial_sysroot: config.initial_sysroot.clone(), local_rebuild: config.local_rebuild, fail_fast: config.cmd.fail_fast(), doc_tests: config.cmd.doc_tests(), From 1309e8f3f37c90153c84334e586785f276b65b34 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:52:56 +0200 Subject: [PATCH 035/330] allow conditional `Send` futures in `future_not_send` --- clippy_lints/src/future_not_send.rs | 67 ++++++++++++++++++++++++----- tests/ui/crashes/ice-10645.rs | 7 --- tests/ui/crashes/ice-10645.stderr | 17 -------- tests/ui/future_not_send.rs | 18 +++++++- tests/ui/future_not_send.stderr | 51 +++++++++++----------- 5 files changed, 101 insertions(+), 59 deletions(-) delete mode 100644 tests/ui/crashes/ice-10645.rs delete mode 100644 tests/ui/crashes/ice-10645.stderr diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index cf08c16458bd..bb2dc9995df7 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::return_ty; use rustc_hir::intravisit::FnKind; @@ -5,7 +7,9 @@ use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::print::PrintTraitRefExt; -use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind}; +use rustc_middle::ty::{ + self, AliasTy, Binder, ClauseKind, PredicateKind, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor, +}; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; @@ -15,9 +19,16 @@ use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt}; declare_clippy_lint! { /// ### What it does /// This lint requires Future implementations returned from - /// functions and methods to implement the `Send` marker trait. It is mostly - /// used by library authors (public and internal) that target an audience where - /// multithreaded executors are likely to be used for running these Futures. + /// functions and methods to implement the `Send` marker trait, + /// ignoring type parameters. + /// + /// If a function is generic and its Future conditionally implements `Send` + /// based on a generic parameter then it is considered `Send` and no warning is emitted. + /// + /// This can be used by library authors (public and internal) to ensure + /// their functions are compatible with both multi-threaded runtimes that require `Send` futures, + /// as well as single-threaded runtimes where callers may choose `!Send` types + /// for generic parameters. /// /// ### Why is this bad? /// A Future implementation captures some state that it @@ -64,22 +75,46 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { return; } let ret_ty = return_ty(cx, cx.tcx.local_def_id_to_hir_id(fn_def_id).expect_owner()); - if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() { + if let ty::Alias(ty::Opaque, AliasTy { def_id, args, .. }) = *ret_ty.kind() + && let Some(future_trait) = cx.tcx.lang_items().future_trait() + && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send) + { let preds = cx.tcx.explicit_item_super_predicates(def_id); let is_future = preds.iter_instantiated_copied(cx.tcx, args).any(|(p, _)| { - p.as_trait_clause().is_some_and(|trait_pred| { - Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() - }) + p.as_trait_clause() + .is_some_and(|trait_pred| trait_pred.skip_binder().trait_ref.def_id == future_trait) }); if is_future { - let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let span = decl.output.span(); let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let cause = traits::ObligationCause::misc(span, fn_def_id); ocx.register_bound(cause, cx.param_env, ret_ty, send_trait); let send_errors = ocx.select_all_or_error(); - if !send_errors.is_empty() { + + // Allow errors that try to prove `Send` for types that "mention" a generic parameter at the "top + // level". + // For example, allow errors that `T: Send` can't be proven, but reject `Rc: Send` errors, + // which is always unconditionally `!Send` for any possible type `T`. + // + // We also allow associated type projections if the self type is either itself a projection or a + // type parameter. + // This is to prevent emitting warnings for e.g. holding a `::Output` across await + // points, where `Fut` is a type parameter. + + let is_send = send_errors.iter().all(|err| { + err.obligation + .predicate + .as_trait_clause() + .map(Binder::skip_binder) + .is_some_and(|pred| { + pred.def_id() == send_trait + && pred.self_ty().has_param() + && TyParamAtTopLevelVisitor.visit_ty(pred.self_ty()) == ControlFlow::Break(true) + }) + }); + + if !is_send { span_lint_and_then( cx, FUTURE_NOT_SEND, @@ -107,3 +142,15 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } } } + +struct TyParamAtTopLevelVisitor; +impl<'tcx> TypeVisitor> for TyParamAtTopLevelVisitor { + type Result = ControlFlow; + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { + match ty.kind() { + ty::Param(_) => ControlFlow::Break(true), + ty::Alias(ty::AliasTyKind::Projection, ty) => ty.visit_with(self), + _ => ControlFlow::Break(false), + } + } +} diff --git a/tests/ui/crashes/ice-10645.rs b/tests/ui/crashes/ice-10645.rs deleted file mode 100644 index 6e126aff7512..000000000000 --- a/tests/ui/crashes/ice-10645.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@compile-flags: --cap-lints=warn -// https://github.com/rust-lang/rust-clippy/issues/10645 - -#![warn(clippy::future_not_send)] -pub async fn bar<'a, T: 'a>(_: T) {} - -fn main() {} diff --git a/tests/ui/crashes/ice-10645.stderr b/tests/ui/crashes/ice-10645.stderr deleted file mode 100644 index 0269072b88bc..000000000000 --- a/tests/ui/crashes/ice-10645.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: future cannot be sent between threads safely - --> tests/ui/crashes/ice-10645.rs:5:1 - | -LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `bar` is not `Send` - | -note: captured value is not `Send` - --> tests/ui/crashes/ice-10645.rs:5:29 - | -LL | pub async fn bar<'a, T: 'a>(_: T) {} - | ^ has type `T` which is not `Send` - = note: `T` doesn't implement `std::marker::Send` - = note: `-D clippy::future-not-send` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]` - -warning: 1 warning emitted - diff --git a/tests/ui/future_not_send.rs b/tests/ui/future_not_send.rs index 9274340b5caa..626ee6de9e4f 100644 --- a/tests/ui/future_not_send.rs +++ b/tests/ui/future_not_send.rs @@ -1,6 +1,7 @@ #![warn(clippy::future_not_send)] use std::cell::Cell; +use std::future::Future; use std::rc::Rc; use std::sync::Arc; @@ -63,6 +64,22 @@ where t } +async fn maybe_send_generic_future(t: T) -> T { + async { true }.await; + t +} + +async fn maybe_send_generic_future2 Fut, Fut: Future>(f: F) { + async { true }.await; + let res = f(); + async { true }.await; +} + +async fn generic_future_always_unsend(_: Rc) { + //~^ ERROR: future cannot be sent between threads safely + async { true }.await; +} + async fn generic_future_send(t: T) where T: Send, @@ -71,7 +88,6 @@ where } async fn unclear_future(t: T) {} -//~^ ERROR: future cannot be sent between threads safely fn main() { let rc = Rc::new([1, 2, 3]); diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index 67677d6367aa..3807c7470136 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -1,11 +1,11 @@ error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:7:1 + --> tests/ui/future_not_send.rs:8:1 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:9:20 + --> tests/ui/future_not_send.rs:10:20 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | -- has type `std::rc::Rc<[u8]>` which is not `Send` @@ -14,7 +14,7 @@ LL | async { true }.await | ^^^^^ await occurs here, with `rc` maybe used later = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:7:39 + --> tests/ui/future_not_send.rs:8:39 | LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^ has type `&std::cell::Cell` which is not `Send`, because `std::cell::Cell` is not `Sync` @@ -23,13 +23,13 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell) -> bool { = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:12:1 + --> tests/ui/future_not_send.rs:13:1 | LL | pub async fn public_future(rc: Rc<[u8]>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:14:20 + --> tests/ui/future_not_send.rs:15:20 | LL | pub async fn public_future(rc: Rc<[u8]>) { | -- has type `std::rc::Rc<[u8]>` which is not `Send` @@ -39,45 +39,45 @@ LL | async { true }.await; = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:21:1 + --> tests/ui/future_not_send.rs:22:1 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send` | note: captured value is not `Send` - --> tests/ui/future_not_send.rs:21:26 + --> tests/ui/future_not_send.rs:22:26 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:21:40 + --> tests/ui/future_not_send.rs:22:40 | LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell) -> bool { | ^^^^ has type `&std::cell::Cell` which is not `Send`, because `std::cell::Cell` is not `Sync` = note: `std::cell::Cell` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:26:1 + --> tests/ui/future_not_send.rs:27:1 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send` | note: captured value is not `Send` - --> tests/ui/future_not_send.rs:26:29 + --> tests/ui/future_not_send.rs:27:29 | LL | pub async fn public_future2(rc: Rc<[u8]>) {} | ^^ has type `std::rc::Rc<[u8]>` which is not `Send` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:38:5 + --> tests/ui/future_not_send.rs:39:5 | LL | async fn private_future(&self) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:40:24 + --> tests/ui/future_not_send.rs:41:24 | LL | async fn private_future(&self) -> usize { | ----- has type `&Dummy` which is not `Send` @@ -87,20 +87,20 @@ LL | async { true }.await; = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:44:5 + --> tests/ui/future_not_send.rs:45:5 | LL | pub async fn public_future(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send` | note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` - --> tests/ui/future_not_send.rs:44:32 + --> tests/ui/future_not_send.rs:45:32 | LL | pub async fn public_future(&self) { | ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync` = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:55:1 + --> tests/ui/future_not_send.rs:56:1 | LL | / async fn generic_future(t: T) -> T LL | | @@ -109,7 +109,7 @@ LL | | T: Send, | |____________^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> tests/ui/future_not_send.rs:61:20 + --> tests/ui/future_not_send.rs:62:20 | LL | let rt = &t; | -- has type `&T` which is not `Send` @@ -118,17 +118,20 @@ LL | async { true }.await; = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> tests/ui/future_not_send.rs:73:1 + --> tests/ui/future_not_send.rs:78:1 | -LL | async fn unclear_future(t: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `unclear_future` is not `Send` +LL | async fn generic_future_always_unsend(_: Rc) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `generic_future_always_unsend` is not `Send` | -note: captured value is not `Send` - --> tests/ui/future_not_send.rs:73:28 +note: future is not `Send` as this value is used across an await + --> tests/ui/future_not_send.rs:80:20 | -LL | async fn unclear_future(t: T) {} - | ^ has type `T` which is not `Send` - = note: `T` doesn't implement `std::marker::Send` +LL | async fn generic_future_always_unsend(_: Rc) { + | - has type `std::rc::Rc` which is not `Send` +LL | +LL | async { true }.await; + | ^^^^^ await occurs here, with `_` maybe used later + = note: `std::rc::Rc` doesn't implement `std::marker::Send` error: aborting due to 8 previous errors From 95177699866a6101228ce0cc755b6c4eb162fa47 Mon Sep 17 00:00:00 2001 From: xmh0511 <970252187@qq.com> Date: Tue, 12 Nov 2024 09:46:41 +0800 Subject: [PATCH 036/330] a release operation synchronizes with an acquire operation --- library/std/src/thread/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 227ee9d64f37..36400be61320 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1001,11 +1001,11 @@ impl Drop for PanicGuard { /// /// # Memory Ordering /// -/// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory +/// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory /// operations performed before a call to `unpark` are made visible to the thread that /// consumes the token and returns from `park`. Note that all `park` and `unpark` -/// operations for a given thread form a total order and `park` synchronizes-with -/// _all_ prior `unpark` operations. +/// operations for a given thread form a total order and _all_ prior `unpark` operations +/// synchronize-with `park`. /// /// In atomic ordering terms, `unpark` performs a `Release` operation and `park` /// performs the corresponding `Acquire` operation. Calls to `unpark` for the same From 8fb6c08f498df771a56c52d62b6480c1792bc014 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Oct 2024 01:41:52 +0200 Subject: [PATCH 037/330] Increase impl items indent and decrease documentation indent for impl block --- src/librustdoc/html/static/css/rustdoc.css | 50 +++++++++++++++------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 66a8a1989288..ed0c347879b4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -36,6 +36,8 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ --button-border-radius: 2px; --toolbar-button-border-radius: 6px; --code-block-border-radius: 6px; + --impl-items-indent: 0.5em; + --docblock-indent: 24px; } /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @@ -909,7 +911,7 @@ both the code example and the line numbers, so we need to remove the radius in t .docblock h6 { font-size: 0.875rem; } .docblock { - margin-left: 24px; + margin-left: var(--docblock-indent); position: relative; } @@ -982,7 +984,11 @@ div.where { .item-info { display: block; - margin-left: 24px; + margin-left: var(--docblock-indent); +} +.impl-items > .item-info { + /* Margin of docblocks + margin of impl block items. */ + margin-left: calc(var(--docblock-indent) + var(--impl-items-indent)); } .item-info code { @@ -2166,6 +2172,15 @@ details.toggle > summary:not(.hideme)::before { left: -24px; } +/* We indent items of an impl block to have a visual marker that these items are part + of this impl block. */ +.impl-items > *:not(.item-info), +/* We also indent the first top doc comment the same to still keep an indent on the + doc block while aligning it with the impl block items. */ +.implementors-toggle > .docblock { + margin-left: var(--impl-items-indent); +} + details.big-toggle > summary:not(.hideme)::before { left: -34px; top: 9px; @@ -2255,6 +2270,10 @@ If you update this line, then you also need to update the line with the same war in src-script.js and main.js */ @media (max-width: 700px) { + :root { + --impl-items-indent: 0.7em; + } + /* When linking to an item with an `id` (for instance, by clicking a link in the sidebar, or visiting a URL with a fragment like `#method.new`, we don't want the item to be obscured by the topbar. Anything with an `id` gets scroll-margin-top equal to .mobile-topbar's size. @@ -2454,19 +2473,20 @@ in src-script.js and main.js padding-top: 0; } - /* Position of the "[-]" element. */ - details.toggle:not(.top-doc) > summary, .impl-items > section { + details.implementors-toggle:not(.top-doc) > summary { margin-left: 10px; } - .impl-items > details.toggle > summary:not(.hideme)::before, - #main-content > details.toggle:not(.top-doc) > summary::before, - #main-content > div > details.toggle > summary::before { - left: -11px; + + .impl-items > details.toggle > summary:not(.hideme)::before { + left: -20px; } /* Align summary-nested and unnested item-info gizmos. */ + summary > .item-info { + margin-left: 10px; + } .impl-items > .item-info { - margin-left: 34px; + margin-left: calc(var(--impl-items-indent) + 10px); } .src nav.sub { @@ -2500,24 +2520,24 @@ in src-script.js and main.js } @media print { + :root { + --docblock-indent: 0; + } + nav.sidebar, nav.sub, .out-of-band, a.src, #copy-path, details.toggle[open] > summary::before, details.toggle > summary::before, details.toggle.top-doc > summary { display: none; } - .docblock { - margin-left: 0; - } - main { padding: 10px; } } @media (max-width: 464px) { - .docblock { - margin-left: 12px; + :root { + --docblock-indent: 12px; } .docblock code { From 4f20626cefab445aa3f8e560f11cd7d14f4665ba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Oct 2024 01:42:07 +0200 Subject: [PATCH 038/330] Update GUI tests for documentation indent changes --- tests/rustdoc-gui/deref-block.goml | 8 ++++++-- tests/rustdoc-gui/docblock-table-overflow.goml | 2 +- tests/rustdoc-gui/item-info-alignment.goml | 2 ++ tests/rustdoc-gui/item-info.goml | 2 +- tests/rustdoc-gui/methods-left-margin.goml | 1 - tests/rustdoc-gui/notable-trait.goml | 14 +++++++------- tests/rustdoc-gui/toggle-docs-mobile.goml | 2 +- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/tests/rustdoc-gui/deref-block.goml b/tests/rustdoc-gui/deref-block.goml index 24f612f8a6fd..97930b61ef4a 100644 --- a/tests/rustdoc-gui/deref-block.goml +++ b/tests/rustdoc-gui/deref-block.goml @@ -20,8 +20,12 @@ assert-css: (".big-toggle summary::before", { "left": "-11px", "top": "9px", }) -// It should have the same X position as the other toggles. -compare-elements-position: (".big-toggle summary::before", ".method-toggle summary::before", ["x"]) +// It should have a slightly different X position as the other toggles. +store-position: (".big-toggle summary::before", {"x": big_toggle}) +store-position: (".method-toggle summary::before", {"x": small_toggle}) +assert: |big_toggle| < |small_toggle| +// Margin is 0.5em so around 8 px. +assert: |small_toggle| - |big_toggle| < 10 // But still shouldn't have the same Y position. compare-elements-position-false: ( ".big-toggle summary::before", diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml index 1ca919d1eabc..60fbd69fe3f7 100644 --- a/tests/rustdoc-gui/docblock-table-overflow.goml +++ b/tests/rustdoc-gui/docblock-table-overflow.goml @@ -16,6 +16,6 @@ compare-elements-property: ( "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "816"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "832"}) // However, since there is overflow in the , its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/tests/rustdoc-gui/item-info-alignment.goml b/tests/rustdoc-gui/item-info-alignment.goml index cd0624056b9a..075722bb539c 100644 --- a/tests/rustdoc-gui/item-info-alignment.goml +++ b/tests/rustdoc-gui/item-info-alignment.goml @@ -4,7 +4,9 @@ go-to: "file://" + |DOC_PATH| + "/lib2/struct.ItemInfoAlignmentTest.html" // First, we try it in "desktop" mode. set-window-size: (1200, 870) +wait-for-size: ("body", {"width": 1200}) compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ["x"]) // Next, we try it in "mobile" mode (max-width: 700px). set-window-size: (650, 650) +wait-for-size: ("body", {"width": 650}) compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ["x"]) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index 1636e1496923..c775bf005dc7 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -19,7 +19,7 @@ store-position: ( "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']", {"x": second_line_x, "y": second_line_y}, ) -assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 +assert: |first_line_x| != |second_line_x| && |first_line_x| == 524 && |second_line_x| == 280 assert: |first_line_y| != |second_line_y| && |first_line_y| == 718 && |second_line_y| == 741 // Now we ensure that they're not rendered on the same line. diff --git a/tests/rustdoc-gui/methods-left-margin.goml b/tests/rustdoc-gui/methods-left-margin.goml index 1003cec33f95..31b53faf7560 100644 --- a/tests/rustdoc-gui/methods-left-margin.goml +++ b/tests/rustdoc-gui/methods-left-margin.goml @@ -1,7 +1,6 @@ // This test is to ensure that methods are correctly aligned on the left side. go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" - // First we ensure that we have methods with and without documentation. assert: ".impl-items > details.method-toggle > summary > section.method" assert: ".impl-items > section.method" diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index e02974e60829..e04ace8a0d44 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -62,9 +62,9 @@ define-function: ( // We start with a wide screen. set-window-size: (1100, 600) call-function: ("check-notable-tooltip-position-complete", { - "x": 677, - "i_x": 955, - "popover_x": 463, + "x": 685, + "i_x": 963, + "popover_x": 471, }) // Now only the `i` should be on the next line. @@ -78,16 +78,16 @@ compare-elements-position-false: ( // Now both the `i` and the struct name should be on the next line. set-window-size: (980, 600) call-function: ("check-notable-tooltip-position", { - "x": 245, - "i_x": 523, + "x": 253, + "i_x": 531, }) // Checking on mobile now. set-window-size: (650, 600) wait-for-size: ("body", {"width": 650}) call-function: ("check-notable-tooltip-position-complete", { - "x": 25, - "i_x": 303, + "x": 26, + "i_x": 305, "popover_x": 0, }) diff --git a/tests/rustdoc-gui/toggle-docs-mobile.goml b/tests/rustdoc-gui/toggle-docs-mobile.goml index b69aa6e30ca0..be12e4c19b3b 100644 --- a/tests/rustdoc-gui/toggle-docs-mobile.goml +++ b/tests/rustdoc-gui/toggle-docs-mobile.goml @@ -18,7 +18,7 @@ assert-position: ("#implementations-list > details > summary::before", {"x": 4}) // Assert the position of the toggle on a method. assert-position: ( "#trait-implementations-list .impl-items .method-toggle > summary::before", - {"x": 4}, + {"x": 6}, ) // Now we do the same but with a little bigger width From 421661553fa550fbdb1c011e8930443ae09e5519 Mon Sep 17 00:00:00 2001 From: David Kurilla <130074511+davidkurilla@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:43:48 +0000 Subject: [PATCH 039/330] fix: fix immutable tree error --- .../crates/ide-assists/src/handlers/add_braces.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index c96ae7a16bc1..5ffaaebc9ea2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -1,5 +1,5 @@ use syntax::{ - ast::{self, edit::AstNodeEdit, make, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxEditor, + ast::{self, edit::AstNodeEdit, edit_in_place, make, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxEditor, AstNode, }; @@ -43,10 +43,8 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let make = SyntaxFactory::new(); let mut editor = builder.make_editor(&expr.syntax()); - let block_expr = AstNodeEdit::indent( - &make.block_expr(None, Some(expr.clone())), - AstNodeEdit::indent_level(&expr), - ); + let block_expr = make.block_expr(None, Some(expr.clone())); + block_expr.indent(expr.indent_level()); editor.replace(expr.syntax(), block_expr.syntax()); From 90857446625c7c0be4f623c8617066cd5cd21258 Mon Sep 17 00:00:00 2001 From: David Kurilla <130074511+davidkurilla@users.noreply.github.com> Date: Tue, 12 Nov 2024 23:58:24 +0000 Subject: [PATCH 040/330] fix: fix indentation error --- .../rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index 5ffaaebc9ea2..9f93f16c0f67 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -1,5 +1,5 @@ use syntax::{ - ast::{self, edit::AstNodeEdit, edit_in_place, make, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxEditor, + ast::{self, edit_in_place::Indent, make, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxEditor, AstNode, }; From 5458612e0454a812381deef4059bc46260091420 Mon Sep 17 00:00:00 2001 From: David Kurilla <130074511+davidkurilla@users.noreply.github.com> Date: Wed, 13 Nov 2024 00:06:12 +0000 Subject: [PATCH 041/330] fix: remove unused imports --- .../rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index 9f93f16c0f67..dfbecc7cffcb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -1,5 +1,5 @@ use syntax::{ - ast::{self, edit_in_place::Indent, make, syntax_factory::SyntaxFactory}, syntax_editor::SyntaxEditor, + ast::{self, edit_in_place::Indent, syntax_factory::SyntaxFactory}, AstNode, }; From bf6fcc9db8260c673c4798bf9b1074ae36a73bed Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Nov 2024 15:13:31 +0100 Subject: [PATCH 042/330] Align impl doc block with `impl` keyword --- src/librustdoc/html/static/css/rustdoc.css | 2 +- tests/rustdoc-gui/docblock-table-overflow.goml | 2 +- tests/rustdoc-gui/item-info.goml | 2 +- tests/rustdoc-gui/notable-trait.goml | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index ed0c347879b4..90aa5904dafe 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -36,7 +36,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ --button-border-radius: 2px; --toolbar-button-border-radius: 6px; --code-block-border-radius: 6px; - --impl-items-indent: 0.5em; + --impl-items-indent: 0.3em; --docblock-indent: 24px; } diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml index 60fbd69fe3f7..abfa820ef270 100644 --- a/tests/rustdoc-gui/docblock-table-overflow.goml +++ b/tests/rustdoc-gui/docblock-table-overflow.goml @@ -16,6 +16,6 @@ compare-elements-property: ( "#implementations-list > details .docblock > p", ["scrollWidth"], ) -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "832"}) +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "835"}) // However, since there is overflow in the
, its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index c775bf005dc7..b5b0052fe613 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -19,7 +19,7 @@ store-position: ( "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']", {"x": second_line_x, "y": second_line_y}, ) -assert: |first_line_x| != |second_line_x| && |first_line_x| == 524 && |second_line_x| == 280 +assert: |first_line_x| != |second_line_x| && |first_line_x| == 521 && |second_line_x| == 277 assert: |first_line_y| != |second_line_y| && |first_line_y| == 718 && |second_line_y| == 741 // Now we ensure that they're not rendered on the same line. diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index e04ace8a0d44..4624fb80b377 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -62,9 +62,9 @@ define-function: ( // We start with a wide screen. set-window-size: (1100, 600) call-function: ("check-notable-tooltip-position-complete", { - "x": 685, - "i_x": 963, - "popover_x": 471, + "x": 682, + "i_x": 960, + "popover_x": 468, }) // Now only the `i` should be on the next line. @@ -78,8 +78,8 @@ compare-elements-position-false: ( // Now both the `i` and the struct name should be on the next line. set-window-size: (980, 600) call-function: ("check-notable-tooltip-position", { - "x": 253, - "i_x": 531, + "x": 250, + "i_x": 528, }) // Checking on mobile now. From 1ceaa9041331c277c143078942ba5683d888a98c Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 14 Nov 2024 19:35:26 +0100 Subject: [PATCH 043/330] Merge commit '786fbd6d683933cd0e567fdcd25d449a69b4320c' into clippy-subtree-update --- CHANGELOG.md | 1 + clippy_dev/src/setup/vscode.rs | 2 +- clippy_lints/src/attrs/useless_attribute.rs | 2 +- clippy_lints/src/attrs/utils.rs | 4 +- clippy_lints/src/bool_assert_comparison.rs | 4 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/box_default.rs | 8 +- clippy_lints/src/casts/unnecessary_cast.rs | 3 +- clippy_lints/src/comparison_chain.rs | 2 +- clippy_lints/src/copies.rs | 16 +- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/default_numeric_fallback.rs | 2 +- clippy_lints/src/derivable_impls.rs | 2 +- clippy_lints/src/derive.rs | 2 +- clippy_lints/src/doc/missing_headers.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- clippy_lints/src/infinite_iter.rs | 8 +- clippy_lints/src/item_name_repetitions.rs | 4 +- .../src/iter_not_returning_iterator.rs | 2 +- clippy_lints/src/large_const_arrays.rs | 3 +- clippy_lints/src/large_include_file.rs | 2 + clippy_lints/src/len_zero.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/loops/manual_find.rs | 2 +- clippy_lints/src/loops/manual_memcpy.rs | 2 +- clippy_lints/src/loops/mut_range_bound.rs | 2 +- clippy_lints/src/loops/same_item_push.rs | 2 +- clippy_lints/src/loops/utils.rs | 7 +- clippy_lints/src/manual_clamp.rs | 2 +- clippy_lints/src/manual_strip.rs | 4 +- .../src/matches/match_like_matches.rs | 2 +- .../src/matches/redundant_pattern_match.rs | 2 +- clippy_lints/src/matches/single_match.rs | 2 +- clippy_lints/src/matches/try_err.rs | 2 +- clippy_lints/src/methods/expect_fun_call.rs | 2 +- clippy_lints/src/methods/filter_next.rs | 7 +- clippy_lints/src/methods/manual_next_back.rs | 4 +- clippy_lints/src/methods/manual_str_repeat.rs | 4 +- clippy_lints/src/methods/map_clone.rs | 2 +- clippy_lints/src/methods/mod.rs | 32 ++- clippy_lints/src/methods/needless_collect.rs | 2 +- .../src/methods/option_as_ref_deref.rs | 2 +- clippy_lints/src/methods/or_fun_call.rs | 4 +- clippy_lints/src/methods/str_splitn.rs | 2 +- .../src/methods/unnecessary_map_or.rs | 131 ++++++++++++ .../src/methods/unnecessary_sort_by.rs | 7 +- clippy_lints/src/methods/useless_asref.rs | 2 +- clippy_lints/src/misc_early/mod.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 10 +- clippy_lints/src/needless_continue.rs | 4 +- clippy_lints/src/nonstandard_macro_braces.rs | 2 +- clippy_lints/src/only_used_in_recursion.rs | 4 +- .../src/operators/arithmetic_side_effects.rs | 2 +- clippy_lints/src/operators/cmp_owned.rs | 6 +- clippy_lints/src/operators/identity_op.rs | 190 ++++++++---------- .../src/operators/numeric_arithmetic.rs | 2 +- clippy_lints/src/pass_by_ref_or_value.rs | 2 +- clippy_lints/src/ptr.rs | 5 +- clippy_lints/src/question_mark.rs | 172 +++++++++++++++- clippy_lints/src/redundant_slicing.rs | 4 +- clippy_lints/src/swap.rs | 4 +- clippy_lints/src/types/borrowed_box.rs | 3 +- clippy_lints/src/unit_types/let_unit_value.rs | 2 +- clippy_lints/src/vec_init_then_push.rs | 2 +- clippy_lints/src/write.rs | 2 +- clippy_utils/src/check_proc_macro.rs | 6 +- clippy_utils/src/hir_utils.rs | 8 +- clippy_utils/src/lib.rs | 31 ++- clippy_utils/src/numeric_literal.rs | 2 +- clippy_utils/src/sugg.rs | 2 +- clippy_utils/src/ty.rs | 12 +- clippy_utils/src/visitors.rs | 10 +- rust-toolchain | 2 +- tests/ui-internal/unnecessary_def_path.fixed | 1 + tests/ui-internal/unnecessary_def_path.rs | 1 + tests/ui-internal/unnecessary_def_path.stderr | 30 +-- tests/ui-toml/large_include_file/empty.txt | 0 .../large_include_file/large_include_file.rs | 6 +- ...sensitive_file_extension_comparisons.fixed | 1 + ...se_sensitive_file_extension_comparisons.rs | 1 + ...ensitive_file_extension_comparisons.stderr | 12 +- tests/ui/identity_op.fixed | 46 ++++- tests/ui/identity_op.rs | 44 ++++ tests/ui/identity_op.stderr | 70 ++++++- tests/ui/question_mark.fixed | 56 ++++++ tests/ui/question_mark.rs | 71 +++++++ tests/ui/question_mark.stderr | 63 +++++- tests/ui/unnecessary_map_or.fixed | 64 ++++++ tests/ui/unnecessary_map_or.rs | 67 ++++++ tests/ui/unnecessary_map_or.stderr | 99 +++++++++ 92 files changed, 1149 insertions(+), 286 deletions(-) create mode 100644 clippy_lints/src/methods/unnecessary_map_or.rs create mode 100644 tests/ui-toml/large_include_file/empty.txt create mode 100644 tests/ui/unnecessary_map_or.fixed create mode 100644 tests/ui/unnecessary_map_or.rs create mode 100644 tests/ui/unnecessary_map_or.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 161fa630ed47..dd3124ee9a3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6071,6 +6071,7 @@ Released 2018-09-13 [`unnecessary_literal_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_bound [`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap [`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_on_constructor +[`unnecessary_map_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_or [`unnecessary_min_or_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_min_or_max [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation diff --git a/clippy_dev/src/setup/vscode.rs b/clippy_dev/src/setup/vscode.rs index 204f4af2cf1b..a37c873eed4f 100644 --- a/clippy_dev/src/setup/vscode.rs +++ b/clippy_dev/src/setup/vscode.rs @@ -84,7 +84,7 @@ fn delete_vs_task_file(path: &Path) -> bool { /// It may fail silently. fn try_delete_vs_directory_if_empty() { let path = Path::new(VSCODE_DIR); - if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) { + if path.read_dir().is_ok_and(|mut iter| iter.next().is_none()) { // The directory is empty. We just try to delete it but allow a silence // fail as an empty `.vscode` directory is still valid let _silence_result = fs::remove_dir(path); diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs index dc5a68570896..e21853598c3b 100644 --- a/clippy_lints/src/attrs/useless_attribute.rs +++ b/clippy_lints/src/attrs/useless_attribute.rs @@ -16,7 +16,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { return; } if let Some(lint_list) = &attr.meta_item_list() { - if attr.ident().map_or(false, |ident| is_lint_level(ident.name, attr.id)) { + if attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) { for lint in lint_list { match item.kind { ItemKind::Use(..) => { diff --git a/clippy_lints/src/attrs/utils.rs b/clippy_lints/src/attrs/utils.rs index 9b10ae836514..3bb02688bf22 100644 --- a/clippy_lints/src/attrs/utils.rs +++ b/clippy_lints/src/attrs/utils.rs @@ -50,7 +50,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_ block .expr .as_ref() - .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)), + .is_some_and(|e| is_relevant_expr(cx, typeck_results, e)), |stmt| match &stmt.kind { StmtKind::Let(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), @@ -60,7 +60,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_ } fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool { - if macro_backtrace(expr.span).last().map_or(false, |macro_call| { + if macro_backtrace(expr.span).last().is_some_and(|macro_call| { is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable }) { return false; diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs index db5792188dd4..7d89195eeca7 100644 --- a/clippy_lints/src/bool_assert_comparison.rs +++ b/clippy_lints/src/bool_assert_comparison.rs @@ -60,8 +60,8 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - trait_id, ) }) - .map_or(false, |assoc_item| { - let proj = Ty::new_projection_from_args(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, [])); + .is_some_and(|assoc_item| { + let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, [])); let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); nty.is_bool() diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 26a20bc99a05..896bd5fd03d5 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -667,5 +667,5 @@ fn implements_ord(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = cx.typeck_results().expr_ty(expr); cx.tcx .get_diagnostic_item(sym::Ord) - .map_or(false, |id| implements_trait(cx, ty, id, &[])) + .is_some_and(|id| implements_trait(cx, ty, id, &[])) } diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index bf1d077fec28..a1ca23e65ff1 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -45,7 +45,7 @@ impl LateLintPass<'_> for BoxDefault { // 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()) + && path_def_id(cx, ty).is_some_and(|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()` (or default equivalent) of `Box::new(T::default())` && let ExprKind::Call(arg_path, _) = arg.kind @@ -83,9 +83,9 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool { } 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) - }) + macro_backtrace(expr.span) + .next() + .is_some_and(|call| cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span)) } #[derive(Default)] diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index abd80abffe69..332e897def7e 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -159,8 +159,7 @@ pub(super) fn check<'tcx>( // The same is true if the expression encompassing the cast expression is a unary // expression or an addressof expression. let needs_block = matches!(cast_expr.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)) - || get_parent_expr(cx, expr) - .map_or(false, |e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))); + || get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index b9baf9af248e..c85e3500ebdc 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -110,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain { let is_ord = cx .tcx .get_diagnostic_item(sym::Ord) - .map_or(false, |id| implements_trait(cx, ty, id, &[])); + .is_some_and(|id| implements_trait(cx, ty, id, &[])); if !is_ord { return; diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index c4afdc757d81..3ecd36d3711f 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -345,7 +345,7 @@ fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool { let mut i = 0usize; let mut res = true; l.pat.each_binding_or_first(&mut |_, _, _, name| { - if names.get(i).map_or(false, |&(_, n)| n == name.name) { + if names.get(i).is_some_and(|&(_, n)| n == name.name) { i += 1; } else { res = false; @@ -389,12 +389,10 @@ fn eq_stmts( let new_bindings = &moved_bindings[old_count..]; blocks .iter() - .all(|b| get_stmt(b).map_or(false, |s| eq_binding_names(s, new_bindings))) + .all(|b| get_stmt(b).is_some_and(|s| eq_binding_names(s, new_bindings))) } else { true - }) && blocks - .iter() - .all(|b| get_stmt(b).map_or(false, |s| eq.eq_stmt(s, stmt))) + }) && blocks.iter().all(|b| get_stmt(b).is_some_and(|s| eq.eq_stmt(s, stmt))) } #[expect(clippy::too_many_lines)] @@ -451,9 +449,7 @@ fn scan_block_for_eq<'tcx>( // x + 50 let expr_hash_eq = if let Some(e) = block.expr { let hash = hash_expr(cx, e); - blocks - .iter() - .all(|b| b.expr.map_or(false, |e| hash_expr(cx, e) == hash)) + blocks.iter().all(|b| b.expr.is_some_and(|e| hash_expr(cx, e) == hash)) } else { blocks.iter().all(|b| b.expr.is_none()) }; @@ -514,7 +510,7 @@ fn scan_block_for_eq<'tcx>( }); if let Some(e) = block.expr { for block in blocks { - if block.expr.map_or(false, |expr| !eq.eq_expr(expr, e)) { + if block.expr.is_some_and(|expr| !eq.eq_expr(expr, e)) { moved_locals.truncate(moved_locals_at_start); return BlockEq { start_end_eq, @@ -533,7 +529,7 @@ fn scan_block_for_eq<'tcx>( } fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbol)], if_expr: &Expr<'_>) -> bool { - get_enclosing_block(cx, if_expr.hir_id).map_or(false, |block| { + get_enclosing_block(cx, if_expr.hir_id).is_some_and(|block| { let ignore_span = block.span.shrink_to_lo().to(if_expr.span); symbols diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index edb52851e0cb..dff60f76b746 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -481,6 +481,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, + crate::methods::UNNECESSARY_MAP_OR_INFO, crate::methods::UNNECESSARY_MIN_OR_MAX_INFO, crate::methods::UNNECESSARY_RESULT_MAP_OR_ELSE_INFO, crate::methods::UNNECESSARY_SORT_BY_INFO, diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index 4808c372754c..ef6b141920d0 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -253,6 +253,6 @@ impl<'tcx> From> for ExplicitTyBound { impl<'tcx> From>> for ExplicitTyBound { fn from(v: Option>) -> Self { - Self(v.map_or(false, Ty::is_numeric)) + Self(v.is_some_and(Ty::is_numeric)) } } diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 2b6bfafe695b..767dda552bcd 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -81,7 +81,7 @@ fn is_path_self(e: &Expr<'_>) -> bool { fn contains_trait_object(ty: Ty<'_>) -> bool { match ty.kind() { ty::Ref(_, ty, _) => contains_trait_object(*ty), - ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object), + ty::Adt(def, args) => def.is_box() && args[0].as_type().is_some_and(contains_trait_object), ty::Dynamic(..) => true, _ => false, } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index e569c4dc7863..0db6a822ec05 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -327,7 +327,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h // there's a Copy impl for any instance of the adt. if !is_copy(cx, ty) { if ty_subs.non_erasable_generics().next().is_some() { - let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).map_or(false, |impls| { + let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).is_some_and(|impls| { impls.iter().any(|&id| { matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()) diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index c9173030a55e..40377dd841e0 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -47,7 +47,7 @@ pub fn check( ), _ => (), } - if !headers.panics && panic_info.map_or(false, |el| !el.1) { + if !headers.panics && panic_info.is_some_and(|el| !el.1) { span_lint_and_note( cx, MISSING_PANICS_DOC, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index c7dd7292a14b..55afdbf22e1f 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { MEM_FORGET, Cow::Owned(format!( "usage of `mem::forget` on {}", - if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) { + if arg_ty.ty_adt_def().is_some_and(|def| def.has_dtor(cx.tcx)) { "`Drop` type" } else { "type with `Drop` fields" diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index de10b7bf5339..6c87a05ace39 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -196,7 +196,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { - if path_to_local(callee).map_or(false, |l| { + if path_to_local(callee).is_some_and(|l| { // FIXME: Do we really need this `local_used_in` check? // Isn't it checking something like... `callee(callee)`? // If somehow this check is needed, add some test for it, diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index c2b40ae01d4c..4986a311eba8 100644 --- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -87,7 +87,7 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option { } fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) { - if path_to_local(arg).map_or(false, |id| raw_ptrs.contains(&id)) { + if path_to_local(arg).is_some_and(|id| raw_ptrs.contains(&id)) { span_lint( cx, NOT_UNSAFE_PTR_ARG_DEREF, diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 48874d6064b6..d3aade31f14f 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -171,13 +171,13 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { if let ExprKind::Path(ref qpath) = path.kind { cx.qpath_res(qpath, path.hir_id) .opt_def_id() - .map_or(false, |id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id)) + .is_some_and(|id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id)) .into() } else { Finite } }, - ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(), + ExprKind::Struct(..) => higher::Range::hir(expr).is_some_and(|r| r.end.is_none()).into(), _ => Finite, } } @@ -228,9 +228,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { let not_double_ended = cx .tcx .get_diagnostic_item(sym::DoubleEndedIterator) - .map_or(false, |id| { - !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[]) - }); + .is_some_and(|id| !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[])); if not_double_ended { return is_infinite(cx, receiver); } diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index dd90e2a6e94f..6363f717a5c2 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -309,8 +309,8 @@ fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_> let item_name_chars = item_name.chars().count(); if count_match_start(item_name, name).char_count == item_name_chars - && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) - && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) + && name.chars().nth(item_name_chars).is_some_and(|c| !c.is_lowercase()) + && name.chars().nth(item_name_chars + 1).is_some_and(|c| !c.is_numeric()) { span_lint_hir( cx, diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index b19b348c7430..25105817ad97 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -75,7 +75,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe if cx .tcx .get_diagnostic_item(sym::Iterator) - .map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[])) + .is_some_and(|iter_id| !implements_trait(cx, ret_ty, iter_id, &[])) { span_lint( cx, diff --git a/clippy_lints/src/large_const_arrays.rs b/clippy_lints/src/large_const_arrays.rs index 44b9d6adaaab..c5a2760234fc 100644 --- a/clippy_lints/src/large_const_arrays.rs +++ b/clippy_lints/src/large_const_arrays.rs @@ -56,7 +56,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && !item.span.from_expansion() && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Array(element_type, cst) = ty.kind() - && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx.try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree() + && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx + .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree() && let element_count = element_count.to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index ab3d19f89c3f..4f22931a4ded 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -94,6 +94,8 @@ impl LateLintPass<'_> for LargeIncludeFile { // Currently, rustc limits the usage of macro at the top-level of attributes, // so we don't need to recurse into each level. && let AttrKind::Normal(ref normal) = attr.kind + && let Some(doc) = attr.doc_str() + && doc.as_str().len() as u64 > self.max_file_size && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index b7887ef76a53..3ea758e176f0 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -622,7 +622,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let ty = &cx.typeck_results().expr_ty(expr).peel_refs(); match ty.kind() { - ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| { + ty::Dynamic(tt, ..) => tt.principal().is_some_and(|principal| { let is_empty = sym!(is_empty); cx.tcx .associated_items(principal.def_id()) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index d55be2b036ac..ce0e1a24a7b5 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -737,7 +737,7 @@ fn elision_suggestions( suggestions.extend( usages .iter() - .filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id))) + .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id))) .map(|usage| { match cx.tcx.parent_hir_node(usage.hir_id) { Node::Ty(Ty { diff --git a/clippy_lints/src/loops/manual_find.rs b/clippy_lints/src/loops/manual_find.rs index bfe2e68b5d1f..1721f569541b 100644 --- a/clippy_lints/src/loops/manual_find.rs +++ b/clippy_lints/src/loops/manual_find.rs @@ -58,7 +58,7 @@ pub(super) fn check<'tcx>( .tcx .lang_items() .copy_trait() - .map_or(false, |id| implements_trait(cx, ty, id, &[])) + .is_some_and(|id| implements_trait(cx, ty, id, &[])) { snippet.push_str( &format!( diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index af0894517595..701567a7d84e 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -416,7 +416,7 @@ fn get_assignments<'a, 'tcx>( .chain(*expr) .filter(move |e| { if let ExprKind::AssignOp(_, place, _) = e.kind { - path_to_local(place).map_or(false, |id| { + path_to_local(place).is_some_and(|id| { !loop_counters .iter() // skip the first item which should be `StartKind::Range` diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index 094b19473244..39e5e140b7a4 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -126,7 +126,7 @@ impl BreakAfterExprVisitor { break_after_expr: false, }; - get_enclosing_block(cx, hir_id).map_or(false, |block| { + get_enclosing_block(cx, hir_id).is_some_and(|block| { visitor.visit_block(block); visitor.break_after_expr }) diff --git a/clippy_lints/src/loops/same_item_push.rs b/clippy_lints/src/loops/same_item_push.rs index d255fea3af20..951ebc9caef0 100644 --- a/clippy_lints/src/loops/same_item_push.rs +++ b/clippy_lints/src/loops/same_item_push.rs @@ -50,7 +50,7 @@ pub(super) fn check<'tcx>( .tcx .lang_items() .clone_trait() - .map_or(false, |id| implements_trait(cx, ty, id, &[])) + .is_some_and(|id| implements_trait(cx, ty, id, &[])) { // Make sure that the push does not involve possibly mutating values match pushed_item.kind { diff --git a/clippy_lints/src/loops/utils.rs b/clippy_lints/src/loops/utils.rs index c4c504e1ae4f..51fde5288ab9 100644 --- a/clippy_lints/src/loops/utils.rs +++ b/clippy_lints/src/loops/utils.rs @@ -256,9 +256,10 @@ fn is_conditional(expr: &Expr<'_>) -> bool { /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the /// actual `Iterator` that the loop uses. pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String { - let impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { - implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[]) - }); + let impls_iterator = cx + .tcx + .get_diagnostic_item(sym::Iterator) + .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])); if impls_iterator { format!( "{}", diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index fd66cacdfe93..016ec7320a6a 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -226,7 +226,7 @@ impl TypeClampability { } else if cx .tcx .get_diagnostic_item(sym::Ord) - .map_or(false, |id| implements_trait(cx, ty, id, &[])) + .is_some_and(|id| implements_trait(cx, ty, id, &[])) { Some(TypeClampability::Ord) } else { diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 828c5a3f6ffd..3f401eff6bdb 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -162,9 +162,9 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t .. }) = expr.kind { - constant_length(cx, pattern).map_or(false, |length| *n == length) + constant_length(cx, pattern).is_some_and(|length| *n == length) } else { - len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg)) + len_arg(cx, expr).is_some_and(|arg| eq_expr_value(cx, pattern, arg)) } } diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index 6d62b530ae7e..47472ab831f2 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -74,7 +74,7 @@ where && b0 != b1 && (first_guard.is_none() || iter.len() == 0) && first_attrs.is_empty() - && iter.all(|arm| find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty()) + && iter.all(|arm| find_bool_lit(&arm.2.kind).is_some_and(|b| b == b0) && arm.3.is_none() && arm.0.is_empty()) { if let Some(last_pat) = last_pat_opt { if !is_wild(last_pat) { diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index ca45ed6ea59c..264458a86ef4 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -447,7 +447,7 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte .tcx .lang_items() .get(expected_lang_item) - .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id), + .is_some_and(|expected_id| cx.tcx.parent(id) == expected_id), Item::Diag(expected_ty, expected_variant) => { let ty = cx.typeck_results().pat_ty(pat); diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 2aea25b5f12a..95a4bf6f60de 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -175,7 +175,7 @@ impl<'tcx> Visitor<'tcx> for PatVisitor<'tcx> { if matches!(pat.kind, PatKind::Binding(..)) { ControlFlow::Break(()) } else { - self.has_enum |= self.typeck.pat_ty(pat).ty_adt_def().map_or(false, AdtDef::is_enum); + self.has_enum |= self.typeck.pat_ty(pat).ty_adt_def().is_some_and(AdtDef::is_enum); walk_pat(self, pat) } } diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs index c7e1b70d19e7..6c02207af49d 100644 --- a/clippy_lints/src/matches/try_err.rs +++ b/clippy_lints/src/matches/try_err.rs @@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt()); let mut applicability = Applicability::MachineApplicable; let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability); - let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) { + let ret_prefix = if get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Ret(_))) { "" // already returns } else { "return " diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index c288dbdabe96..6dc48c26ba93 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -83,7 +83,7 @@ pub(super) fn check<'tcx>( hir::ExprKind::MethodCall(..) => { cx.typeck_results() .type_dependent_def_id(arg.hir_id) - .map_or(false, |method_id| { + .is_some_and(|method_id| { matches!( cx.tcx.fn_sig(method_id).instantiate_identity().output().skip_binder().kind(), ty::Ref(re, ..) if re.is_static() diff --git a/clippy_lints/src/methods/filter_next.rs b/clippy_lints/src/methods/filter_next.rs index e697ba656f5f..6c1a14fc8829 100644 --- a/clippy_lints/src/methods/filter_next.rs +++ b/clippy_lints/src/methods/filter_next.rs @@ -32,9 +32,10 @@ pub(super) fn check<'tcx>( filter_arg: &'tcx hir::Expr<'_>, ) { // lint if caller of `.filter().next()` is an Iterator - let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { - implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[]) - }); + let recv_impls_iterator = cx + .tcx + .get_diagnostic_item(sym::Iterator) + .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[])); if recv_impls_iterator { let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \ `.find(..)` instead"; diff --git a/clippy_lints/src/methods/manual_next_back.rs b/clippy_lints/src/methods/manual_next_back.rs index 5f3fec53827a..9a03559b2237 100644 --- a/clippy_lints/src/methods/manual_next_back.rs +++ b/clippy_lints/src/methods/manual_next_back.rs @@ -19,9 +19,7 @@ pub(super) fn check<'tcx>( if cx .tcx .get_diagnostic_item(sym::DoubleEndedIterator) - .map_or(false, |double_ended_iterator| { - implements_trait(cx, rev_recv_ty, double_ended_iterator, &[]) - }) + .is_some_and(|double_ended_iterator| implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])) && is_trait_method(cx, rev_call, sym::Iterator) && is_trait_method(cx, expr, sym::Iterator) { diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 61e74369cb05..098721dc046f 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -36,8 +36,8 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { } else { let ty = cx.typeck_results().expr_ty(e); if is_type_lang_item(cx, ty, LangItem::String) - || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, Ty::is_str)) - || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, Ty::is_str)) + || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).is_some_and(Ty::is_str)) + || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).is_some_and(Ty::is_str)) { Some(RepeatKind::String) } else { diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 515d4a11ed51..d5594b21db5d 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -70,7 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ if ident_eq(name, obj) && method.ident.name == sym::clone && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id) && let Some(trait_id) = cx.tcx.trait_of_item(fn_id) - && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id) + && cx.tcx.lang_items().clone_trait() == Some(trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index b1809796355d..795e041ffd9d 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -121,6 +121,7 @@ mod unnecessary_iter_cloned; mod unnecessary_join; mod unnecessary_lazy_eval; mod unnecessary_literal_unwrap; +mod unnecessary_map_or; mod unnecessary_min_or_max; mod unnecessary_result_map_or_else; mod unnecessary_sort_by; @@ -4099,6 +4100,33 @@ declare_clippy_lint! { "is_empty() called on strings known at compile time" } +declare_clippy_lint! { + /// ### What it does + /// Converts some constructs mapping an Enum value for equality comparison. + /// + /// ### Why is this bad? + /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome, + /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`. + /// This lint offers readability and conciseness improvements. + /// + /// ### Example + /// ```no_run + /// pub fn a(x: Option) -> bool { + /// x.map_or(false, |n| n == 5) + /// } + /// ``` + /// Use instead: + /// ```no_run + /// pub fn a(x: Option) -> bool { + /// x == Some(5) + /// } + /// ``` + #[clippy::version = "1.75.0"] + pub UNNECESSARY_MAP_OR, + style, + "reduce unnecessary pattern matching for constructs that implement `PartialEq`" +} + declare_clippy_lint! { /// ### What it does /// Checks if an iterator is used to check if a string is ascii. @@ -4417,6 +4445,7 @@ impl_lint_pass!(Methods => [ NEEDLESS_AS_BYTES, MAP_ALL_ANY_IDENTITY, MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES, + UNNECESSARY_MAP_OR, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -4950,6 +4979,7 @@ impl Methods { option_map_or_none::check(cx, expr, recv, def, map); manual_ok_or::check(cx, expr, recv, def, map); option_map_or_err_ok::check(cx, expr, recv, def, map); + unnecessary_map_or::check(cx, expr, recv, def, map, &self.msrv); }, ("map_or_else", [def, map]) => { result_map_or_else_none::check(cx, expr, recv, def, map); @@ -5343,7 +5373,7 @@ impl SelfKind { boxed_ty == parent_ty } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) { if let ty::Adt(_, args) = ty.kind() { - args.types().next().map_or(false, |t| t == parent_ty) + args.types().next() == Some(parent_ty) } else { false } diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 055107068ae0..9c41528e6476 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -193,7 +193,7 @@ fn check_collect_into_intoiterator<'tcx>( /// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool` fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool { - cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| { + cx.typeck_results().type_dependent_def_id(call_id).is_some_and(|id| { let sig = cx.tcx.fn_sig(id).instantiate_identity().skip_binder(); sig.inputs().len() == 1 && sig.output().is_bool() }) diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 389e02056b2b..998bdee01576 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -45,7 +45,7 @@ pub(super) fn check( hir::ExprKind::Path(ref expr_qpath) => { cx.qpath_res(expr_qpath, map_arg.hir_id) .opt_def_id() - .map_or(false, |fun_def_id| { + .is_some_and(|fun_def_id| { cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id) || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id) || deref_aliases diff --git a/clippy_lints/src/methods/or_fun_call.rs b/clippy_lints/src/methods/or_fun_call.rs index b685a466b728..6b39b753885e 100644 --- a/clippy_lints/src/methods/or_fun_call.rs +++ b/clippy_lints/src/methods/or_fun_call.rs @@ -59,9 +59,7 @@ pub(super) fn check<'tcx>( let output_ty = cx.tcx.fn_sig(def_id).instantiate(cx.tcx, args).skip_binder().output(); cx.tcx .get_diagnostic_item(sym::Default) - .map_or(false, |default_trait_id| { - implements_trait(cx, output_ty, default_trait_id, &[]) - }) + .is_some_and(|default_trait_id| implements_trait(cx, output_ty, default_trait_id, &[])) } else { false } diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index a2a7de905caf..1cee28e19861 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -348,7 +348,7 @@ fn parse_iter_usage<'tcx>( && cx .typeck_results() .type_dependent_def_id(e.hir_id) - .map_or(false, |id| is_diag_item_method(cx, id, sym::Option)) => + .is_some_and(|id| is_diag_item_method(cx, id, sym::Option)) => { (Some(UnwrapKind::Unwrap), e.span) }, diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs new file mode 100644 index 000000000000..adc27cd437f4 --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -0,0 +1,131 @@ +use std::borrow::Cow; + +use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::source::snippet_opt; +use clippy_utils::sugg::{Sugg, make_binop}; +use clippy_utils::ty::{get_type_diagnostic_name, implements_trait}; +use clippy_utils::visitors::is_local_used; +use clippy_utils::{is_from_proc_macro, path_to_local_id}; +use rustc_ast::LitKind::Bool; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind}; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::UNNECESSARY_MAP_OR; + +pub(super) enum Variant { + Ok, + Some, +} +impl Variant { + pub fn variant_name(&self) -> &'static str { + match self { + Variant::Ok => "Ok", + Variant::Some => "Some", + } + } + + pub fn method_name(&self) -> &'static str { + match self { + Variant::Ok => "is_ok_and", + Variant::Some => "is_some_and", + } + } +} + +pub(super) fn check<'a>( + cx: &LateContext<'a>, + expr: &Expr<'a>, + recv: &Expr<'_>, + def: &Expr<'_>, + map: &Expr<'_>, + msrv: &Msrv, +) { + let ExprKind::Lit(def_kind) = def.kind else { + return; + }; + + let recv_ty = cx.typeck_results().expr_ty(recv); + + let Bool(def_bool) = def_kind.node else { + return; + }; + + let variant = match get_type_diagnostic_name(cx, recv_ty) { + Some(sym::Option) => Variant::Some, + Some(sym::Result) => Variant::Ok, + Some(_) | None => return, + }; + + let (sugg, method) = if let ExprKind::Closure(map_closure) = map.kind + && let closure_body = cx.tcx.hir().body(map_closure.body) + && let closure_body_value = closure_body.value.peel_blocks() + && let ExprKind::Binary(op, l, r) = closure_body_value.kind + && let Some(param) = closure_body.params.first() + && let PatKind::Binding(_, hir_id, _, _) = param.pat.kind + // checking that map_or is one of the following: + // .map_or(false, |x| x == y) + // .map_or(false, |x| y == x) - swapped comparison + // .map_or(true, |x| x != y) + // .map_or(true, |x| y != x) - swapped comparison + && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool)) + && let non_binding_location = if path_to_local_id(l, hir_id) { r } else { l } + && switch_to_eager_eval(cx, non_binding_location) + // xor, because if its both then thats a strange edge case and + // we can just ignore it, since by default clippy will error on this + && (path_to_local_id(l, hir_id) ^ path_to_local_id(r, hir_id)) + && !is_local_used(cx, non_binding_location, hir_id) + && let typeck_results = cx.typeck_results() + && typeck_results.expr_ty(l) == typeck_results.expr_ty(r) + && let Some(partial_eq) = cx.tcx.get_diagnostic_item(sym::PartialEq) + && implements_trait(cx, recv_ty, partial_eq, &[recv_ty.into()]) + { + let wrap = variant.variant_name(); + + // we may need to add parens around the suggestion + // in case the parent expression has additional method calls, + // since for example `Some(5).map_or(false, |x| x == 5).then(|| 1)` + // being converted to `Some(5) == Some(5).then(|| 1)` isnt + // the same thing + + let inner_non_binding = Sugg::NonParen(Cow::Owned(format!( + "{wrap}({})", + Sugg::hir(cx, non_binding_location, "") + ))); + + let binop = make_binop(op.node, &Sugg::hir(cx, recv, ".."), &inner_non_binding) + .maybe_par() + .into_string(); + + (binop, "a standard comparison") + } else if !def_bool + && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) + && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite()) + && let Some(span_callsite) = snippet_opt(cx, map.span.source_callsite()) + { + let suggested_name = variant.method_name(); + ( + format!("{recv_callsite}.{suggested_name}({span_callsite})",), + suggested_name, + ) + } else { + return; + }; + + if is_from_proc_macro(cx, expr) { + return; + } + + span_lint_and_sugg( + cx, + UNNECESSARY_MAP_OR, + expr.span, + "this `map_or` is redundant", + format!("use {method} instead"), + sugg, + Applicability::MaybeIncorrect, + ); +} diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs index 6911da69b945..603916e06c95 100644 --- a/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -166,9 +166,10 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp }, )) = &left_expr.kind && left_name == left_ident - && cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| { - implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[]) - }) + && cx + .tcx + .get_diagnostic_item(sym::Ord) + .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])) { return Some(LintTrigger::Sort(SortDetection { vec_name })); } diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index c309e7781166..82313257e5c4 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -124,7 +124,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id) && let Some(trait_id) = cx.tcx.trait_of_item(fn_id) // We check it's the `Clone` trait. - && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id) + && cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 4cba13a05c24..37d7427f9a5d 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -427,7 +427,7 @@ impl MiscEarlyLints { // See for a regression. // FIXME: Find a better way to detect those cases. let lit_snip = match snippet_opt(cx, span) { - Some(snip) if snip.chars().next().map_or(false, |c| c.is_ascii_digit()) => snip, + Some(snip) if snip.chars().next().is_some_and(|c| c.is_ascii_digit()) => snip, _ => return, }; diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index f7fa31d83aa4..c1424b9f1dc8 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -134,9 +134,11 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { } fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &Body<'_>) { - if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| { - local_def_id == cx.tcx.hir().body_owner_def_id(body.id()) - }) { + if self + .possible_borrowers + .last() + .is_some_and(|&(local_def_id, _)| local_def_id == cx.tcx.hir().body_owner_def_id(body.id())) + { self.possible_borrowers.pop(); } } @@ -232,7 +234,7 @@ fn needless_borrow_count<'tcx>( let mut check_reference_and_referent = |reference: &Expr<'tcx>, referent: &Expr<'tcx>| { if let ExprKind::Field(base, _) = &referent.kind { let base_ty = cx.typeck_results().expr_ty(base); - if drop_trait_def_id.map_or(false, |id| implements_trait(cx, base_ty, id, &[])) { + if drop_trait_def_id.is_some_and(|id| implements_trait(cx, base_ty, id, &[])) { return false; } } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index c48367729336..c48232f99058 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -153,7 +153,7 @@ fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>) } fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool { - block.stmts.first().map_or(false, |stmt| match stmt.kind { + block.stmts.first().is_some_and(|stmt| match stmt.kind { ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => { if let ast::ExprKind::Continue(ref l) = e.kind { compare_labels(label, l.as_ref()) @@ -390,7 +390,7 @@ fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) { #[must_use] fn erode_from_back(s: &str) -> String { let mut ret = s.to_string(); - while ret.pop().map_or(false, |c| c != '}') {} + while ret.pop().is_some_and(|c| c != '}') {} while let Some(c) = ret.pop() { if !c.is_whitespace() { ret.push(c); diff --git a/clippy_lints/src/nonstandard_macro_braces.rs b/clippy_lints/src/nonstandard_macro_braces.rs index a13391a59457..83f7d9319697 100644 --- a/clippy_lints/src/nonstandard_macro_braces.rs +++ b/clippy_lints/src/nonstandard_macro_braces.rs @@ -88,7 +88,7 @@ fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBrace || span .macro_backtrace() .last() - .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local)) + .is_some_and(|e| e.macro_def_id.is_some_and(DefId::is_local)) }; let span_call_site = span.ctxt().outer_expn_data().call_site; if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind diff --git a/clippy_lints/src/only_used_in_recursion.rs b/clippy_lints/src/only_used_in_recursion.rs index 372128ac16f0..13b3d2407007 100644 --- a/clippy_lints/src/only_used_in_recursion.rs +++ b/clippy_lints/src/only_used_in_recursion.rs @@ -290,7 +290,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { Some((Node::Expr(parent), child_id)) => match parent.kind { // Recursive call. Track which index the parameter is used in. ExprKind::Call(callee, args) - if path_def_id(cx, callee).map_or(false, |id| { + if path_def_id(cx, callee).is_some_and(|id| { id == param.fn_id && has_matching_args(param.fn_kind, typeck.node_args(callee.hir_id)) }) => { @@ -300,7 +300,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { return; }, ExprKind::MethodCall(_, receiver, args, _) - if typeck.type_dependent_def_id(parent.hir_id).map_or(false, |id| { + if typeck.type_dependent_def_id(parent.hir_id).is_some_and(|id| { id == param.fn_id && has_matching_args(param.fn_kind, typeck.node_args(parent.hir_id)) }) => { diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 8b9f899d82d3..65ef56fd2112 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -325,7 +325,7 @@ impl ArithmeticSideEffects { fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool { is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id) || self.expr_span.is_some() - || self.const_span.map_or(false, |sp| sp.contains(expr.span)) + || self.const_span.is_some_and(|sp| sp.contains(expr.span)) } } diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index 208b20a7a069..b0d872e98fd4 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -42,14 +42,12 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) if typeck .type_dependent_def_id(expr.hir_id) .and_then(|id| cx.tcx.trait_of_item(id)) - .map_or(false, |id| { - matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned)) - }) => + .is_some_and(|id| matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned))) => { (arg, arg.span) }, ExprKind::Call(path, [arg]) - if path_def_id(cx, path).map_or(false, |did| { + if path_def_id(cx, path).is_some_and(|did| { if cx.tcx.is_diagnostic_item(sym::from_str_method, did) { true } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) { diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs index 830be50c8ba4..1c2d6e90fc95 100644 --- a/clippy_lints/src/operators/identity_op.rs +++ b/clippy_lints/src/operators/identity_op.rs @@ -42,83 +42,43 @@ pub(crate) fn check<'tcx>( match op { BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => { - let _ = check_op( - cx, - left, - 0, - expr.span, - peeled_right_span, - needs_parenthesis(cx, expr, right), - right_is_coerced_to_value, - ) || check_op( - cx, - right, - 0, - expr.span, - peeled_left_span, - Parens::Unneeded, - left_is_coerced_to_value, - ); + if is_redundant_op(cx, left, 0) { + let paren = needs_parenthesis(cx, expr, right); + span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value); + } else if is_redundant_op(cx, right, 0) { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); + } }, BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => { - let _ = check_op( - cx, - right, - 0, - expr.span, - peeled_left_span, - Parens::Unneeded, - left_is_coerced_to_value, - ); + if is_redundant_op(cx, right, 0) { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); + } }, BinOpKind::Mul => { - let _ = check_op( - cx, - left, - 1, - expr.span, - peeled_right_span, - needs_parenthesis(cx, expr, right), - right_is_coerced_to_value, - ) || check_op( - cx, - right, - 1, - expr.span, - peeled_left_span, - Parens::Unneeded, - left_is_coerced_to_value, - ); + if is_redundant_op(cx, left, 1) { + let paren = needs_parenthesis(cx, expr, right); + span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value); + } else if is_redundant_op(cx, right, 1) { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); + } }, BinOpKind::Div => { - let _ = check_op( - cx, - right, - 1, - expr.span, - peeled_left_span, - Parens::Unneeded, - left_is_coerced_to_value, - ); + if is_redundant_op(cx, right, 1) { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); + } }, BinOpKind::BitAnd => { - let _ = check_op( - cx, - left, - -1, - expr.span, - peeled_right_span, - needs_parenthesis(cx, expr, right), - right_is_coerced_to_value, - ) || check_op( - cx, - right, - -1, - expr.span, - peeled_left_span, - Parens::Unneeded, - left_is_coerced_to_value, - ); + if is_redundant_op(cx, left, -1) { + let paren = needs_parenthesis(cx, expr, right); + span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value); + } else if is_redundant_op(cx, right, -1) { + let paren = needs_parenthesis(cx, expr, left); + span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value); + } }, BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span), _ => (), @@ -138,43 +98,70 @@ enum Parens { Unneeded, } -/// Checks if `left op right` needs parenthesis when reduced to `right` +/// Checks if a binary expression needs parenthesis when reduced to just its +/// right or left child. +/// +/// e.g. `-(x + y + 0)` cannot be reduced to `-x + y`, as the behavior changes silently. +/// e.g. `1u64 + ((x + y + 0i32) as u64)` cannot be reduced to `1u64 + x + y as u64`, since +/// the the cast expression will not apply to the same expression. /// e.g. `0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }` cannot be reduced /// to `if b { 1 } else { 2 } + if b { 3 } else { 4 }` where the `if` could be -/// interpreted as a statement +/// interpreted as a statement. The same behavior happens for `match`, `loop`, +/// and blocks. +/// e.g. `2 * (0 + { a })` can be reduced to `2 * { a }` without the need for parenthesis, +/// but `1 * ({ a } + 4)` cannot be reduced to `{ a } + 4`, as a block at the start of a line +/// will be interpreted as a statement instead of an expression. /// -/// See #8724 -fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>) -> Parens { - match right.kind { +/// See #8724, #13470 +fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, child: &Expr<'_>) -> Parens { + match child.kind { ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) => { - // ensure we're checking against the leftmost expression of `right` - // - // ~~~ `lhs` - // 0 + {4} * 2 - // ~~~~~~~ `right` - return needs_parenthesis(cx, binary, lhs); + // For casts and binary expressions, we want to add parenthesis if + // the parent HIR node is an expression, or if the parent HIR node + // is a Block or Stmt, and the new left hand side would need + // parenthesis be treated as a statement rather than an expression. + if let Some((_, parent)) = cx.tcx.hir().parent_iter(binary.hir_id).next() { + match parent { + Node::Expr(_) => return Parens::Needed, + Node::Block(_) | Node::Stmt(_) => { + // ensure we're checking against the leftmost expression of `child` + // + // ~~~~~~~~~~~ `binary` + // ~~~ `lhs` + // 0 + {4} * 2 + // ~~~~~~~ `child` + return needs_parenthesis(cx, binary, lhs); + }, + _ => return Parens::Unneeded, + } + } + }, + ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Block(..) | ExprKind::Loop(..) => { + // For if, match, block, and loop expressions, we want to add parenthesis if + // the closest ancestor node that is not an expression is a block or statement. + // This would mean that the rustfix suggestion will appear at the start of a line, which causes + // these expressions to be interpreted as statements if they do not have parenthesis. + let mut prev_id = binary.hir_id; + for (_, parent) in cx.tcx.hir().parent_iter(binary.hir_id) { + if let Node::Expr(expr) = parent + && let ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) | ExprKind::Unary(_, lhs) = expr.kind + && lhs.hir_id == prev_id + { + // keep going until we find a node that encompasses left of `binary` + prev_id = expr.hir_id; + continue; + } + + match parent { + Node::Block(_) | Node::Stmt(_) => return Parens::Needed, + _ => return Parens::Unneeded, + }; + } + }, + _ => { + return Parens::Unneeded; }, - ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Block(..) | ExprKind::Loop(..) => {}, - _ => return Parens::Unneeded, } - - let mut prev_id = binary.hir_id; - for (_, node) in cx.tcx.hir().parent_iter(binary.hir_id) { - if let Node::Expr(expr) = node - && let ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) = expr.kind - && lhs.hir_id == prev_id - { - // keep going until we find a node that encompasses left of `binary` - prev_id = expr.hir_id; - continue; - } - - match node { - Node::Block(_) | Node::Stmt(_) => break, - _ => return Parens::Unneeded, - }; - } - Parens::Needed } @@ -199,7 +186,7 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span } } -fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool { +fn is_redundant_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8) -> bool { if let Some(Constant::Int(v)) = ConstEvalCtxt::new(cx).eval_simple(e).map(Constant::peel_refs) { let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() { ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), @@ -212,7 +199,6 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa 1 => v == 1, _ => unreachable!(), } { - span_ineffective_operation(cx, span, arg, parens, is_erased); return true; } } diff --git a/clippy_lints/src/operators/numeric_arithmetic.rs b/clippy_lints/src/operators/numeric_arithmetic.rs index 565294bb40a8..d369978b8be8 100644 --- a/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/clippy_lints/src/operators/numeric_arithmetic.rs @@ -14,7 +14,7 @@ pub struct Context { } impl Context { fn skip_expr(&mut self, e: &hir::Expr<'_>) -> bool { - self.expr_id.is_some() || self.const_span.map_or(false, |span| span.contains(e.span)) + self.expr_id.is_some() || self.const_span.is_some_and(|span| span.contains(e.span)) } pub fn check_binary<'tcx>( diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 1bddfab39c69..b2089487a9f4 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -192,7 +192,7 @@ impl PassByRefOrValue { continue; } } - let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) { + let value_type = if fn_body.and_then(|body| body.params.get(index)).is_some_and(is_self) { "self".into() } else { snippet(cx, decl_ty.span, "_").into() diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index a548c6ef3b1f..ecc095f38599 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -727,9 +727,8 @@ fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutabili fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { if let ExprKind::Call(pathexp, []) = expr.kind { - path_def_id(cx, pathexp).map_or(false, |id| { - matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ptr_null | sym::ptr_null_mut)) - }) + path_def_id(cx, pathexp) + .is_some_and(|id| matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ptr_null | sym::ptr_null_mut))) } else { false } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index cb374fcf20e3..a00fd01a62e0 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -8,18 +8,18 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{ eq_expr_value, higher, is_else_clause, is_in_const_context, is_lint_allowed, is_path_lang_item, is_res_lang_ctor, - pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, - span_contains_comment, + pat_and_expr_can_be_question_mark, path_res, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt, + span_contains_cfg, span_contains_comment, }; use rustc_errors::Applicability; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::Res; use rustc_hir::{ - BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt, - StmtKind, + Arm, BindingMode, Block, Body, ByRef, Expr, ExprKind, FnRetTy, HirId, LetStmt, MatchSource, Mutability, Node, Pat, + PatKind, PathSegment, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -58,6 +58,9 @@ pub struct QuestionMark { /// if it is greater than zero. /// As for why we need this in the first place: try_block_depth_stack: Vec, + /// Keeps track of the number of inferred return type closures we are inside, to avoid problems + /// with the `Err(x.into())` expansion being ambiguious. + inferred_ret_closure_stack: u16, } impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]); @@ -68,6 +71,7 @@ impl QuestionMark { msrv: conf.msrv.clone(), matches_behaviour: conf.matches_for_let_else, try_block_depth_stack: Vec::new(), + inferred_ret_closure_stack: 0, } } } @@ -125,7 +129,7 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { cx.tcx .lang_items() .try_trait() - .map_or(false, |did| implements_trait(cx, init_ty, did, &[])) + .is_some_and(|did| implements_trait(cx, init_ty, did, &[])) } if let StmtKind::Let(LetStmt { @@ -271,6 +275,135 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex } } +#[derive(Clone, Copy, Debug)] +enum TryMode { + Result, + Option, +} + +fn find_try_mode<'tcx>(cx: &LateContext<'tcx>, scrutinee: &Expr<'tcx>) -> Option { + let scrutinee_ty = cx.typeck_results().expr_ty_adjusted(scrutinee); + let ty::Adt(scrutinee_adt_def, _) = scrutinee_ty.kind() else { + return None; + }; + + match cx.tcx.get_diagnostic_name(scrutinee_adt_def.did())? { + sym::Result => Some(TryMode::Result), + sym::Option => Some(TryMode::Option), + _ => None, + } +} + +// Check that `pat` is `{ctor_lang_item}(val)`, returning `val`. +fn extract_ctor_call<'a, 'tcx>( + cx: &LateContext<'tcx>, + expected_ctor: LangItem, + pat: &'a Pat<'tcx>, +) -> Option<&'a Pat<'tcx>> { + if let PatKind::TupleStruct(variant_path, [val_binding], _) = &pat.kind + && is_res_lang_ctor(cx, cx.qpath_res(variant_path, pat.hir_id), expected_ctor) + { + Some(val_binding) + } else { + None + } +} + +// Extracts the local ID of a plain `val` pattern. +fn extract_binding_pat(pat: &Pat<'_>) -> Option { + if let PatKind::Binding(BindingMode::NONE, binding, _, None) = pat.kind { + Some(binding) + } else { + None + } +} + +fn check_arm_is_some_or_ok<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm: &Arm<'tcx>) -> bool { + let happy_ctor = match mode { + TryMode::Result => ResultOk, + TryMode::Option => OptionSome, + }; + + // Check for `Ok(val)` or `Some(val)` + if arm.guard.is_none() + && let Some(val_binding) = extract_ctor_call(cx, happy_ctor, arm.pat) + // Extract out `val` + && let Some(binding) = extract_binding_pat(val_binding) + // Check body is just `=> val` + && path_to_local_id(peel_blocks(arm.body), binding) + { + true + } else { + false + } +} + +fn check_arm_is_none_or_err<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm: &Arm<'tcx>) -> bool { + if arm.guard.is_some() { + return false; + } + + let arm_body = peel_blocks(arm.body); + match mode { + TryMode::Result => { + // Check that pat is Err(val) + if let Some(ok_pat) = extract_ctor_call(cx, ResultErr, arm.pat) + && let Some(ok_val) = extract_binding_pat(ok_pat) + // check `=> return Err(...)` + && let ExprKind::Ret(Some(wrapped_ret_expr)) = arm_body.kind + && let ExprKind::Call(ok_ctor, [ret_expr]) = wrapped_ret_expr.kind + && is_res_lang_ctor(cx, path_res(cx, ok_ctor), ResultErr) + // check `...` is `val` from binding + && path_to_local_id(ret_expr, ok_val) + { + true + } else { + false + } + }, + TryMode::Option => { + // Check the pat is `None` + if is_res_lang_ctor(cx, path_res(cx, arm.pat), OptionNone) + // Check `=> return None` + && let ExprKind::Ret(Some(ret_expr)) = arm_body.kind + && is_res_lang_ctor(cx, path_res(cx, ret_expr), OptionNone) + && !ret_expr.span.from_expansion() + { + true + } else { + false + } + }, + } +} + +fn check_arms_are_try<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm1: &Arm<'tcx>, arm2: &Arm<'tcx>) -> bool { + (check_arm_is_some_or_ok(cx, mode, arm1) && check_arm_is_none_or_err(cx, mode, arm2)) + || (check_arm_is_some_or_ok(cx, mode, arm2) && check_arm_is_none_or_err(cx, mode, arm1)) +} + +fn check_if_try_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal | MatchSource::Postfix) = expr.kind + && !expr.span.from_expansion() + && let Some(mode) = find_try_mode(cx, scrutinee) + && !span_contains_cfg(cx, expr.span) + && check_arms_are_try(cx, mode, arm1, arm2) + { + let mut applicability = Applicability::MachineApplicable; + let snippet = snippet_with_applicability(cx, scrutinee.span.source_callsite(), "..", &mut applicability); + + span_lint_and_sugg( + cx, + QUESTION_MARK, + expr.span, + "this `match` expression can be replaced with `?`", + "try instead", + snippet.into_owned() + "?", + applicability, + ); + } +} + fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if let Some(higher::IfLet { let_pat, @@ -339,6 +472,17 @@ fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool { } } +fn is_inferred_ret_closure(expr: &Expr<'_>) -> bool { + let ExprKind::Closure(closure) = expr.kind else { + return false; + }; + + match closure.fn_decl.output { + FnRetTy::Return(ret_ty) => ret_ty.is_suggestable_infer_ty(), + FnRetTy::DefaultReturn(_) => true, + } +} + impl<'tcx> LateLintPass<'tcx> for QuestionMark { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) { @@ -350,11 +494,27 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { } self.check_manual_let_else(cx, stmt); } + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if is_inferred_ret_closure(expr) { + self.inferred_ret_closure_stack += 1; + return; + } + if !self.inside_try_block() && !is_in_const_context(cx) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) { check_is_none_or_err_and_early_return(cx, expr); check_if_let_some_or_err_and_early_return(cx, expr); + + if self.inferred_ret_closure_stack == 0 { + check_if_try_match(cx, expr); + } + } + } + + fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if is_inferred_ret_closure(expr) { + self.inferred_ret_closure_stack -= 1; } } diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index 030df535c35d..dc66fb28fa8c 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr)); let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); - let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX); + let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence().order() > PREC_PREFIX); if expr_ty == indexed_ty { if expr_ref_count > indexed_ref_count { @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _), .. }) - ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| { + ) || cx.typeck_results().expr_adjustments(expr).first().is_some_and(|a| { matches!( a.kind, Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut { .. })) diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 23362506ccad..78f0b7d121c2 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -412,9 +412,7 @@ impl<'tcx> IndexBinding<'_, 'tcx> { } Self::is_used_slice_indexed(lhs, idx_ident) || Self::is_used_slice_indexed(rhs, idx_ident) }, - ExprKind::Path(QPath::Resolved(_, path)) => { - path.segments.first().map_or(false, |idx| idx.ident == idx_ident) - }, + ExprKind::Path(QPath::Resolved(_, path)) => path.segments.first().is_some_and(|idx| idx.ident == idx_ident), _ => false, } } diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index eb7ffbbe360d..bde88ab61adf 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -51,8 +51,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m format!("&{ltopt}({inner_snippet})") }, TyKind::Path(qpath) - if get_bounds_if_impl_trait(cx, qpath, inner.hir_id) - .map_or(false, |bounds| bounds.len() > 1) => + if get_bounds_if_impl_trait(cx, qpath, inner.hir_id).is_some_and(|bounds| bounds.len() > 1) => { format!("&{ltopt}({inner_snippet})") }, diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index 1a1284ce9c43..6eef582b4b28 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { return; } - if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer)) + if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer)) || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none())) && expr_needs_inferred_result(cx, init) { diff --git a/clippy_lints/src/vec_init_then_push.rs b/clippy_lints/src/vec_init_then_push.rs index 91dff5a95236..cbc6885ae5de 100644 --- a/clippy_lints/src/vec_init_then_push.rs +++ b/clippy_lints/src/vec_init_then_push.rs @@ -98,7 +98,7 @@ impl VecPushSearcher { needs_mut |= cx.typeck_results().expr_ty_adjusted(last_place).ref_mutability() == Some(Mutability::Mut) || get_parent_expr(cx, last_place) - .map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _))); + .is_some_and(|e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _))); }, ExprKind::MethodCall(_, recv, ..) if recv.hir_id == e.hir_id diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 1dd46ed5a891..a42ddcdae353 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -295,7 +295,7 @@ impl<'tcx> LateLintPass<'tcx> for Write { .opts .crate_name .as_ref() - .map_or(false, |crate_name| crate_name == "build_script_build"); + .is_some_and(|crate_name| crate_name == "build_script_build"); let allowed_in_tests = self.allow_print_in_tests && is_in_test(cx.tcx, expr.hir_id); match diag_name { diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 75169e05734a..3269bf758ac0 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -51,7 +51,7 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> return false; }; let end = span.hi() - pos.sf.start_pos; - src.get(pos.pos.0 as usize..end.0 as usize).map_or(false, |s| { + src.get(pos.pos.0 as usize..end.0 as usize).is_some_and(|s| { // Spans can be wrapped in a mixture or parenthesis, whitespace, and trailing commas. let start_str = s.trim_start_matches(|c: char| c.is_whitespace() || c == '('); let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ','); @@ -60,13 +60,13 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => start_str.starts_with(sym.as_str()), - Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit), + Pat::Num => start_str.as_bytes().first().is_some_and(u8::is_ascii_digit), } && match end_pat { Pat::Str(text) => end_str.ends_with(text), Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), - Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit), + Pat::Num => end_str.as_bytes().last().is_some_and(u8::is_ascii_hexdigit), }) }) } diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index cb69f8e5a0ed..c73ab4bfa688 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -258,7 +258,7 @@ impl HirEqInterExpr<'_, '_, '_> { } fn should_ignore(&mut self, expr: &Expr<'_>) -> bool { - macro_backtrace(expr.span).last().map_or(false, |macro_call| { + macro_backtrace(expr.span).last().is_some_and(|macro_call| { matches!( &self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id), Some(sym::todo_macro | sym::unimplemented_macro) @@ -322,7 +322,7 @@ impl HirEqInterExpr<'_, '_, '_> { (&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r), (&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, @@ -444,7 +444,7 @@ impl HirEqInterExpr<'_, '_, '_> { ) => false, }; (is_eq && (!self.should_ignore(left) || !self.should_ignore(right))) - || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right)) + || self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right)) } fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool { @@ -724,7 +724,7 @@ fn swap_binop<'a>( /// `eq_fn`. pub fn both(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { l.as_ref() - .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y))) + .map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y))) } /// Checks if two slices are equal as per `eq_fn`. diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 50d334acf18e..19316a906835 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -342,10 +342,9 @@ pub fn is_ty_alias(qpath: &QPath<'_>) -> bool { /// Checks if the method call given in `expr` belongs to the given trait. /// This is a deprecated function, consider using [`is_trait_method`]. pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool { - cx.typeck_results() - .type_dependent_def_id(expr.hir_id) - .and_then(|defid| cx.tcx.trait_of_item(defid)) - .map_or(false, |trt_id| match_def_path(cx, trt_id, path)) + let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap(); + let trt_id = cx.tcx.trait_of_item(def_id); + trt_id.is_some_and(|trt_id| match_def_path(cx, trt_id, path)) } /// Checks if the given method call expression calls an inherent method. @@ -379,7 +378,7 @@ pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool { cx.typeck_results() .type_dependent_def_id(expr.hir_id) - .map_or(false, |did| is_diag_trait_item(cx, did, diag_item)) + .is_some_and(|did| is_diag_trait_item(cx, did, diag_item)) } /// Checks if the `def_id` belongs to a function that is part of a trait impl. @@ -406,7 +405,7 @@ pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) - if let ExprKind::Path(ref qpath) = expr.kind { cx.qpath_res(qpath, expr.hir_id) .opt_def_id() - .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item)) + .is_some_and(|def_id| is_diag_trait_item(cx, def_id, diag_item)) } else { false } @@ -466,13 +465,13 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { /// /// Please use `is_path_diagnostic_item` if the target is a diagnostic item. pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool { - path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, segments)) + path_def_id(cx, expr).is_some_and(|id| match_def_path(cx, id, segments)) } /// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if /// it matches the given lang item. pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool { - path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.lang_items().get(lang_item) == Some(id)) + path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.lang_items().get(lang_item) == Some(id)) } /// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if @@ -482,7 +481,7 @@ pub fn is_path_diagnostic_item<'tcx>( maybe_path: &impl MaybePath<'tcx>, diag_item: Symbol, ) -> bool { - path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id)) + path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.is_diagnostic_item(diag_item, id)) } /// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals. @@ -1315,7 +1314,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option, def_id: DefId) -> bool { cx.tcx .entry_fn(()) - .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id) + .is_some_and(|(entry_fn_def_id, _)| def_id == entry_fn_def_id) } /// Returns `true` if the expression is in the program's `#[panic_handler]`. @@ -1753,8 +1752,8 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { match pat.kind { PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. - PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)), - PatKind::Box(pat) | PatKind::Deref(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), + PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)), + PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), PatKind::Or(pats) => { // TODO: should be the honest check, that pats is exhaustive set @@ -1778,7 +1777,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { }, } }, - PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) => true, + PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) => true, } } @@ -2021,7 +2020,7 @@ pub fn match_libc_symbol(cx: &LateContext<'_>, did: DefId, name: &str) -> bool { let path = cx.get_def_path(did); // libc is meant to be used as a flat list of names, but they're all actually defined in different // modules based on the target platform. Ignore everything but crate name and the item name. - path.first().map_or(false, |s| s.as_str() == "libc") && path.last().map_or(false, |s| s.as_str() == name) + path.first().is_some_and(|s| s.as_str() == "libc") && path.last().is_some_and(|s| s.as_str() == name) } /// Returns the list of condition expressions and the list of blocks in a @@ -2104,7 +2103,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => None, }; - did.map_or(false, |did| cx.tcx.has_attr(did, sym::must_use)) + did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use)) } /// Checks if a function's body represents the identity function. Looks for bodies of the form: @@ -2211,7 +2210,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)), - _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)), + _ => path_def_id(cx, expr).is_some_and(|id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)), } } diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs index c5a34160e3da..2c49df9d807f 100644 --- a/clippy_utils/src/numeric_literal.rs +++ b/clippy_utils/src/numeric_literal.rs @@ -53,7 +53,7 @@ impl<'a> NumericLiteral<'a> { .trim_start() .chars() .next() - .map_or(false, |c| c.is_ascii_digit()) + .is_some_and(|c| c.is_ascii_digit()) { let (unsuffixed, suffix) = split_suffix(src, lit_kind); let float = matches!(lit_kind, LitKind::Float(..)); diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 3255c51d009c..25ebe879192f 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -905,7 +905,7 @@ impl<'tcx> DerefDelegate<'_, 'tcx> { _ => return false, }; - ty.map_or(false, |ty| matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref())) + ty.is_some_and(|ty| matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref())) } } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index ce1a20e0066d..770cd9c37865 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -45,7 +45,7 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { pub fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { cx.tcx .get_diagnostic_item(sym::Debug) - .map_or(false, |debug| implements_trait(cx, ty, debug, &[])) + .is_some_and(|debug| implements_trait(cx, ty, debug, &[])) } /// Checks whether a type can be partially moved. @@ -487,7 +487,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { .tcx .lang_items() .drop_trait() - .map_or(false, |id| implements_trait(cx, ty, id, &[])) + .is_some_and(|id| implements_trait(cx, ty, id, &[])) { // This type doesn't implement drop, so no side effects here. // Check if any component type has any. @@ -718,7 +718,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option( && p.self_ty() == ty => { let i = pred.kind().rebind(p.trait_ref.args.type_at(1)); - if inputs.map_or(false, |inputs| i != inputs) { + if inputs.is_some_and(|inputs| i != inputs) { // Multiple different fn trait impls. Is this even allowed? return None; } @@ -794,7 +794,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option { let i = pred.kind().rebind(p.trait_ref.args.type_at(1)); - if inputs.map_or(false, |inputs| inputs != i) { + if inputs.is_some_and(|inputs| inputs != i) { // Multiple different fn trait impls. Is this even allowed? return None; } @@ -1291,7 +1291,7 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx> /// Checks if the type is `core::mem::ManuallyDrop<_>` pub fn is_manually_drop(ty: Ty<'_>) -> bool { - ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop) + ty.ty_adt_def().is_some_and(AdtDef::is_manually_drop) } /// Returns the deref chain of a type, starting with the type itself. diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 8f5ec185bf15..a79be5ca7d4c 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -344,13 +344,13 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> .cx .qpath_res(p, hir_id) .opt_def_id() - .map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {}, + .is_some_and(|id| self.cx.tcx.is_const_fn(id)) => {}, ExprKind::MethodCall(..) if self .cx .typeck_results() .type_dependent_def_id(e.hir_id) - .map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {}, + .is_some_and(|id| self.cx.tcx.is_const_fn(id)) => {}, ExprKind::Binary(_, lhs, rhs) if self.cx.typeck_results().expr_ty(lhs).peel_refs().is_primitive_ty() && self.cx.typeck_results().expr_ty(rhs).peel_refs().is_primitive_ty() => {}, @@ -426,9 +426,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .cx .typeck_results() .type_dependent_def_id(e.hir_id) - .map_or(false, |id| { - self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe - }) => + .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe) => { ControlFlow::Break(()) }, @@ -444,7 +442,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .cx .qpath_res(p, e.hir_id) .opt_def_id() - .map_or(false, |id| self.cx.tcx.is_mutable_static(id)) => + .is_some_and(|id| self.cx.tcx.is_mutable_static(id)) => { ControlFlow::Break(()) }, diff --git a/rust-toolchain b/rust-toolchain index 37d9cce24650..e32e0cb36047 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-11-07" +channel = "nightly-2024-11-14" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/tests/ui-internal/unnecessary_def_path.fixed b/tests/ui-internal/unnecessary_def_path.fixed index 0a9948428341..d3fab60f9e3e 100644 --- a/tests/ui-internal/unnecessary_def_path.fixed +++ b/tests/ui-internal/unnecessary_def_path.fixed @@ -1,6 +1,7 @@ //@aux-build:paths.rs #![deny(clippy::internal)] #![feature(rustc_private)] +#![allow(clippy::unnecessary_map_or)] extern crate clippy_utils; extern crate paths; diff --git a/tests/ui-internal/unnecessary_def_path.rs b/tests/ui-internal/unnecessary_def_path.rs index ba68de6c6d01..1b36f6b09e9c 100644 --- a/tests/ui-internal/unnecessary_def_path.rs +++ b/tests/ui-internal/unnecessary_def_path.rs @@ -1,6 +1,7 @@ //@aux-build:paths.rs #![deny(clippy::internal)] #![feature(rustc_private)] +#![allow(clippy::unnecessary_map_or)] extern crate clippy_utils; extern crate paths; diff --git a/tests/ui-internal/unnecessary_def_path.stderr b/tests/ui-internal/unnecessary_def_path.stderr index 79da17316134..79521c5037a8 100644 --- a/tests/ui-internal/unnecessary_def_path.stderr +++ b/tests/ui-internal/unnecessary_def_path.stderr @@ -1,5 +1,5 @@ error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:36:13 + --> tests/ui-internal/unnecessary_def_path.rs:37:13 | LL | let _ = match_type(cx, ty, &OPTION); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)` @@ -12,61 +12,61 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:37:13 + --> tests/ui-internal/unnecessary_def_path.rs:38:13 | LL | let _ = match_type(cx, ty, RESULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:38:13 + --> tests/ui-internal/unnecessary_def_path.rs:39:13 | LL | let _ = match_type(cx, ty, &["core", "result", "Result"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:42:13 + --> tests/ui-internal/unnecessary_def_path.rs:43:13 | LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:44:13 + --> tests/ui-internal/unnecessary_def_path.rs:45:13 | LL | let _ = match_type(cx, ty, &paths::OPTION); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:45:13 + --> tests/ui-internal/unnecessary_def_path.rs:46:13 | LL | let _ = match_type(cx, ty, paths::RESULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:47:13 + --> tests/ui-internal/unnecessary_def_path.rs:48:13 | LL | let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:48:13 + --> tests/ui-internal/unnecessary_def_path.rs:49:13 | LL | let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:50:13 + --> tests/ui-internal/unnecessary_def_path.rs:51:13 | LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:51:13 + --> tests/ui-internal/unnecessary_def_path.rs:52:13 | LL | let _ = match_def_path(cx, did, &["core", "option", "Option"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:52:13 + --> tests/ui-internal/unnecessary_def_path.rs:53:13 | LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)` @@ -74,25 +74,25 @@ LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); = help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:54:13 + --> tests/ui-internal/unnecessary_def_path.rs:55:13 | LL | let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:56:13 + --> tests/ui-internal/unnecessary_def_path.rs:57:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:57:13 + --> tests/ui-internal/unnecessary_def_path.rs:58:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:58:13 + --> tests/ui-internal/unnecessary_def_path.rs:59:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)` diff --git a/tests/ui-toml/large_include_file/empty.txt b/tests/ui-toml/large_include_file/empty.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/ui-toml/large_include_file/large_include_file.rs b/tests/ui-toml/large_include_file/large_include_file.rs index dc9349f75a08..8a6dd36501cf 100644 --- a/tests/ui-toml/large_include_file/large_include_file.rs +++ b/tests/ui-toml/large_include_file/large_include_file.rs @@ -15,5 +15,9 @@ const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt"); const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt"); //~^ large_include_file -#[doc = include_str!("too_big.txt")] //~ large_include_file +#[doc = include_str!("too_big.txt")] +//~^ large_include_file +// Should not lint! +// Regression test for . +#[doc = include_str!("empty.txt")] fn main() {} diff --git a/tests/ui/case_sensitive_file_extension_comparisons.fixed b/tests/ui/case_sensitive_file_extension_comparisons.fixed index 8b4a165a97c6..c4d77f24f126 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.fixed +++ b/tests/ui/case_sensitive_file_extension_comparisons.fixed @@ -1,4 +1,5 @@ #![warn(clippy::case_sensitive_file_extension_comparisons)] +#![allow(clippy::unnecessary_map_or)] use std::string::String; diff --git a/tests/ui/case_sensitive_file_extension_comparisons.rs b/tests/ui/case_sensitive_file_extension_comparisons.rs index e4b8178110b6..690e93c2639a 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.rs +++ b/tests/ui/case_sensitive_file_extension_comparisons.rs @@ -1,4 +1,5 @@ #![warn(clippy::case_sensitive_file_extension_comparisons)] +#![allow(clippy::unnecessary_map_or)] use std::string::String; diff --git a/tests/ui/case_sensitive_file_extension_comparisons.stderr b/tests/ui/case_sensitive_file_extension_comparisons.stderr index d203f91b8323..e21815f251b7 100644 --- a/tests/ui/case_sensitive_file_extension_comparisons.stderr +++ b/tests/ui/case_sensitive_file_extension_comparisons.stderr @@ -1,5 +1,5 @@ error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:13:5 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:14:5 | LL | filename.ends_with(".rs") | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL + .map_or(false, |ext| ext.eq_ignore_ascii_case("rs")) | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:18:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13 | LL | let _ = String::new().ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13 | LL | let _ = "str".ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:23:17 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:24:17 | LL | let _ = "str".ends_with(".ext12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -57,7 +57,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("ext12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:30:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13 | LL | let _ = String::new().ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL ~ .map_or(false, |ext| ext.eq_ignore_ascii_case("EXT12")); | error: case-sensitive file extension comparison - --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13 + --> tests/ui/case_sensitive_file_extension_comparisons.rs:32:13 | LL | let _ = "str".ends_with(".EXT12"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/identity_op.fixed b/tests/ui/identity_op.fixed index b18d8560f6f8..2e8e2366de6f 100644 --- a/tests/ui/identity_op.fixed +++ b/tests/ui/identity_op.fixed @@ -116,7 +116,7 @@ fn main() { //~^ ERROR: this operation has no effect (match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 }; //~^ ERROR: this operation has no effect - (if b { 1 } else { 2 }); + ((if b { 1 } else { 2 })); //~^ ERROR: this operation has no effect ({ a }) + 3; @@ -212,3 +212,47 @@ fn issue_12050() { //~^ ERROR: this operation has no effect } } + +fn issue_13470() { + let x = 1i32; + let y = 1i32; + // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works + let _: u64 = (x + y) as u64; + //~^ ERROR: this operation has no effect + // both of the next two lines should look the same after rustfix + let _: u64 = 1u64 & (x + y) as u64; + //~^ ERROR: this operation has no effect + // Same as above, but with extra redundant parenthesis + let _: u64 = 1u64 & ((x + y)) as u64; + //~^ ERROR: this operation has no effect + // Should maintain parenthesis even if the surrounding expr has the same precedence + let _: u64 = 5u64 + ((x + y)) as u64; + //~^ ERROR: this operation has no effect + + // If we don't maintain the parens here, the behavior changes + let _ = -(x + y); + //~^ ERROR: this operation has no effect + // Similarly, we need to maintain parens here + let _ = -(x / y); + //~^ ERROR: this operation has no effect + // Maintain parenthesis if the parent expr is of higher precedence + let _ = 2i32 * (x + y); + //~^ ERROR: this operation has no effect + // Maintain parenthesis if the parent expr is the same precedence + // as not all operations are associative + let _ = 2i32 - (x - y); + //~^ ERROR: this operation has no effect + // But make sure that inner parens still exist + let z = 1i32; + let _ = 2 + (x + (y * z)); + //~^ ERROR: this operation has no effect + // Maintain parenthesis if the parent expr is of lower precedence + // This is for clarity, and clippy will not warn on these being unnecessary + let _ = 2i32 + (x * y); + //~^ ERROR: this operation has no effect + + let x = 1i16; + let y = 1i16; + let _: u64 = 1u64 + ((x as i32 + y as i32) as u64); + //~^ ERROR: this operation has no effect +} diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index f1f01b424478..3e20fa6f2b89 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -212,3 +212,47 @@ fn issue_12050() { //~^ ERROR: this operation has no effect } } + +fn issue_13470() { + let x = 1i32; + let y = 1i32; + // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works + let _: u64 = (x + y + 0i32) as u64; + //~^ ERROR: this operation has no effect + // both of the next two lines should look the same after rustfix + let _: u64 = 1u64 & (x + y + 0i32) as u64; + //~^ ERROR: this operation has no effect + // Same as above, but with extra redundant parenthesis + let _: u64 = 1u64 & ((x + y) + 0i32) as u64; + //~^ ERROR: this operation has no effect + // Should maintain parenthesis even if the surrounding expr has the same precedence + let _: u64 = 5u64 + ((x + y) + 0i32) as u64; + //~^ ERROR: this operation has no effect + + // If we don't maintain the parens here, the behavior changes + let _ = -(x + y + 0i32); + //~^ ERROR: this operation has no effect + // Similarly, we need to maintain parens here + let _ = -(x / y / 1i32); + //~^ ERROR: this operation has no effect + // Maintain parenthesis if the parent expr is of higher precedence + let _ = 2i32 * (x + y + 0i32); + //~^ ERROR: this operation has no effect + // Maintain parenthesis if the parent expr is the same precedence + // as not all operations are associative + let _ = 2i32 - (x - y - 0i32); + //~^ ERROR: this operation has no effect + // But make sure that inner parens still exist + let z = 1i32; + let _ = 2 + (x + (y * z) + 0); + //~^ ERROR: this operation has no effect + // Maintain parenthesis if the parent expr is of lower precedence + // This is for clarity, and clippy will not warn on these being unnecessary + let _ = 2i32 + (x * y * 1i32); + //~^ ERROR: this operation has no effect + + let x = 1i16; + let y = 1i16; + let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64); + //~^ ERROR: this operation has no effect +} diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 9fff86b86f9f..99a58ef2c1b5 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -149,7 +149,7 @@ error: this operation has no effect --> tests/ui/identity_op.rs:119:5 | LL | (if b { 1 } else { 2 }) + 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((if b { 1 } else { 2 }))` error: this operation has no effect --> tests/ui/identity_op.rs:122:5 @@ -313,5 +313,71 @@ error: this operation has no effect LL | let _: i32 = **&&*&x + 0; | ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x` -error: aborting due to 52 previous errors +error: this operation has no effect + --> tests/ui/identity_op.rs:220:18 + | +LL | let _: u64 = (x + y + 0i32) as u64; + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:223:25 + | +LL | let _: u64 = 1u64 & (x + y + 0i32) as u64; + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:226:25 + | +LL | let _: u64 = 1u64 & ((x + y) + 0i32) as u64; + | ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))` + +error: this operation has no effect + --> tests/ui/identity_op.rs:229:25 + | +LL | let _: u64 = 5u64 + ((x + y) + 0i32) as u64; + | ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))` + +error: this operation has no effect + --> tests/ui/identity_op.rs:233:14 + | +LL | let _ = -(x + y + 0i32); + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:236:14 + | +LL | let _ = -(x / y / 1i32); + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x / y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:239:20 + | +LL | let _ = 2i32 * (x + y + 0i32); + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:243:20 + | +LL | let _ = 2i32 - (x - y - 0i32); + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x - y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:247:17 + | +LL | let _ = 2 + (x + (y * z) + 0); + | ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(x + (y * z))` + +error: this operation has no effect + --> tests/ui/identity_op.rs:251:20 + | +LL | let _ = 2i32 + (x * y * 1i32); + | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x * y)` + +error: this operation has no effect + --> tests/ui/identity_op.rs:256:25 + | +LL | let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x as i32 + y as i32) as u64)` + +error: aborting due to 63 previous errors diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 679388372e61..b6e148e9f772 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -96,12 +96,42 @@ impl MoveStruct { } fn func() -> Option { + macro_rules! opt_none { + () => { + None + }; + } + fn f() -> Option { Some(String::new()) } f()?; + let _val = f()?; + + let s: &str = match &Some(String::new()) { + Some(v) => v, + None => return None, + }; + + f()?; + + opt_none!()?; + + match f() { + Some(x) => x, + None => return opt_none!(), + }; + + match f() { + Some(val) => { + println!("{val}"); + val + }, + None => return None, + }; + Some(0) } @@ -114,6 +144,10 @@ fn result_func(x: Result) -> Result { x?; + let _val = func_returning_result()?; + + func_returning_result()?; + // No warning let y = if let Ok(x) = x { x @@ -157,6 +191,28 @@ fn result_func(x: Result) -> Result { Ok(y) } +fn infer_check() { + let closure = |x: Result| { + // `?` would fail here, as it expands to `Err(val.into())` which is not constrained. + let _val = match x { + Ok(val) => val, + Err(val) => return Err(val), + }; + + Ok(()) + }; + + let closure = |x: Result| -> Result<(), _> { + // `?` would fail here, as it expands to `Err(val.into())` which is not constrained. + let _val = match x { + Ok(val) => val, + Err(val) => return Err(val), + }; + + Ok(()) + }; +} + // see issue #8019 pub enum NotOption { None, diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 601ab78bf5aa..48dc9eb0a626 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -124,6 +124,12 @@ impl MoveStruct { } fn func() -> Option { + macro_rules! opt_none { + () => { + None + }; + } + fn f() -> Option { Some(String::new()) } @@ -132,6 +138,39 @@ fn func() -> Option { return None; } + let _val = match f() { + Some(val) => val, + None => return None, + }; + + let s: &str = match &Some(String::new()) { + Some(v) => v, + None => return None, + }; + + match f() { + Some(val) => val, + None => return None, + }; + + match opt_none!() { + Some(x) => x, + None => return None, + }; + + match f() { + Some(x) => x, + None => return opt_none!(), + }; + + match f() { + Some(val) => { + println!("{val}"); + val + }, + None => return None, + }; + Some(0) } @@ -146,6 +185,16 @@ fn result_func(x: Result) -> Result { return x; } + let _val = match func_returning_result() { + Ok(val) => val, + Err(err) => return Err(err), + }; + + match func_returning_result() { + Ok(val) => val, + Err(err) => return Err(err), + }; + // No warning let y = if let Ok(x) = x { x @@ -189,6 +238,28 @@ fn result_func(x: Result) -> Result { Ok(y) } +fn infer_check() { + let closure = |x: Result| { + // `?` would fail here, as it expands to `Err(val.into())` which is not constrained. + let _val = match x { + Ok(val) => val, + Err(val) => return Err(val), + }; + + Ok(()) + }; + + let closure = |x: Result| -> Result<(), _> { + // `?` would fail here, as it expands to `Err(val.into())` which is not constrained. + let _val = match x { + Ok(val) => val, + Err(val) => return Err(val), + }; + + Ok(()) + }; +} + // see issue #8019 pub enum NotOption { None, diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index 5f26a7ea2c3e..0a48c4e80cb6 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -94,29 +94,76 @@ LL | | }; | |_________^ help: replace it with: `self.opt?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:131:5 + --> tests/ui/question_mark.rs:137:5 | LL | / if f().is_none() { LL | | return None; LL | | } | |_____^ help: replace it with: `f()?;` +error: this `match` expression can be replaced with `?` + --> tests/ui/question_mark.rs:141:16 + | +LL | let _val = match f() { + | ________________^ +LL | | Some(val) => val, +LL | | None => return None, +LL | | }; + | |_____^ help: try instead: `f()?` + +error: this `match` expression can be replaced with `?` + --> tests/ui/question_mark.rs:151:5 + | +LL | / match f() { +LL | | Some(val) => val, +LL | | None => return None, +LL | | }; + | |_____^ help: try instead: `f()?` + +error: this `match` expression can be replaced with `?` + --> tests/ui/question_mark.rs:156:5 + | +LL | / match opt_none!() { +LL | | Some(x) => x, +LL | | None => return None, +LL | | }; + | |_____^ help: try instead: `opt_none!()?` + error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:143:13 + --> tests/ui/question_mark.rs:182:13 | LL | let _ = if let Ok(x) = x { x } else { return x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:145:5 + --> tests/ui/question_mark.rs:184:5 | LL | / if x.is_err() { LL | | return x; LL | | } | |_____^ help: replace it with: `x?;` +error: this `match` expression can be replaced with `?` + --> tests/ui/question_mark.rs:188:16 + | +LL | let _val = match func_returning_result() { + | ________________^ +LL | | Ok(val) => val, +LL | | Err(err) => return Err(err), +LL | | }; + | |_____^ help: try instead: `func_returning_result()?` + +error: this `match` expression can be replaced with `?` + --> tests/ui/question_mark.rs:193:5 + | +LL | / match func_returning_result() { +LL | | Ok(val) => val, +LL | | Err(err) => return Err(err), +LL | | }; + | |_____^ help: try instead: `func_returning_result()?` + error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:213:5 + --> tests/ui/question_mark.rs:284:5 | LL | / if let Err(err) = func_returning_result() { LL | | return Err(err); @@ -124,7 +171,7 @@ LL | | } | |_____^ help: replace it with: `func_returning_result()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:220:5 + --> tests/ui/question_mark.rs:291:5 | LL | / if let Err(err) = func_returning_result() { LL | | return Err(err); @@ -132,7 +179,7 @@ LL | | } | |_____^ help: replace it with: `func_returning_result()?;` error: this block may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:297:13 + --> tests/ui/question_mark.rs:368:13 | LL | / if a.is_none() { LL | | return None; @@ -142,12 +189,12 @@ LL | | } | |_____________^ help: replace it with: `a?;` error: this `let...else` may be rewritten with the `?` operator - --> tests/ui/question_mark.rs:357:5 + --> tests/ui/question_mark.rs:428:5 | LL | / let Some(v) = bar.foo.owned.clone() else { LL | | return None; LL | | }; | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;` -error: aborting due to 17 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed new file mode 100644 index 000000000000..2d932a70e9d9 --- /dev/null +++ b/tests/ui/unnecessary_map_or.fixed @@ -0,0 +1,64 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::unnecessary_map_or)] +#![allow(clippy::no_effect)] +#![allow(clippy::eq_op)] +#![allow(clippy::unnecessary_lazy_evaluations)] +#[clippy::msrv = "1.70.0"] +#[macro_use] +extern crate proc_macros; + +fn main() { + // should trigger + let _ = (Some(5) == Some(5)); + let _ = (Some(5) != Some(5)); + let _ = (Some(5) == Some(5)); + let _ = Some(5).is_some_and(|n| { + let _ = n; + 6 >= 5 + }); + let _ = Some(vec![5]).is_some_and(|n| n == [5]); + let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); + let _ = Some(5).is_some_and(|n| n == n); + let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); + let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); + let _ = (Ok::(5) == Ok(5)); + let _ = (Some(5) == Some(5)).then(|| 1); + + // shouldnt trigger + let _ = Some(5).map_or(true, |n| n == 5); + let _ = Some(5).map_or(true, |n| 5 == n); + macro_rules! x { + () => { + Some(1) + }; + } + // methods lints dont fire on macros + let _ = x!().map_or(false, |n| n == 1); + let _ = x!().map_or(false, |n| n == vec![1][0]); + + msrv_1_69(); + + external! { + let _ = Some(5).map_or(false, |n| n == 5); + } + + with_span! { + let _ = Some(5).map_or(false, |n| n == 5); + } + + // check for presence of PartialEq, and alter suggestion to use `is_ok_and` if absent + struct S; + let r: Result = Ok(3); + let _ = r.is_ok_and(|x| x == 7); + + #[derive(PartialEq)] + struct S2; + let r: Result = Ok(4); + let _ = (r == Ok(8)); +} + +#[clippy::msrv = "1.69.0"] +fn msrv_1_69() { + // is_some_and added in 1.70.0 + let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); +} diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs new file mode 100644 index 000000000000..4a9d69be1e9d --- /dev/null +++ b/tests/ui/unnecessary_map_or.rs @@ -0,0 +1,67 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::unnecessary_map_or)] +#![allow(clippy::no_effect)] +#![allow(clippy::eq_op)] +#![allow(clippy::unnecessary_lazy_evaluations)] +#[clippy::msrv = "1.70.0"] +#[macro_use] +extern crate proc_macros; + +fn main() { + // should trigger + let _ = Some(5).map_or(false, |n| n == 5); + let _ = Some(5).map_or(true, |n| n != 5); + let _ = Some(5).map_or(false, |n| { + let _ = 1; + n == 5 + }); + let _ = Some(5).map_or(false, |n| { + let _ = n; + 6 >= 5 + }); + let _ = Some(vec![5]).map_or(false, |n| n == [5]); + let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); + let _ = Some(5).map_or(false, |n| n == n); + let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); + let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); + let _ = Ok::(5).map_or(false, |n| n == 5); + let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); + + // shouldnt trigger + let _ = Some(5).map_or(true, |n| n == 5); + let _ = Some(5).map_or(true, |n| 5 == n); + macro_rules! x { + () => { + Some(1) + }; + } + // methods lints dont fire on macros + let _ = x!().map_or(false, |n| n == 1); + let _ = x!().map_or(false, |n| n == vec![1][0]); + + msrv_1_69(); + + external! { + let _ = Some(5).map_or(false, |n| n == 5); + } + + with_span! { + let _ = Some(5).map_or(false, |n| n == 5); + } + + // check for presence of PartialEq, and alter suggestion to use `is_ok_and` if absent + struct S; + let r: Result = Ok(3); + let _ = r.map_or(false, |x| x == 7); + + #[derive(PartialEq)] + struct S2; + let r: Result = Ok(4); + let _ = r.map_or(false, |x| x == 8); +} + +#[clippy::msrv = "1.69.0"] +fn msrv_1_69() { + // is_some_and added in 1.70.0 + let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); +} diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr new file mode 100644 index 000000000000..299a4e5da7aa --- /dev/null +++ b/tests/ui/unnecessary_map_or.stderr @@ -0,0 +1,99 @@ +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:12:13 + | +LL | let _ = Some(5).map_or(false, |n| n == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))` + | + = note: `-D clippy::unnecessary-map-or` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:13:13 + | +LL | let _ = Some(5).map_or(true, |n| n != 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) != Some(5))` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:14:13 + | +LL | let _ = Some(5).map_or(false, |n| { + | _____________^ +LL | | let _ = 1; +LL | | n == 5 +LL | | }); + | |______^ help: use a standard comparison instead: `(Some(5) == Some(5))` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:18:13 + | +LL | let _ = Some(5).map_or(false, |n| { + | _____________^ +LL | | let _ = n; +LL | | 6 >= 5 +LL | | }); + | |______^ + | +help: use is_some_and instead + | +LL ~ let _ = Some(5).is_some_and(|n| { +LL + let _ = n; +LL + 6 >= 5 +LL ~ }); + | + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:22:13 + | +LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![5]).is_some_and(|n| n == [5])` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:23:13 + | +LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![1]).is_some_and(|n| vec![2] == n)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:24:13 + | +LL | let _ = Some(5).map_or(false, |n| n == n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == n)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:25:13 + | +LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 })` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:26:13 + | +LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `Ok::, i32>(vec![5]).is_ok_and(|n| n == [5])` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:27:13 + | +LL | let _ = Ok::(5).map_or(false, |n| n == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Ok::(5) == Ok(5))` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:28:13 + | +LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:55:13 + | +LL | let _ = r.map_or(false, |x| x == 7); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:60:13 + | +LL | let _ = r.map_or(false, |x| x == 8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))` + +error: aborting due to 13 previous errors + From 451c8cdb06b5d4033fe245ce19fdd9bfabd13f1f Mon Sep 17 00:00:00 2001 From: Peter Gervai Date: Thu, 14 Nov 2024 22:01:13 +0100 Subject: [PATCH 044/330] Remove one stray space. --- library/std/src/os/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 92613d9b004c..7c2c3f33d80b 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -985,7 +985,7 @@ impl DirBuilderExt for fs::DirBuilder { /// Changing the owner typically requires privileges, such as root or a specific capability. /// Changing the group typically requires either being the owner and a member of the group, or /// having privileges. -/// +/// /// Be aware that changing owner clears the `suid` and `sgid` permission bits in most cases /// according to POSIX, usually even if the user is root. The sgid is not cleared when /// the file is non-group-executable. See: From 34dd288376f0e2268c95ee9492c5a03218c18aa9 Mon Sep 17 00:00:00 2001 From: David Kurilla <130074511+davidkurilla@users.noreply.github.com> Date: Fri, 15 Nov 2024 18:02:16 +0000 Subject: [PATCH 045/330] style: cargo fmt --- .../rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index dfbecc7cffcb..c17d9c5ccd15 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -39,7 +39,6 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( }, expr.syntax().text_range(), |builder| { - let make = SyntaxFactory::new(); let mut editor = builder.make_editor(&expr.syntax()); From 4460db085001e76352f9979d0e852baa23f99bc7 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 15 Nov 2024 19:24:27 +0100 Subject: [PATCH 046/330] Move MSRV implementation to clippy_utils --- clippy_config/src/conf.rs | 2 +- clippy_config/src/lib.rs | 6 ------ clippy_utils/Cargo.toml | 1 + clippy_utils/src/lib.rs | 2 ++ {clippy_config => clippy_utils}/src/msrvs.rs | 0 clippy_utils/src/paths.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 7 files changed, 6 insertions(+), 9 deletions(-) rename {clippy_config => clippy_utils}/src/msrvs.rs (100%) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 600d5b6e2c8d..c3b1fc83af0a 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -1,10 +1,10 @@ use crate::ClippyConfiguration; -use crate::msrvs::Msrv; use crate::types::{ DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, }; +use clippy_utils::msrvs::Msrv; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 1c3f32c2514c..4acd54fa0374 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -13,18 +13,12 @@ rustc::untranslatable_diagnostic )] -extern crate rustc_ast; -extern crate rustc_attr; -#[allow(unused_extern_crates)] -extern crate rustc_driver; extern crate rustc_errors; extern crate rustc_session; extern crate rustc_span; -extern crate smallvec; mod conf; mod metadata; -pub mod msrvs; pub mod types; pub use conf::{Conf, get_configuration_metadata, lookup_conf_file, sanitize_explanation}; diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index d8d5733da1c9..745890ee1832 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -10,6 +10,7 @@ arrayvec = { version = "0.7", default-features = false } itertools = "0.12" # FIXME(f16_f128): remove when no longer needed for parsing rustc_apfloat = "0.2.0" +serde = { version = "1.0", features = ["derive"] } [package.metadata.rust-analyzer] # This crate uses #[feature(rustc_private)] diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 19316a906835..42de0e20e96d 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -50,6 +50,7 @@ extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; extern crate rustc_trait_selection; +extern crate smallvec; #[macro_use] pub mod sym_helper; @@ -65,6 +66,7 @@ pub mod higher; mod hir_utils; pub mod macros; pub mod mir; +pub mod msrvs; pub mod numeric_literal; pub mod paths; pub mod ptr; diff --git a/clippy_config/src/msrvs.rs b/clippy_utils/src/msrvs.rs similarity index 100% rename from clippy_config/src/msrvs.rs rename to clippy_utils/src/msrvs.rs diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 11a98b02f337..bb40a9430a7a 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -36,7 +36,7 @@ pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"]; pub const PANIC_ANY: [&str; 3] = ["std", "panic", "panic_any"]; // Paths in clippy itself -pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"]; +pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"]; // Paths in external crates #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 971f8eeb1b33..d4d00f1abe3e 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -3,7 +3,7 @@ // of terminologies might not be relevant in the context of Clippy. Note that its behavior might // differ from the time of `rustc` even if the name stays the same. -use clippy_config::msrvs::{self, Msrv}; +use crate::msrvs::{self, Msrv}; use hir::LangItem; use rustc_attr::StableSince; use rustc_const_eval::check_consts::ConstCx; From 81483d4a6c94d37b7f3af135598dfcb9e4a331b2 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 15 Nov 2024 19:28:20 +0100 Subject: [PATCH 047/330] Move create_disallowed_map to clippy_config --- clippy_config/Cargo.toml | 2 ++ clippy_config/src/lib.rs | 2 ++ clippy_config/src/types.rs | 15 +++++++++++++++ clippy_lints/src/await_holding_invalid.rs | 3 ++- clippy_lints/src/disallowed_macros.rs | 2 +- clippy_lints/src/disallowed_methods.rs | 2 +- clippy_utils/Cargo.toml | 2 -- clippy_utils/src/lib.rs | 15 +-------------- 8 files changed, 24 insertions(+), 19 deletions(-) diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index d21df202dcab..0cd0cabc3a6e 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -2,10 +2,12 @@ name = "clippy_config" version = "0.1.84" edition = "2021" +publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clippy_utils = { path = "../clippy_utils" } itertools = "0.12" serde = { version = "1.0", features = ["derive"] } toml = "0.7.3" diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 4acd54fa0374..5d6e8b875166 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -14,6 +14,8 @@ )] extern crate rustc_errors; +extern crate rustc_hir; +extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index fe5764241487..c949db9109de 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -1,3 +1,6 @@ +use clippy_utils::def_path_def_ids; +use rustc_hir::def_id::DefIdMap; +use rustc_middle::ty::TyCtxt; use serde::de::{self, Deserializer, Visitor}; use serde::{Deserialize, Serialize, ser}; use std::collections::HashMap; @@ -31,6 +34,18 @@ impl DisallowedPath { } } +/// Creates a map of disallowed items to the reason they were disallowed. +pub fn create_disallowed_map( + tcx: TyCtxt<'_>, + disallowed: &'static [DisallowedPath], +) -> DefIdMap<(&'static str, Option<&'static str>)> { + disallowed + .iter() + .map(|x| (x.path(), x.path().split("::").collect::>(), x.reason())) + .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason)))) + .collect() +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] pub enum MatchLintBehaviour { AllTypes, diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index 6948cf560a53..2eb0566bf9a6 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -1,6 +1,7 @@ use clippy_config::Conf; +use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{create_disallowed_map, match_def_path, paths}; +use clippy_utils::{match_def_path, paths}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index bdd49bf8aa7c..a0cb36f88dc0 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_utils::create_disallowed_map; +use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; use rustc_data_structures::fx::FxHashSet; diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs index 5a01d76a2a62..1e660b1957a4 100644 --- a/clippy_lints/src/disallowed_methods.rs +++ b/clippy_lints/src/disallowed_methods.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_utils::create_disallowed_map; +use clippy_config::types::create_disallowed_map; use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefIdMap; diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 745890ee1832..d136f3bc6f1d 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -2,10 +2,8 @@ name = "clippy_utils" version = "0.1.84" edition = "2021" -publish = false [dependencies] -clippy_config = { path = "../clippy_config" } arrayvec = { version = "0.7", default-features = false } itertools = "0.12" # FIXME(f16_f128): remove when no longer needed for parsing diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 42de0e20e96d..927ce5b6f16f 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -91,7 +91,6 @@ use std::hash::BuildHasherDefault; use std::iter::{once, repeat}; use std::sync::{Mutex, MutexGuard, OnceLock}; -use clippy_config::types::DisallowedPath; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_data_structures::fx::FxHashMap; @@ -99,7 +98,7 @@ use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::definitions::{DefPath, DefPathData}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; @@ -750,18 +749,6 @@ pub fn def_path_def_ids(tcx: TyCtxt<'_>, path: &[&str]) -> impl Iterator, - disallowed: &'static [DisallowedPath], -) -> DefIdMap<(&'static str, Option<&'static str>)> { - disallowed - .iter() - .map(|x| (x.path(), x.path().split("::").collect::>(), x.reason())) - .flat_map(|(name, path, reason)| def_path_def_ids(tcx, &path).map(move |id| (id, (name, reason)))) - .collect() -} - /// Convenience function to get the `DefId` of a trait by path. /// It could be a trait or trait alias. /// From 5c1811ab94bcf0961ff5cdd57f428d94d4d08227 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 15 Nov 2024 19:33:39 +0100 Subject: [PATCH 048/330] Rename all clippy_config::msrvs -> clippy_utils::msrvs --- book/src/development/adding_lints.md | 4 ++-- clippy_dev/src/new_lint.rs | 4 ++-- clippy_lints/src/almost_complete_range.rs | 2 +- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/assigning_clones.rs | 2 +- clippy_lints/src/attrs/deprecated_cfg_attr.rs | 2 +- clippy_lints/src/attrs/mod.rs | 2 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/casts/cast_abs_to_unsigned.rs | 2 +- clippy_lints/src/casts/cast_lossless.rs | 2 +- clippy_lints/src/casts/cast_slice_different_sizes.rs | 2 +- clippy_lints/src/casts/cast_slice_from_raw_parts.rs | 2 +- clippy_lints/src/casts/mod.rs | 2 +- clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- clippy_lints/src/casts/ptr_cast_constness.rs | 2 +- clippy_lints/src/checked_conversions.rs | 2 +- clippy_lints/src/derivable_impls.rs | 2 +- clippy_lints/src/format_args.rs | 2 +- clippy_lints/src/from_over_into.rs | 2 +- clippy_lints/src/if_then_some_else_none.rs | 2 +- clippy_lints/src/implicit_saturating_sub.rs | 2 +- clippy_lints/src/incompatible_msrv.rs | 2 +- clippy_lints/src/index_refutable_slice.rs | 2 +- clippy_lints/src/instant_subtraction.rs | 2 +- clippy_lints/src/legacy_numeric_constants.rs | 6 +++--- clippy_lints/src/loops/explicit_iter_loop.rs | 2 +- clippy_lints/src/loops/mod.rs | 2 +- clippy_lints/src/manual_bits.rs | 2 +- clippy_lints/src/manual_clamp.rs | 2 +- clippy_lints/src/manual_div_ceil.rs | 2 +- clippy_lints/src/manual_float_methods.rs | 4 ++-- clippy_lints/src/manual_hash_one.rs | 2 +- clippy_lints/src/manual_is_ascii_check.rs | 2 +- clippy_lints/src/manual_let_else.rs | 3 +-- clippy_lints/src/manual_main_separator_str.rs | 2 +- clippy_lints/src/manual_non_exhaustive.rs | 2 +- clippy_lints/src/manual_rem_euclid.rs | 2 +- clippy_lints/src/manual_retain.rs | 2 +- clippy_lints/src/manual_strip.rs | 2 +- clippy_lints/src/matches/collapsible_match.rs | 2 +- clippy_lints/src/matches/mod.rs | 2 +- clippy_lints/src/matches/redundant_guards.rs | 2 +- clippy_lints/src/mem_replace.rs | 2 +- clippy_lints/src/methods/cloned_instead_of_copied.rs | 2 +- clippy_lints/src/methods/err_expect.rs | 2 +- clippy_lints/src/methods/filter_map_next.rs | 2 +- clippy_lints/src/methods/is_digit_ascii_radix.rs | 2 +- clippy_lints/src/methods/iter_kv_map.rs | 2 +- clippy_lints/src/methods/manual_c_str_literals.rs | 2 +- clippy_lints/src/methods/manual_inspect.rs | 2 +- clippy_lints/src/methods/manual_is_variant_and.rs | 4 ++-- clippy_lints/src/methods/manual_try_fold.rs | 2 +- clippy_lints/src/methods/map_clone.rs | 2 +- clippy_lints/src/methods/map_unwrap_or.rs | 2 +- .../src/methods/map_with_unused_argument_over_ranges.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/option_as_ref_deref.rs | 2 +- clippy_lints/src/methods/option_map_unwrap_or.rs | 2 +- clippy_lints/src/methods/path_ends_with_ext.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 2 +- clippy_lints/src/methods/string_lit_chars_any.rs | 2 +- clippy_lints/src/methods/unnecessary_map_or.rs | 2 +- clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +- clippy_lints/src/missing_const_for_fn.rs | 2 +- clippy_lints/src/missing_const_for_thread_local.rs | 2 +- clippy_lints/src/needless_borrows_for_generic_args.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/redundant_field_names.rs | 2 +- clippy_lints/src/redundant_static_lifetimes.rs | 2 +- clippy_lints/src/std_instead_of_core.rs | 2 +- clippy_lints/src/string_patterns.rs | 2 +- clippy_lints/src/trait_bounds.rs | 2 +- clippy_lints/src/transmute/mod.rs | 2 +- clippy_lints/src/transmute/transmute_float_to_int.rs | 2 +- clippy_lints/src/transmute/transmute_int_to_float.rs | 2 +- clippy_lints/src/transmute/transmute_num_to_bytes.rs | 2 +- clippy_lints/src/transmute/transmute_ptr_to_ptr.rs | 2 +- clippy_lints/src/transmute/transmute_ptr_to_ref.rs | 2 +- clippy_lints/src/tuple_array_conversions.rs | 2 +- clippy_lints/src/unnested_or_patterns.rs | 2 +- clippy_lints/src/unused_trait_names.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/vec.rs | 2 +- tests/ui-internal/invalid_msrv_attr_impl.fixed | 2 +- tests/ui-internal/invalid_msrv_attr_impl.rs | 2 +- 86 files changed, 92 insertions(+), 93 deletions(-) diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 963e02e5c161..c07568697d02 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -438,7 +438,7 @@ need to ensure that the MSRV configured for the project is >= the MSRV of the required Rust feature. If multiple features are required, just use the one with a lower MSRV. -First, add an MSRV alias for the required feature in [`clippy_config::msrvs`]. +First, add an MSRV alias for the required feature in [`clippy_utils::msrvs`]. This can be accessed later as `msrvs::STR_STRIP_PREFIX`, for example. ```rust @@ -517,7 +517,7 @@ define_Conf! { } ``` -[`clippy_config::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html +[`clippy_utils::msrvs`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_config/msrvs/index.html Afterwards update the documentation for the book as described in [Adding configuration to a lint](#adding-configuration-to-a-lint). diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 8b32dc6b8885..ee626d60b864 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -273,7 +273,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { result.push_str(&if enable_msrv { formatdoc!( r" - use clippy_config::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, Msrv}}; use clippy_config::Conf; {pass_import} use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; @@ -399,7 +399,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let _: fmt::Result = writedoc!( lint_file_contents, r#" - use clippy_config::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, Msrv}}; use rustc_lint::{{{context_import}, LintContext}}; use super::{name_upper}; diff --git a/clippy_lints/src/almost_complete_range.rs b/clippy_lints/src/almost_complete_range.rs index 370f0c482fd5..2af5178920d9 100644 --- a/clippy_lints/src/almost_complete_range.rs +++ b/clippy_lints/src/almost_complete_range.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{trim_span, walk_span_to_context}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 4f8f091a0956..2f7f5e07ac77 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 0b82c0cd04c1..3a402a53e1c2 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::{is_diag_trait_item, is_in_test, last_path_segment, local_is_initialized, path_to_local}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/clippy_lints/src/attrs/deprecated_cfg_attr.rs index abf924f7542e..3a462018e3e0 100644 --- a/clippy_lints/src/attrs/deprecated_cfg_attr.rs +++ b/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -1,6 +1,6 @@ use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg}; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::EarlyContext; diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index c29c9f08cf70..a9766597d50d 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -13,7 +13,7 @@ mod useless_attribute; mod utils; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, Item, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 896bd5fd03d5..6eef0d42a550 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use rustc_ast::ast::LitKind; diff --git a/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/clippy_lints/src/casts/cast_abs_to_unsigned.rs index b7b63250864e..ae433773193a 100644 --- a/clippy_lints/src/casts/cast_abs_to_unsigned.rs +++ b/clippy_lints/src/casts/cast_abs_to_unsigned.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index 84a44b14dde5..4ad39d9160de 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_const_context; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_isize_or_usize; diff --git a/clippy_lints/src/casts/cast_slice_different_sizes.rs b/clippy_lints/src/casts/cast_slice_different_sizes.rs index 285f0357112b..030c2d322db6 100644 --- a/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source; use rustc_ast::Mutability; use rustc_hir::{Expr, ExprKind, Node}; diff --git a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs index 1d89f6c75e18..c3bc5c0c9f2a 100644 --- a/clippy_lints/src/casts/cast_slice_from_raw_parts.rs +++ b/clippy_lints/src/casts/cast_slice_from_raw_parts.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 3acd4eca420e..8b884399f923 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -24,8 +24,8 @@ mod utils; mod zero_ptr; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::is_hir_ty_cfg_dependant; +use clippy_utils::msrvs::{self, Msrv}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index 86c5f6b9f0ba..451d65100176 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 7518dd2435ae..945c05ee9436 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::std_or_core; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index f76e399517cf..364f5c7dc7a0 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 767dda552bcd..2b2644213222 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::indent_of; use clippy_utils::{is_default_equivalent, peel_blocks}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 4c043f8dc14b..da5825b7ab21 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -1,6 +1,5 @@ use arrayvec::ArrayVec; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_diag_trait_item; use clippy_utils::macros::{ @@ -8,6 +7,7 @@ use clippy_utils::macros::{ format_placeholder_format_span, is_assert_macro, is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, }; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use itertools::Itertools; diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 14da0b515a51..4c5a366f8841 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -1,9 +1,9 @@ use std::ops::ControlFlow; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::span_is_local; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::path_def_id; use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index d63c18c0edaa..3fc0a6965224 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::{ diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 3b84b569c3ed..37481dc7feb7 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::{ SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index 0b3a6ee1beae..f3467adacc55 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_in_test; +use clippy_utils::msrvs::Msrv; use rustc_attr::{StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, HirId}; diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index 96550c4d1cb9..c2030a5ab090 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::is_copy; use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; diff --git a/clippy_lints/src/instant_subtraction.rs b/clippy_lints/src/instant_subtraction.rs index 66931a7f98c3..f4e41dc826b0 100644 --- a/clippy_lints/src/instant_subtraction.rs +++ b/clippy_lints/src/instant_subtraction.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::Sugg; use clippy_utils::ty; diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index e17d6213679a..fb46bdcab6e1 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{Msrv, NUMERIC_ASSOCIATED_CONSTANTS}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{get_parent_expr, is_from_proc_macro}; use hir::def_id::DefId; use rustc_errors::Applicability; @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind - && self.msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) + && self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) && !in_external_macro(cx.sess(), item.span) && let Some(def_id) = path.res[0].opt_def_id() { @@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { return; }; - if self.msrv.meets(NUMERIC_ASSOCIATED_CONSTANTS) + if self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) && !in_external_macro(cx.sess(), expr.span) && !is_from_proc_macro(cx, expr) { diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index ee561ea85ed1..c9d72315803b 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -1,6 +1,6 @@ use super::EXPLICIT_ITER_LOOP; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{ implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection, diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 17215621d2aa..f3ca4a4a5715 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -23,8 +23,8 @@ mod while_let_loop; mod while_let_on_iterator; use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::higher; +use clippy_utils::msrvs::Msrv; use rustc_ast::Label; use rustc_hir::{Expr, ExprKind, LoopSource, Pat}; use rustc_lint::{LateContext, LateLintPass}; diff --git a/clippy_lints/src/manual_bits.rs b/clippy_lints/src/manual_bits.rs index fd71167f814d..c31656f8a05e 100644 --- a/clippy_lints/src/manual_bits.rs +++ b/clippy_lints/src/manual_bits.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 016ec7320a6a..484a7ba256bd 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -1,8 +1,8 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::higher::If; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::is_const_evaluatable; diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs index 4c171e6d890f..07af2ddb0def 100644 --- a/clippy_lints/src/manual_div_ceil.rs +++ b/clippy_lints/src/manual_div_ceil.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::SpanlessEq; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use rustc_ast::{BinOpKind, LitKind}; diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index a269ea113974..b12f575e81a3 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -1,7 +1,7 @@ -use clippy_config::msrvs::Msrv; -use clippy_config::{Conf, msrvs}; +use clippy_config::Conf; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, path_to_local}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/manual_hash_one.rs b/clippy_lints/src/manual_hash_one.rs index 7a9c99637428..7e092d11f1b4 100644 --- a/clippy_lints/src/manual_hash_one.rs +++ b/clippy_lints/src/manual_hash_one.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::visitors::{is_local_used, local_used_once}; use clippy_utils::{is_trait_method, path_to_local_id}; diff --git a/clippy_lints/src/manual_is_ascii_check.rs b/clippy_lints/src/manual_is_ascii_check.rs index dec8c5d85dec..3f01f3cf30ae 100644 --- a/clippy_lints/src/manual_is_ascii_check.rs +++ b/clippy_lints/src/manual_is_ascii_check.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators}; use rustc_ast::LitKind::{Byte, Char}; diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 17185df5d76f..a70955a7c78d 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -1,11 +1,10 @@ use crate::question_mark::{QUESTION_MARK, QuestionMark}; -use clippy_config::msrvs; use clippy_config::types::MatchLintBehaviour; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; -use clippy_utils::{is_lint_allowed, is_never_expr, pat_and_expr_can_be_question_mark, peel_blocks}; +use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind}; diff --git a/clippy_lints/src/manual_main_separator_str.rs b/clippy_lints/src/manual_main_separator_str.rs index 85e99a92cf59..b7563a2508d0 100644 --- a/clippy_lints/src/manual_main_separator_str.rs +++ b/clippy_lints/src/manual_main_separator_str.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{is_trait_method, peel_hir_expr_refs}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 25868ccae400..00800231fe46 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::is_doc_hidden; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_indent; use itertools::Itertools; use rustc_ast::attr; diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index 86293169ea28..5e58054a9866 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::{is_in_const_context, path_to_local}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index a60163be770d..708980ac503d 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::SpanlessEq; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 3f401eff6bdb..79de41db3438 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::usage::mutated_variables; use clippy_utils::{eq_expr_value, higher}; diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 50e6dfc6298d..95a73e5f05d1 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLetOrMatch; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet; use clippy_utils::visitors::is_local_used; use clippy_utils::{ diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index 28adcc2f2274..64969271764c 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -25,7 +25,7 @@ mod try_err; mod wild_in_or_pats; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::walk_span_to_context; use clippy_utils::{higher, is_direct_expn_of, is_in_const_context, is_span_match, span_contains_cfg}; use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind}; diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs index 9e54475033c8..a7ef28ff8da2 100644 --- a/clippy_lints/src/matches/redundant_guards.rs +++ b/clippy_lints/src/matches/redundant_guards.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet; use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used}; use clippy_utils::{is_in_const_context, path_to_local}; diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index 146748734cff..5597cd85abc9 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_non_aggregate_primitive_type; diff --git a/clippy_lints/src/methods/cloned_instead_of_copied.rs b/clippy_lints/src/methods/cloned_instead_of_copied.rs index fa04f74eec10..2a0a9d3710dc 100644 --- a/clippy_lints/src/methods/cloned_instead_of_copied.rs +++ b/clippy_lints/src/methods/cloned_instead_of_copied.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{get_iterator_item_ty, is_copy}; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/clippy_lints/src/methods/err_expect.rs b/clippy_lints/src/methods/err_expect.rs index 3b1adb16b80e..44b55570eead 100644 --- a/clippy_lints/src/methods/err_expect.rs +++ b/clippy_lints/src/methods/err_expect.rs @@ -1,6 +1,6 @@ use super::ERR_EXPECT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item}; use rustc_errors::Applicability; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index f94fe221833d..3f89e5931487 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::is_trait_method; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir as hir; diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs index 40b48ccca5d5..d8bb9e377a0c 100644 --- a/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -1,7 +1,7 @@ use super::IS_DIGIT_ASCII_RADIX; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index 390dd24b5058..299f6d101123 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -1,6 +1,6 @@ use super::ITER_KV_MAP; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::pat_is_wild; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; diff --git a/clippy_lints/src/methods/manual_c_str_literals.rs b/clippy_lints/src/methods/manual_c_str_literals.rs index 22f4748de70d..7d5ebdedd0c3 100644 --- a/clippy_lints/src/methods/manual_c_str_literals.rs +++ b/clippy_lints/src/methods/manual_c_str_literals.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use rustc_ast::{LitKind, StrStyle}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/methods/manual_inspect.rs b/clippy_lints/src/methods/manual_inspect.rs index 223b0630bfd4..f3a576b822ec 100644 --- a/clippy_lints/src/methods/manual_inspect.rs +++ b/clippy_lints/src/methods/manual_inspect.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{IntoSpan, SpanRangeExt}; use clippy_utils::ty::get_field_by_name; use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures}; diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index c377abd62377..90e502f244fa 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{Msrv, OPTION_RESULT_IS_VARIANT_AND}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; @@ -36,7 +36,7 @@ pub(super) fn check<'tcx>( } // 4. msrv doesn't meet `OPTION_RESULT_IS_VARIANT_AND` - if !msrv.meets(OPTION_RESULT_IS_VARIANT_AND) { + if !msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) { return; } diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index 31449d417701..4a48d4b547cc 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{is_from_proc_macro, is_trait_method}; diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index d5594b21db5d..1252f7ccd357 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, is_type_diagnostic_item, should_call_clone_as_function}; use clippy_utils::{is_diag_trait_item, peel_blocks}; diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 3226fa9cd3fa..428da0cf107e 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::usage::mutated_variables; diff --git a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs index fc656fd78ba2..80703618a113 100644 --- a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs +++ b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs @@ -1,6 +1,6 @@ use crate::methods::MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use clippy_utils::{eager_or_lazy, higher, usage}; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 795e041ffd9d..6023cade5798 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -137,10 +137,10 @@ mod wrong_self_convention; mod zst_offset; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::macros::FormatArgsStorage; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty}; pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES; diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 998bdee01576..8d97d1c72a6b 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{path_to_local_id, peel_blocks}; diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 528e2204cf8f..7c4dc4ffb202 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, is_type_diagnostic_item}; use rustc_data_structures::fx::FxHashSet; diff --git a/clippy_lints/src/methods/path_ends_with_ext.rs b/clippy_lints/src/methods/path_ends_with_ext.rs index cfb823dbf5de..febd7fd5cf2f 100644 --- a/clippy_lints/src/methods/path_ends_with_ext.rs +++ b/clippy_lints/src/methods/path_ends_with_ext.rs @@ -1,6 +1,6 @@ use super::PATH_ENDS_WITH_EXT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::{LitKind, StrStyle}; diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 1cee28e19861..c91be33b1cd0 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -1,6 +1,6 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::usage::local_used_after_expr; use clippy_utils::visitors::{Descend, for_each_expr}; diff --git a/clippy_lints/src/methods/string_lit_chars_any.rs b/clippy_lints/src/methods/string_lit_chars_any.rs index cc0d432b799d..cb719b34b1f0 100644 --- a/clippy_lints/src/methods/string_lit_chars_any.rs +++ b/clippy_lints/src/methods/string_lit_chars_any.rs @@ -1,5 +1,5 @@ -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::{is_from_proc_macro, is_trait_method, path_to_local}; use itertools::Itertools; diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index adc27cd437f4..1dacec1032dd 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::eager_or_lazy::switch_to_eager_eval; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use clippy_utils::sugg::{Sugg, make_binop}; use clippy_utils::ty::{get_type_diagnostic_name, implements_trait}; diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 82549413fa91..6dc0f9409bd9 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -1,7 +1,7 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::find_all_ret_expressions; diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index eea0459e026e..121c4326d648 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/missing_const_for_thread_local.rs b/clippy_lints/src/missing_const_for_thread_local.rs index c2f524a63531..9a44a3c980c0 100644 --- a/clippy_lints/src/missing_const_for_thread_local.rs +++ b/clippy_lints/src/missing_const_for_thread_local.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::macros::macro_backtrace; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::qualify_min_const_fn::is_min_const_fn; use clippy_utils::source::snippet; use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks}; diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index c1424b9f1dc8..dd2e48f4831b 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{PossibleBorrowerMap, enclosing_mir, expr_local, local_assignments, used_exactly_once}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::{DefinedTy, ExprUseNode, expr_use_ctxt, peel_n_hir_expr_refs}; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index a00fd01a62e0..c38783642df3 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -1,9 +1,9 @@ use crate::manual_let_else::MANUAL_LET_ELSE; use crate::question_mark_used::QUESTION_MARK_USED; use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_config::types::MatchLintBehaviour; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::Msrv; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{ diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 21cd33672624..1b0c0a4956f7 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::sugg::Sugg; use clippy_utils::{get_parent_expr, higher, is_in_const_context, is_integer_const, path_to_local}; diff --git a/clippy_lints/src/redundant_field_names.rs b/clippy_lints/src/redundant_field_names.rs index d0dbff081f90..347540e7344f 100644 --- a/clippy_lints/src/redundant_field_names.rs +++ b/clippy_lints/src/redundant_field_names.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index b27bb2e78afe..06c854338066 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet; use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind}; use rustc_errors::Applicability; diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 8dd998587932..2941b9c39607 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::Msrv; use rustc_attr::{StabilityLevel, StableSince}; use rustc_errors::Applicability; use rustc_hir::def::Res; diff --git a/clippy_lints/src/string_patterns.rs b/clippy_lints/src/string_patterns.rs index ba2ddac2ec33..0d85b1b858a4 100644 --- a/clippy_lints/src/string_patterns.rs +++ b/clippy_lints/src/string_patterns.rs @@ -1,10 +1,10 @@ use std::ops::ControlFlow; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::eager_or_lazy::switch_to_eager_eval; use clippy_utils::macros::matching_root_macro_call; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::path_to_local_id; use clippy_utils::source::{snippet, str_literal_to_char_literal}; use clippy_utils::visitors::{Descend, for_each_expr}; diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 07bf4319ff0e..e641822b5d9b 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro}; use core::hash::{Hash, Hasher}; diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 25fec9f688ca..1cb0f837227d 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -20,8 +20,8 @@ mod utils; mod wrong_transmute; use clippy_config::Conf; -use clippy_config::msrvs::Msrv; use clippy_utils::is_in_const_context; +use clippy_utils::msrvs::Msrv; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs index 3507eb9a1248..f0b8abf9af66 100644 --- a/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_FLOAT_TO_INT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_ast as ast; use rustc_errors::Applicability; diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs index c5c7ed6d398b..e5b9aea6423a 100644 --- a/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_INT_TO_FLOAT; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs index a94cd27c7fd1..6d828bad9b32 100644 --- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs +++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_NUM_TO_BYTES; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 0772b284968a..89f76d286128 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_PTR_TO_PTR; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg; use rustc_errors::Applicability; use rustc_hir::Expr; diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index eaf927c0005f..ef18633d945f 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -1,6 +1,6 @@ use super::TRANSMUTE_PTR_TO_REF; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg; use rustc_errors::Applicability; diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 07d0f59b91c1..99a55f9fc357 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -1,6 +1,6 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::visitors::for_each_local_use_after_expr; use clippy_utils::{is_from_proc_macro, path_to_local}; use itertools::Itertools; diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index c7c837de505e..9d26bf930a1a 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -1,9 +1,9 @@ #![allow(clippy::wildcard_imports, clippy::enum_glob_use)] use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::over; use rustc_ast::PatKind::*; use rustc_ast::mut_visit::*; diff --git a/clippy_lints/src/unused_trait_names.rs b/clippy_lints/src/unused_trait_names.rs index 9fd6ebccd02f..17ee5fc20ca2 100644 --- a/clippy_lints/src/unused_trait_names.rs +++ b/clippy_lints/src/unused_trait_names.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_opt; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index f5cf4a586fd2..65aea6a87c83 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_from_proc_macro; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::ty::same_type_and_consts; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 9bcff9d7bcec..ef1c46154d29 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -2,9 +2,9 @@ use std::collections::BTreeMap; use std::ops::ControlFlow; use clippy_config::Conf; -use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_local_use_after_expr; diff --git a/tests/ui-internal/invalid_msrv_attr_impl.fixed b/tests/ui-internal/invalid_msrv_attr_impl.fixed index 9b5bf736f137..928596d08091 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -8,8 +8,8 @@ extern crate rustc_lint; extern crate rustc_middle; #[macro_use] extern crate rustc_session; -use clippy_config::msrvs::Msrv; use clippy_utils::extract_msrv_attr; +use clippy_utils::msrvs::Msrv; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; diff --git a/tests/ui-internal/invalid_msrv_attr_impl.rs b/tests/ui-internal/invalid_msrv_attr_impl.rs index c5bde47e4ce8..50b28648ccc9 100644 --- a/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -8,8 +8,8 @@ extern crate rustc_lint; extern crate rustc_middle; #[macro_use] extern crate rustc_session; -use clippy_config::msrvs::Msrv; use clippy_utils::extract_msrv_attr; +use clippy_utils::msrvs::Msrv; use rustc_hir::Expr; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; From c627c1a294a95b6775c01bc68c63ad4193ecf91c Mon Sep 17 00:00:00 2001 From: David Kurilla <130074511+davidkurilla@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:08:01 +0000 Subject: [PATCH 049/330] style: remove needless borrow --- .../rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs index c17d9c5ccd15..42f615e71daf 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs @@ -40,7 +40,7 @@ pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( expr.syntax().text_range(), |builder| { let make = SyntaxFactory::new(); - let mut editor = builder.make_editor(&expr.syntax()); + let mut editor = builder.make_editor(expr.syntax()); let block_expr = make.block_expr(None, Some(expr.clone())); block_expr.indent(expr.indent_level()); From 81dceed8baf324960ea05e9079b749305b16a7cc Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 28 Mar 2023 17:04:30 -0400 Subject: [PATCH 050/330] Support user format-like macros Add support for `#[clippy::format_args]` attribute that can be attached to any macro to indicate that it functions the same as the built-in format macros like `format!`, `println!` and `write!` --- book/src/SUMMARY.md | 1 + book/src/attribs.md | 53 ++++++++++++++++++++++ clippy_utils/src/attrs.rs | 3 ++ clippy_utils/src/macros.rs | 7 ++- tests/ui/format_args_unfixable.rs | 29 ++++++++++++ tests/ui/format_args_unfixable.stderr | 65 ++++++++++++++++++++++++++- tests/ui/uninlined_format_args.fixed | 21 ++++++++- tests/ui/uninlined_format_args.rs | 21 ++++++++- tests/ui/uninlined_format_args.stderr | 50 ++++++++++++++++++++- tests/ui/unused_format_specs.1.fixed | 35 +++++++++++++++ tests/ui/unused_format_specs.2.fixed | 35 +++++++++++++++ tests/ui/unused_format_specs.rs | 35 +++++++++++++++ tests/ui/unused_format_specs.stderr | 60 ++++++++++++++++++++++++- 13 files changed, 406 insertions(+), 9 deletions(-) create mode 100644 book/src/attribs.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index be13fcbe260f..19328fdd3cd4 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -7,6 +7,7 @@ - [Configuration](configuration.md) - [Lint Configuration](lint_configuration.md) - [Clippy's Lints](lints.md) +- [Attributes for Crate Authors](attribs.md) - [Continuous Integration](continuous_integration/README.md) - [GitHub Actions](continuous_integration/github_actions.md) - [GitLab CI](continuous_integration/gitlab.md) diff --git a/book/src/attribs.md b/book/src/attribs.md new file mode 100644 index 000000000000..cf99497bc0fc --- /dev/null +++ b/book/src/attribs.md @@ -0,0 +1,53 @@ +# Attributes for Crate Authors + +In some cases it is possible to extend Clippy coverage to 3rd party libraries. +To do this, Clippy provides attributes that can be applied to items in the 3rd party crate. + +## `#[clippy::format_args]` + +_Available since Clippy v1.84_ + +This attribute can be added to a macro that supports `format!`, `println!`, or similar syntax. +It tells Clippy that the macro is a formatting macro, and that the arguments to the macro +should be linted as if they were arguments to `format!`. Any lint that would apply to a +`format!` call will also apply to the macro call. The macro may have additional arguments +before the format string, and these will be ignored. + +### Example + +```rust +/// A macro that prints a message if a condition is true. +#[macro_export] +#[clippy::format_args] +macro_rules! print_if { + ($condition:expr, $($args:tt)+) => {{ + if $condition { + println!($($args)+) + } + }}; +} +``` + +## `#[clippy::has_significant_drop]` + +_Available since Clippy v1.60_ + +The `clippy::has_significant_drop` attribute can be added to types whose Drop impls have an important side effect, +such as unlocking a mutex, making it important for users to be able to accurately understand their lifetimes. +When a temporary is returned in a function call in a match scrutinee, its lifetime lasts until the end of the match +block, which may be surprising. + +### Example + +```rust +#[clippy::has_significant_drop] +struct CounterWrapper<'a> { + counter: &'a Counter, +} + +impl<'a> Drop for CounterWrapper<'a> { + fn drop(&mut self) { + self.counter.i.fetch_sub(1, Ordering::Relaxed); + } +} +``` diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index edc9c6ccdff8..b2a6657baad3 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -27,7 +27,10 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, DeprecationStatus)] = &[ ("cyclomatic_complexity", DeprecationStatus::Replaced("cognitive_complexity")), ("dump", DeprecationStatus::None), ("msrv", DeprecationStatus::None), + // The following attributes are for the 3rd party crate authors. + // See book/src/attribs.md ("has_significant_drop", DeprecationStatus::None), + ("format_args", DeprecationStatus::None), ]; pub struct LimitStack { diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 9c4d19ac1f1d..01261ea6e8df 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -1,5 +1,6 @@ #![allow(clippy::similar_names)] // `expr` and `expn` +use crate::get_unique_attr; use crate::visitors::{Descend, for_each_expr_without_closures}; use arrayvec::ArrayVec; @@ -7,7 +8,7 @@ use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{Lrc, OnceLock}; use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext}; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; use rustc_span::{BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol, sym}; @@ -36,7 +37,9 @@ pub fn is_format_macro(cx: &LateContext<'_>, macro_def_id: DefId) -> bool { if let Some(name) = cx.tcx.get_diagnostic_name(macro_def_id) { FORMAT_MACRO_DIAG_ITEMS.contains(&name) } else { - false + // Allow users to tag any macro as being format!-like + // TODO: consider deleting FORMAT_MACRO_DIAG_ITEMS and using just this method + get_unique_attr(cx.sess(), cx.tcx.get_attrs_unchecked(macro_def_id), "format_args").is_some() } } diff --git a/tests/ui/format_args_unfixable.rs b/tests/ui/format_args_unfixable.rs index f04715f4f018..7590de3751a8 100644 --- a/tests/ui/format_args_unfixable.rs +++ b/tests/ui/format_args_unfixable.rs @@ -119,3 +119,32 @@ fn test2() { format!("something failed at {}", Location::caller()) ); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn user_format() { + let error = Error::new(ErrorKind::Other, "bad thing"); + let x = 'x'; + + usr_println!(true, "error: {}", format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args + usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller())); + //~^ ERROR: `format!` in `usr_println!` args +} diff --git a/tests/ui/format_args_unfixable.stderr b/tests/ui/format_args_unfixable.stderr index 20cd0bb8c554..1b4b683fd6c6 100644 --- a/tests/ui/format_args_unfixable.stderr +++ b/tests/ui/format_args_unfixable.stderr @@ -174,5 +174,68 @@ LL | panic!("error: {}", format!("something failed at {}", Location::caller( = help: combine the `format!(..)` arguments with the outer `panic!(..)` call = help: or consider changing `format!` to `format_args!` -error: aborting due to 18 previous errors +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:136:5 + | +LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:138:5 + | +LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:140:5 + | +LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:142:5 + | +LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:144:5 + | +LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:146:5 + | +LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: `format!` in `usr_println!` args + --> tests/ui/format_args_unfixable.rs:148:5 + | +LL | usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call + = help: or consider changing `format!` to `format_args!` + +error: aborting due to 25 previous errors diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 3f5b0e52ece0..111a2e1987c8 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -257,8 +257,6 @@ fn tester2() { my_concat!("{}", local_i32); my_good_macro!("{}", local_i32); my_good_macro!("{}", local_i32,); - - // FIXME: Broken false positives, currently unhandled my_bad_macro!("{}", local_i32); my_bad_macro2!("{}", local_i32); used_twice! { @@ -267,3 +265,22 @@ fn tester2() { local_i32, }; } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn user_format() { + let local_i32 = 1; + let local_f64 = 2.0; + + usr_println!(true, "val='{local_i32}'"); + usr_println!(true, "{local_i32}"); + usr_println!(true, "{local_i32:#010x}"); + usr_println!(true, "{local_f64:.1}"); +} diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index b311aa4912cd..81fe24765674 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -262,8 +262,6 @@ fn tester2() { my_concat!("{}", local_i32); my_good_macro!("{}", local_i32); my_good_macro!("{}", local_i32,); - - // FIXME: Broken false positives, currently unhandled my_bad_macro!("{}", local_i32); my_bad_macro2!("{}", local_i32); used_twice! { @@ -272,3 +270,22 @@ fn tester2() { local_i32, }; } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn user_format() { + let local_i32 = 1; + let local_f64 = 2.0; + + usr_println!(true, "val='{}'", local_i32); + usr_println!(true, "{}", local_i32); + usr_println!(true, "{:#010x}", local_i32); + usr_println!(true, "{:.1}", local_f64); +} diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index 5a7ff3bc4f5a..77961fea2c53 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -845,5 +845,53 @@ LL - println!("expand='{}'", local_i32); LL + println!("expand='{local_i32}'"); | -error: aborting due to 71 previous errors +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:287:5 + | +LL | usr_println!(true, "val='{}'", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "val='{}'", local_i32); +LL + usr_println!(true, "val='{local_i32}'"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:288:5 + | +LL | usr_println!(true, "{}", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "{}", local_i32); +LL + usr_println!(true, "{local_i32}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:289:5 + | +LL | usr_println!(true, "{:#010x}", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "{:#010x}", local_i32); +LL + usr_println!(true, "{local_i32:#010x}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:290:5 + | +LL | usr_println!(true, "{:.1}", local_f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - usr_println!(true, "{:.1}", local_f64); +LL + usr_println!(true, "{local_f64:.1}"); + | + +error: aborting due to 75 previous errors diff --git a/tests/ui/unused_format_specs.1.fixed b/tests/ui/unused_format_specs.1.fixed index b7d1cce28701..157c2b08d3cf 100644 --- a/tests/ui/unused_format_specs.1.fixed +++ b/tests/ui/unused_format_specs.1.fixed @@ -33,3 +33,38 @@ fn should_not_lint() { let args = format_args!(""); println!("{args}"); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn should_lint_user() { + // prints `.`, not ` .` + usr_println!(true, "{:5}.", format!("")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + //prints `abcde`, not `abc` + usr_println!(true, "{:.3}", format!("abcde")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + usr_println!(true, "{}.", format_args_from_macro!()); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + let args = format_args!(""); + usr_println!(true, "{args}"); + //~^ ERROR: format specifiers have no effect on `format_args!()` +} + +fn should_not_lint_user() { + usr_println!(true, "{}", format_args!("")); + // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use + // debug formatting so allow it + usr_println!(true, "{:?}", format_args!("")); + + let args = format_args!(""); + usr_println!(true, "{args}"); +} diff --git a/tests/ui/unused_format_specs.2.fixed b/tests/ui/unused_format_specs.2.fixed index 94bb6b7036bd..92c7b951f3ca 100644 --- a/tests/ui/unused_format_specs.2.fixed +++ b/tests/ui/unused_format_specs.2.fixed @@ -33,3 +33,38 @@ fn should_not_lint() { let args = format_args!(""); println!("{args}"); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn should_lint_user() { + // prints `.`, not ` .` + usr_println!(true, "{}.", format_args!("")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + //prints `abcde`, not `abc` + usr_println!(true, "{}", format_args!("abcde")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + usr_println!(true, "{}.", format_args_from_macro!()); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + let args = format_args!(""); + usr_println!(true, "{args}"); + //~^ ERROR: format specifiers have no effect on `format_args!()` +} + +fn should_not_lint_user() { + usr_println!(true, "{}", format_args!("")); + // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use + // debug formatting so allow it + usr_println!(true, "{:?}", format_args!("")); + + let args = format_args!(""); + usr_println!(true, "{args}"); +} diff --git a/tests/ui/unused_format_specs.rs b/tests/ui/unused_format_specs.rs index 2c85e3711493..a5df4d8a8668 100644 --- a/tests/ui/unused_format_specs.rs +++ b/tests/ui/unused_format_specs.rs @@ -33,3 +33,38 @@ fn should_not_lint() { let args = format_args!(""); println!("{args}"); } + +#[clippy::format_args] +macro_rules! usr_println { + ($target:expr, $($args:tt)*) => {{ + if $target { + println!($($args)*) + } + }}; +} + +fn should_lint_user() { + // prints `.`, not ` .` + usr_println!(true, "{:5}.", format_args!("")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + //prints `abcde`, not `abc` + usr_println!(true, "{:.3}", format_args!("abcde")); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + usr_println!(true, "{:5}.", format_args_from_macro!()); + //~^ ERROR: format specifiers have no effect on `format_args!()` + + let args = format_args!(""); + usr_println!(true, "{args:5}"); + //~^ ERROR: format specifiers have no effect on `format_args!()` +} + +fn should_not_lint_user() { + usr_println!(true, "{}", format_args!("")); + // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use + // debug formatting so allow it + usr_println!(true, "{:?}", format_args!("")); + + let args = format_args!(""); + usr_println!(true, "{args}"); +} diff --git a/tests/ui/unused_format_specs.stderr b/tests/ui/unused_format_specs.stderr index 2b5c81c63d60..df61d59130ef 100644 --- a/tests/ui/unused_format_specs.stderr +++ b/tests/ui/unused_format_specs.stderr @@ -58,5 +58,63 @@ LL - println!("{args:5}"); LL + println!("{args}"); | -error: aborting due to 4 previous errors +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:48:25 + | +LL | usr_println!(true, "{:5}.", format_args!("")); + | ^^^^ + | +help: for the width to apply consider using `format!()` + | +LL | usr_println!(true, "{:5}.", format!("")); + | ~~~~~~ +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{:5}.", format_args!("")); +LL + usr_println!(true, "{}.", format_args!("")); + | + +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:51:25 + | +LL | usr_println!(true, "{:.3}", format_args!("abcde")); + | ^^^^^ + | +help: for the precision to apply consider using `format!()` + | +LL | usr_println!(true, "{:.3}", format!("abcde")); + | ~~~~~~ +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{:.3}", format_args!("abcde")); +LL + usr_println!(true, "{}", format_args!("abcde")); + | + +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:54:25 + | +LL | usr_println!(true, "{:5}.", format_args_from_macro!()); + | ^^^^ + | + = help: for the width to apply consider using `format!()` +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{:5}.", format_args_from_macro!()); +LL + usr_println!(true, "{}.", format_args_from_macro!()); + | + +error: format specifiers have no effect on `format_args!()` + --> tests/ui/unused_format_specs.rs:58:25 + | +LL | usr_println!(true, "{args:5}"); + | ^^^^^^^^ + | + = help: for the width to apply consider using `format!()` +help: if the current behavior is intentional, remove the format specifiers + | +LL - usr_println!(true, "{args:5}"); +LL + usr_println!(true, "{args}"); + | + +error: aborting due to 8 previous errors From d1688b53f13f1d486ccb7acd79d51e54c396ea2d Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 5 Nov 2024 00:25:47 +0100 Subject: [PATCH 051/330] `unnecessary_map_or`: add non-comparaison tests --- tests/ui/unnecessary_map_or.fixed | 6 ++++++ tests/ui/unnecessary_map_or.rs | 6 ++++++ tests/ui/unnecessary_map_or.stderr | 14 +++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index 2d932a70e9d9..d645cd3f3c45 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -51,6 +51,12 @@ fn main() { let r: Result = Ok(3); let _ = r.is_ok_and(|x| x == 7); + // lint constructs that are not comparaisons as well + let func = |_x| true; + let r: Result = Ok(3); + let _ = r.is_ok_and(func); + let _ = Some(5).is_some_and(func); + #[derive(PartialEq)] struct S2; let r: Result = Ok(4); diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index 4a9d69be1e9d..4939d52fd43a 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -54,6 +54,12 @@ fn main() { let r: Result = Ok(3); let _ = r.map_or(false, |x| x == 7); + // lint constructs that are not comparaisons as well + let func = |_x| true; + let r: Result = Ok(3); + let _ = r.map_or(false, func); + let _ = Some(5).map_or(false, func); + #[derive(PartialEq)] struct S2; let r: Result = Ok(4); diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index 299a4e5da7aa..56295594ddcb 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -92,8 +92,20 @@ LL | let _ = r.map_or(false, |x| x == 7); error: this `map_or` is redundant --> tests/ui/unnecessary_map_or.rs:60:13 | +LL | let _ = r.map_or(false, func); + | ^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(func)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:61:13 + | +LL | let _ = Some(5).map_or(false, func); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(func)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:66:13 + | LL | let _ = r.map_or(false, |x| x == 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))` -error: aborting due to 13 previous errors +error: aborting due to 15 previous errors From ca963b653ef4b4374f3def53b8e64de2b600683b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 5 Nov 2024 00:02:57 +0100 Subject: [PATCH 052/330] =?UTF-8?q?Simplify=20instances=20of=20`Option::ma?= =?UTF-8?q?p=5For(true,=20=E2=80=A6)`=20in=20Clippy=20sources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/assigning_clones.rs | 4 ++-- clippy_lints/src/borrow_deref_ref.rs | 2 +- clippy_lints/src/cargo/common_metadata.rs | 2 +- clippy_lints/src/casts/cast_possible_truncation.rs | 2 +- clippy_lints/src/copies.rs | 4 ++-- clippy_lints/src/dereference.rs | 2 +- clippy_lints/src/eta_reduction.rs | 2 +- clippy_lints/src/excessive_bools.rs | 2 +- clippy_lints/src/from_over_into.rs | 2 +- clippy_lints/src/if_let_mutex.rs | 2 +- clippy_lints/src/loops/explicit_iter_loop.rs | 2 +- clippy_lints/src/matches/collapsible_match.rs | 5 ++--- clippy_lints/src/methods/clone_on_copy.rs | 2 +- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/unnecessary_filter_map.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/needless_borrows_for_generic_args.rs | 2 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/non_copy_const.rs | 2 +- clippy_lints/src/only_used_in_recursion.rs | 2 +- clippy_lints/src/operators/assign_op_pattern.rs | 2 +- clippy_lints/src/ptr.rs | 4 +--- clippy_lints/src/redundant_async_block.rs | 2 +- clippy_lints/src/single_call_fn.rs | 2 +- clippy_lints/src/undocumented_unsafe_blocks.rs | 2 +- clippy_lints/src/unit_types/let_unit_value.rs | 2 +- clippy_lints/src/upper_case_acronyms.rs | 2 +- clippy_lints/src/use_self.rs | 2 +- clippy_utils/src/consts.rs | 4 ++-- clippy_utils/src/lib.rs | 4 ++-- clippy_utils/src/macros.rs | 2 +- clippy_utils/src/msrvs.rs | 2 +- clippy_utils/src/usage.rs | 2 +- 34 files changed, 39 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index 2f7f5e07ac77..ebd35fd2b27f 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -91,7 +91,7 @@ impl ApproxConstant { let s = s.as_str(); if s.parse::().is_ok() { for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS { - if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| self.msrv.meets(msrv)) { + if is_approx_const(constant, s, min_digits) && msrv.is_none_or(|msrv| self.msrv.meets(msrv)) { span_lint_and_help( cx, APPROX_CONSTANT, diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 3a402a53e1c2..c4debff3cb5a 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -100,13 +100,13 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. - && path_to_local(lhs).map_or(true, |lhs| local_is_initialized(cx, lhs)) + && path_to_local(lhs).is_none_or(|lhs| local_is_initialized(cx, lhs)) && let Some(resolved_impl) = cx.tcx.impl_of_method(resolved_fn.def_id()) // Derived forms don't implement `clone_from`/`clone_into`. // See https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305 && !cx.tcx.is_builtin_derived(resolved_impl) // Don't suggest calling a function we're implementing. - && resolved_impl.as_local().map_or(true, |block_id| { + && resolved_impl.as_local().is_none_or(|block_id| { cx.tcx.hir().parent_owner_iter(e.hir_id).all(|(id, _)| id.def_id != block_id) }) && let resolved_assoc_items = cx.tcx.associated_items(resolved_impl) diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs index f2551a05b1a2..8892a9e6b6b0 100644 --- a/clippy_lints/src/borrow_deref_ref.rs +++ b/clippy_lints/src/borrow_deref_ref.rs @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { && !addrof_target.span.from_expansion() && let ref_ty = cx.typeck_results().expr_ty(deref_target) && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind() - && get_parent_expr(cx, e).map_or(true, |parent| { + && get_parent_expr(cx, e).is_none_or(|parent| { match parent.kind { // `*&*foo` should lint `deref_addrof` instead. ExprKind::Unary(UnOp::Deref, _) => is_lint_allowed(cx, DEREF_ADDROF, parent.hir_id), diff --git a/clippy_lints/src/cargo/common_metadata.rs b/clippy_lints/src/cargo/common_metadata.rs index 6714c053913c..80514cb52e6e 100644 --- a/clippy_lints/src/cargo/common_metadata.rs +++ b/clippy_lints/src/cargo/common_metadata.rs @@ -43,7 +43,7 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel } fn is_empty_str>(value: Option<&T>) -> bool { - value.map_or(true, |s| s.as_ref().is_empty()) + value.is_none_or(|s| s.as_ref().is_empty()) } fn is_empty_vec(value: &[String]) -> bool { diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 40a1a9d1ce8f..48e9f1d690ee 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -134,7 +134,7 @@ pub(super) fn check( }; let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx); - let cast_from_ptr_size = def.repr().int.map_or(true, |ty| matches!(ty, IntegerType::Pointer(_),)); + let cast_from_ptr_size = def.repr().int.is_none_or(|ty| matches!(ty, IntegerType::Pointer(_),)); let suffix = match (cast_from_ptr_size, is_isize_or_usize(cast_to)) { (_, false) if from_nbits > to_nbits => "", (false, true) if from_nbits > 64 => "", diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 3ecd36d3711f..89808d38b9f3 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -212,7 +212,7 @@ fn lint_if_same_then_else(cx: &LateContext<'_>, conds: &[&Expr<'_>], blocks: &[& .array_windows::<2>() .enumerate() .fold(true, |all_eq, (i, &[lhs, rhs])| { - if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).map_or(true, |e| !contains_let(e)) { + if eq.eq_block(lhs, rhs) && !contains_let(conds[i]) && conds.get(i + 1).is_none_or(|e| !contains_let(e)) { span_lint_and_note( cx, IF_SAME_THEN_ELSE, @@ -470,7 +470,7 @@ fn scan_block_for_eq<'tcx>( b.stmts // the bounds check will catch the underflow .get(b.stmts.len().wrapping_sub(offset + 1)) - .map_or(true, |s| hash != hash_stmt(cx, s)) + .is_none_or(|s| hash != hash_stmt(cx, s)) }) }) .map_or(block.stmts.len() - start_end_eq, |(i, _)| i); diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index b167d7f22087..a270bdf81291 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -452,7 +452,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { )); } else if stability.is_deref_stable() // Auto-deref doesn't combine with other adjustments - && next_adjust.map_or(true, |a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) + && next_adjust.is_none_or(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) && iter.all(|a| matches!(a.kind, Adjust::Deref(_) | Adjust::Borrow(_))) { self.state = Some((State::Borrow { mutability }, StateData { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 6c87a05ace39..8c22e43349f6 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -276,7 +276,7 @@ fn check_inputs( && typeck .expr_adjustments(arg) .last() - .map_or(true, |a| a.target == typeck.expr_ty(arg)) + .is_none_or(|a| a.target == typeck.expr_ty(arg)) }) } diff --git a/clippy_lints/src/excessive_bools.rs b/clippy_lints/src/excessive_bools.rs index c88fb50b5afc..0011da03dda7 100644 --- a/clippy_lints/src/excessive_bools.rs +++ b/clippy_lints/src/excessive_bools.rs @@ -165,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { && fn_header.abi == Abi::Rust && fn_decl.inputs.len() as u64 > self.max_fn_params_bools && get_parent_as_impl(cx.tcx, cx.tcx.local_def_id_to_hir_id(def_id)) - .map_or(true, |impl_item| impl_item.of_trait.is_none()) + .is_none_or(|impl_item| impl_item.of_trait.is_none()) { check_fn_decl(cx, fn_decl, span, self.max_fn_params_bools); } diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index 4c5a366f8841..e43c311eb854 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { |diag| { // If the target type is likely foreign mention the orphan rules as it's a common source of // confusion - if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) { + if path_def_id(cx, target_ty.peel_refs()).is_none_or(|id| !id.is_local()) { diag.help( "`impl From for Foreign` is allowed by the orphan rules, for more information see\n\ https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence" diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index ba80c099a015..212d75e16171 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -86,7 +86,7 @@ fn mutex_lock_call<'tcx>( && path.ident.as_str() == "lock" && let ty = cx.typeck_results().expr_ty(self_arg).peel_refs() && is_type_diagnostic_item(cx, ty, sym::Mutex) - && op_mutex.map_or(true, |op| eq_expr_value(cx, self_arg, op)) + && op_mutex.is_none_or(|op| eq_expr_value(cx, self_arg, op)) { ControlFlow::Break(self_arg) } else { diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index c9d72315803b..2577459d073d 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -29,7 +29,7 @@ pub(super) fn check( if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) { return; } - } else if count.try_to_target_usize(cx.tcx).map_or(true, |x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) { + } else if count.try_to_target_usize(cx.tcx).is_none_or(|x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) { return; } } diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 95a73e5f05d1..99a7b8c74be8 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -72,14 +72,13 @@ fn check_arm<'tcx>( (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b), } // the binding must not be used in the if guard - && outer_guard.map_or( - true, + && outer_guard.is_none_or( |e| !is_local_used(cx, e, binding_id) ) // ...or anywhere in the inner expression && match inner { IfLetOrMatch::IfLet(_, _, body, els, _) => { - !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id)) + !is_local_used(cx, body, binding_id) && els.is_none_or(|e| !is_local_used(cx, e, binding_id)) }, IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)), } diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index c9604c7b2e2b..1ee27d90d054 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -30,7 +30,7 @@ pub(super) fn check( .type_dependent_def_id(expr.hir_id) .and_then(|id| cx.tcx.trait_of_item(id)) .zip(cx.tcx.lang_items().clone_trait()) - .map_or(true, |(x, y)| x != y) + .is_none_or(|(x, y)| x != y) { return; } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 6023cade5798..15b192c9c109 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4531,7 +4531,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { && method_config.output_type.matches(&sig.decl.output) // in case there is no first arg, since we already have checked the number of arguments // it's should be always true - && first_arg_ty_opt.map_or(true, |first_arg_ty| method_config + && first_arg_ty_opt.is_none_or(|first_arg_ty| method_config .self_kind.matches(cx, self_ty, first_arg_ty) ) && fn_header_equals(method_config.fn_header, sig.header) diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index bab439015c5f..3de51bc661eb 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind { let body = cx.tcx.hir().body(body); let arg_id = body.params[0].pat.hir_id; - let mutates_arg = mutated_variables(body.value, cx).map_or(true, |used_mutably| used_mutably.contains(&arg_id)); + let mutates_arg = mutated_variables(body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id)); let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value); let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value); diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 408dbef9cb16..8aba650472b4 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -351,7 +351,7 @@ fn used_underscore_binding<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { /// `unused_variables`'s idea /// of what it means for an expression to be "used". fn is_used(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - get_parent_expr(cx, expr).map_or(true, |parent| match parent.kind { + get_parent_expr(cx, expr).is_none_or(|parent| match parent.kind { ExprKind::Assign(_, rhs, _) | ExprKind::AssignOp(_, _, rhs) => SpanlessEq::new(cx).eq_expr(rhs, expr), _ => is_used(cx, parent), }) diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index dd2e48f4831b..776c86398ad2 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -362,7 +362,7 @@ fn referent_used_exactly_once<'tcx>( let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id); if possible_borrowers .last() - .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id) + .is_none_or(|&(local_def_id, _)| local_def_id != body_owner_local_def_id) { possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 74536028b5d4..8ecff9c3f9b3 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -238,7 +238,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { ExprKind::Struct(_, fields, ref base) => { !has_drop(cx, cx.typeck_results().expr_ty(expr)) && fields.iter().all(|field| has_no_effect(cx, field.expr)) - && base.as_ref().map_or(true, |base| has_no_effect(cx, base)) + && base.as_ref().is_none_or(|base| has_no_effect(cx, base)) }, ExprKind::Call(callee, args) => { if let ExprKind::Path(ref qpath) = callee.kind { diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 5e20b4064260..3be70b363346 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -335,7 +335,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // i.e. having an enum doesn't necessary mean a type has a frozen variant. // And, implementing it isn't a trivial task; it'll probably end up // re-implementing the trait predicate evaluation specific to `Freeze`. - && body_id_opt.map_or(true, |body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized)) + && body_id_opt.is_none_or(|body_id| Self::is_value_unfrozen_poly(cx, body_id, normalized)) { lint(cx, Source::Assoc { item: trait_item.span }); } diff --git a/clippy_lints/src/only_used_in_recursion.rs b/clippy_lints/src/only_used_in_recursion.rs index 13b3d2407007..6de203e068b7 100644 --- a/clippy_lints/src/only_used_in_recursion.rs +++ b/clippy_lints/src/only_used_in_recursion.rs @@ -200,7 +200,7 @@ impl Params { if self .get_by_fn(param.fn_id, usage.idx) // If the parameter can't be found, then it's used for more than just recursion. - .map_or(true, |p| self.try_disable_lint_for_param(p, eval_stack)) + .is_none_or(|p| self.try_disable_lint_for_param(p, eval_stack)) { param.apply_lint.set(false); eval_stack.pop(); diff --git a/clippy_lints/src/operators/assign_op_pattern.rs b/clippy_lints/src/operators/assign_op_pattern.rs index 0dcaec1c9a72..1315c3dfc127 100644 --- a/clippy_lints/src/operators/assign_op_pattern.rs +++ b/clippy_lints/src/operators/assign_op_pattern.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( if let Some((_, lang_item)) = binop_traits(op.node) && let Some(trait_id) = cx.tcx.lang_items().get(lang_item) && let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id - && trait_ref_of_method(cx, parent_fn).map_or(true, |t| t.path.res.def_id() != trait_id) + && trait_ref_of_method(cx, parent_fn).is_none_or(|t| t.path.res.def_id() != trait_id) && implements_trait(cx, ty, trait_id, &[rty.into()]) { // Primitive types execute assign-ops right-to-left. Every other type is left-to-right. diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index ecc095f38599..dec4c18a309e 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -541,9 +541,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio .collect(); if let Some(args) = args && !args.is_empty() - && body.map_or(true, |body| { - sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value) - }) + && body.is_none_or(|body| sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value)) { span_lint_and_then( cx, diff --git a/clippy_lints/src/redundant_async_block.rs b/clippy_lints/src/redundant_async_block.rs index 313e4083256b..3ade6bcee84d 100644 --- a/clippy_lints/src/redundant_async_block.rs +++ b/clippy_lints/src/redundant_async_block.rs @@ -88,7 +88,7 @@ fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Op cx.typeck_results() .closure_min_captures .get(def_id) - .map_or(true, |m| { + .is_none_or(|m| { m.values().all(|places| { places .iter() diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index abe13a97c0d1..0176077c70e0 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -93,7 +93,7 @@ impl SingleCallFn { .tcx .hir() .maybe_body_owned_by(fn_def_id) - .map_or(true, |body| is_in_test_function(cx.tcx, body.value.hir_id)) + .is_none_or(|body| is_in_test_function(cx.tcx, body.value.hir_id)) || match cx.tcx.hir_node(fn_hir_id) { Node::Item(item) => is_from_proc_macro(cx, item), Node::ImplItem(item) => is_from_proc_macro(cx, item), diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 0bba611116bb..b79e59f857bb 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -337,7 +337,7 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { .src .as_deref() .and_then(|src| src.get(file_pos.pos.to_usize()..)) - .map_or(true, |src| !src.starts_with("unsafe")) + .is_none_or(|src| !src.starts_with("unsafe")) } // Checks if any parent {expression, statement, block, local, const, static} diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index 6eef582b4b28..0702f6d1e74b 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -145,7 +145,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) - } while let Some(id) = locals_to_check.pop() { if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) { - if !l.ty.map_or(true, |ty| matches!(ty.kind, TyKind::Infer)) { + if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer)) { return false; } if let Some(e) = l.init { diff --git a/clippy_lints/src/upper_case_acronyms.rs b/clippy_lints/src/upper_case_acronyms.rs index 8de062a8fc15..c3843279ba2e 100644 --- a/clippy_lints/src/upper_case_acronyms.rs +++ b/clippy_lints/src/upper_case_acronyms.rs @@ -93,7 +93,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive while let Some(c) = s.next() { r.push( if replace(&mut prev_upper, c.is_ascii_uppercase()) - && s.clone().next().map_or(true, |c| c.is_ascii_uppercase()) + && s.clone().next().is_none_or(|c| c.is_ascii_uppercase()) { c.to_ascii_lowercase() } else { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 65aea6a87c83..05c5be030028 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { && let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args && parameters .as_ref() - .map_or(true, |params| params.parenthesized == GenericArgsParentheses::No) + .is_none_or(|params| params.parenthesized == GenericArgsParentheses::No) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) // expensive, should be last check diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 24a02c7ef871..d97987711c2d 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -226,7 +226,7 @@ impl Constant<'_> { .zip(r) .zip(tys) .map(|((li, ri), cmp_type)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .find(|r| r.is_none_or(|o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), _ => None, }, @@ -236,7 +236,7 @@ impl Constant<'_> { }; iter::zip(l, r) .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) - .find(|r| r.map_or(true, |o| o != Ordering::Equal)) + .find(|r| r.is_none_or(|o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))) }, (Self::Repeat(lv, ls), Self::Repeat(rv, rs)) => { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 927ce5b6f16f..6ad796fdd61f 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1570,7 +1570,7 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool { let ty = cx.typeck_results().expr_ty(expr); if let Some(Range { start, end, limits }) = Range::hir(expr) { - let start_is_none_or_min = start.map_or(true, |start| { + let start_is_none_or_min = start.is_none_or(|start| { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) @@ -1582,7 +1582,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti false } }); - let end_is_none_or_max = end.map_or(true, |end| match limits { + let end_is_none_or_max = end.is_none_or(|end| match limits { RangeLimits::Closed => { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 9c4d19ac1f1d..967b54919fc5 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -93,7 +93,7 @@ pub fn expn_is_local(expn: ExpnId) -> bool { std::iter::once((expn, data)) .chain(backtrace) .find_map(|(_, data)| data.macro_def_id) - .map_or(true, DefId::is_local) + .is_none_or(DefId::is_local) } /// Returns an iterator of macro expansions that created the given span. diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 764ca8fb50ab..1eb7d54e133d 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -121,7 +121,7 @@ impl Msrv { } pub fn meets(&self, required: RustcVersion) -> bool { - self.current().map_or(true, |msrv| msrv >= required) + self.current().is_none_or(|msrv| msrv >= required) } fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option { diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index c8c25456f696..37f729668925 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -27,7 +27,7 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> } pub fn is_potentially_mutated<'tcx>(variable: HirId, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool { - mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&variable)) + mutated_variables(expr, cx).is_none_or(|mutated| mutated.contains(&variable)) } pub fn is_potentially_local_place(local_id: HirId, place: &Place<'_>) -> bool { From de03a05bc8f5f367b94f7ce49896eed82b431026 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Mon, 4 Nov 2024 19:04:30 +0100 Subject: [PATCH 053/330] =?UTF-8?q?unnecessary=5Fmap=5For:=20lint=20`.map?= =?UTF-8?q?=5For(true,=20=E2=80=A6)`=20as=20well?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clippy_lints/src/methods/mod.rs | 18 +++++++++---- .../src/methods/unnecessary_map_or.rs | 18 ++++++++++--- tests/ui/unnecessary_map_or.fixed | 16 +++++++++--- tests/ui/unnecessary_map_or.rs | 14 ++++++++-- tests/ui/unnecessary_map_or.stderr | 26 ++++++++++++++++--- 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 15b192c9c109..2e9f6ea4731f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4107,24 +4107,32 @@ declare_clippy_lint! { /// ### Why is this bad? /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome, /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`. + /// Also, calls such as `opt.map_or(true, |val| val == 5)` can be reduced to + /// `opt.is_none_or(|val| val == 5)`. /// This lint offers readability and conciseness improvements. /// /// ### Example /// ```no_run - /// pub fn a(x: Option) -> bool { - /// x.map_or(false, |n| n == 5) + /// pub fn a(x: Option) -> (bool, bool) { + /// ( + /// x.map_or(false, |n| n == 5), + /// x.map_or(true, |n| n > 5), + /// ) /// } /// ``` /// Use instead: /// ```no_run - /// pub fn a(x: Option) -> bool { - /// x == Some(5) + /// pub fn a(x: Option) -> (bool, bool) { + /// ( + /// x == Some(5), + /// x.is_none_or(|n| n > 5), + /// ) /// } /// ``` #[clippy::version = "1.75.0"] pub UNNECESSARY_MAP_OR, style, - "reduce unnecessary pattern matching for constructs that implement `PartialEq`" + "reduce unnecessary calls to `.map_or(bool, …)`" } declare_clippy_lint! { diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index 1dacec1032dd..74c0c35f9aa9 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -60,7 +60,7 @@ pub(super) fn check<'a>( Some(_) | None => return, }; - let (sugg, method) = if let ExprKind::Closure(map_closure) = map.kind + let (sugg, method, applicability) = if let ExprKind::Closure(map_closure) = map.kind && let closure_body = cx.tcx.hir().body(map_closure.body) && let closure_body_value = closure_body.value.peel_blocks() && let ExprKind::Binary(op, l, r) = closure_body_value.kind @@ -100,7 +100,7 @@ pub(super) fn check<'a>( .maybe_par() .into_string(); - (binop, "a standard comparison") + (binop, "a standard comparison", Applicability::MaybeIncorrect) } else if !def_bool && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite()) @@ -110,6 +110,18 @@ pub(super) fn check<'a>( ( format!("{recv_callsite}.{suggested_name}({span_callsite})",), suggested_name, + Applicability::MachineApplicable, + ) + } else if def_bool + && matches!(variant, Variant::Some) + && msrv.meets(msrvs::IS_NONE_OR) + && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite()) + && let Some(span_callsite) = snippet_opt(cx, map.span.source_callsite()) + { + ( + format!("{recv_callsite}.is_none_or({span_callsite})"), + "is_none_or", + Applicability::MachineApplicable, ) } else { return; @@ -126,6 +138,6 @@ pub(super) fn check<'a>( "this `map_or` is redundant", format!("use {method} instead"), sugg, - Applicability::MaybeIncorrect, + applicability, ); } diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index d645cd3f3c45..70b78ceca502 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -23,10 +23,9 @@ fn main() { let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); let _ = (Ok::(5) == Ok(5)); let _ = (Some(5) == Some(5)).then(|| 1); + let _ = Some(5).is_none_or(|n| n == 5); + let _ = Some(5).is_none_or(|n| 5 == n); - // shouldnt trigger - let _ = Some(5).map_or(true, |n| n == 5); - let _ = Some(5).map_or(true, |n| 5 == n); macro_rules! x { () => { Some(1) @@ -56,11 +55,16 @@ fn main() { let r: Result = Ok(3); let _ = r.is_ok_and(func); let _ = Some(5).is_some_and(func); + let _ = Some(5).is_none_or(func); #[derive(PartialEq)] struct S2; let r: Result = Ok(4); let _ = (r == Ok(8)); + + // do not lint `Result::map_or(true, …)` + let r: Result = Ok(4); + let _ = r.map_or(true, |x| x == 8); } #[clippy::msrv = "1.69.0"] @@ -68,3 +72,9 @@ fn msrv_1_69() { // is_some_and added in 1.70.0 let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); } + +#[clippy::msrv = "1.81.0"] +fn msrv_1_81() { + // is_none_or added in 1.82.0 + let _ = Some(5).map_or(true, |n| n == if 2 > 1 { n } else { 0 }); +} diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index 4939d52fd43a..507577159771 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -26,10 +26,9 @@ fn main() { let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); let _ = Ok::(5).map_or(false, |n| n == 5); let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); - - // shouldnt trigger let _ = Some(5).map_or(true, |n| n == 5); let _ = Some(5).map_or(true, |n| 5 == n); + macro_rules! x { () => { Some(1) @@ -59,11 +58,16 @@ fn main() { let r: Result = Ok(3); let _ = r.map_or(false, func); let _ = Some(5).map_or(false, func); + let _ = Some(5).map_or(true, func); #[derive(PartialEq)] struct S2; let r: Result = Ok(4); let _ = r.map_or(false, |x| x == 8); + + // do not lint `Result::map_or(true, …)` + let r: Result = Ok(4); + let _ = r.map_or(true, |x| x == 8); } #[clippy::msrv = "1.69.0"] @@ -71,3 +75,9 @@ fn msrv_1_69() { // is_some_and added in 1.70.0 let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); } + +#[clippy::msrv = "1.81.0"] +fn msrv_1_81() { + // is_none_or added in 1.82.0 + let _ = Some(5).map_or(true, |n| n == if 2 > 1 { n } else { 0 }); +} diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index 56295594ddcb..025eb24d465f 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -84,28 +84,46 @@ LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))` error: this `map_or` is redundant - --> tests/ui/unnecessary_map_or.rs:55:13 + --> tests/ui/unnecessary_map_or.rs:29:13 + | +LL | let _ = Some(5).map_or(true, |n| n == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| n == 5)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:30:13 + | +LL | let _ = Some(5).map_or(true, |n| 5 == n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| 5 == n)` + +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:54:13 | LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)` error: this `map_or` is redundant - --> tests/ui/unnecessary_map_or.rs:60:13 + --> tests/ui/unnecessary_map_or.rs:59:13 | LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(func)` error: this `map_or` is redundant - --> tests/ui/unnecessary_map_or.rs:61:13 + --> tests/ui/unnecessary_map_or.rs:60:13 | LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(func)` +error: this `map_or` is redundant + --> tests/ui/unnecessary_map_or.rs:61:13 + | +LL | let _ = Some(5).map_or(true, func); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(func)` + error: this `map_or` is redundant --> tests/ui/unnecessary_map_or.rs:66:13 | LL | let _ = r.map_or(false, |x| x == 8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))` -error: aborting due to 15 previous errors +error: aborting due to 18 previous errors From 88598473733d8004d2366a88471fc922a9bc795d Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 17 Nov 2024 04:05:05 +0100 Subject: [PATCH 054/330] `redundant_guards`: lint float literals, don't lint cstr literals --- clippy_lints/src/matches/redundant_guards.rs | 7 +- tests/ui/redundant_guards.fixed | 15 +++- tests/ui/redundant_guards.rs | 11 ++- tests/ui/redundant_guards.stderr | 86 +++++++++++++------- 4 files changed, 78 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs index 9e54475033c8..bfff199af037 100644 --- a/clippy_lints/src/matches/redundant_guards.rs +++ b/clippy_lints/src/matches/redundant_guards.rs @@ -243,11 +243,6 @@ fn emit_redundant_guards<'tcx>( } /// Checks if the given `Expr` can also be represented as a `Pat`. -/// -/// All literals generally also work as patterns, however float literals are special. -/// They are currently (as of 2023/08/08) still allowed in patterns, but that will become -/// an error in the future, and rustc already actively warns against this (see rust#41620), -/// so we don't consider those as usable within patterns for linting purposes. fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { for_each_expr_without_closures(expr, |expr| { if match expr.kind { @@ -267,7 +262,7 @@ fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { | ExprKind::Tup(..) | ExprKind::Struct(..) | ExprKind::Unary(UnOp::Neg, _) => true, - ExprKind::Lit(lit) if !matches!(lit.node, LitKind::Float(..)) => true, + ExprKind::Lit(lit) if !matches!(lit.node, LitKind::CStr(..)) => true, _ => false, } { return ControlFlow::Continue(()); diff --git a/tests/ui/redundant_guards.fixed b/tests/ui/redundant_guards.fixed index ed4b1c219150..ff7b233f004e 100644 --- a/tests/ui/redundant_guards.fixed +++ b/tests/ui/redundant_guards.fixed @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs #![feature(if_let_guard)] -#![allow(clippy::no_effect, unused, clippy::single_match)] +#![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)] #![warn(clippy::redundant_guards)] #[macro_use] @@ -19,15 +19,24 @@ struct FloatWrapper(f32); fn issue11304() { match 0.1 { - x if x == 0.0 => todo!(), + 0.0 => todo!(), + // Pattern matching NAN is illegal + x if x == f64::NAN => todo!(), _ => todo!(), } match FloatWrapper(0.1) { - x if x == FloatWrapper(0.0) => todo!(), + FloatWrapper(0.0) => todo!(), _ => todo!(), } } +fn issue13681() { + match c"hi" { + x if x == c"hi" => (), + _ => (), + } +} + fn main() { let c = C(1, 2); match c { diff --git a/tests/ui/redundant_guards.rs b/tests/ui/redundant_guards.rs index adbc4ed16cd7..b4d4ef5b170d 100644 --- a/tests/ui/redundant_guards.rs +++ b/tests/ui/redundant_guards.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macros.rs #![feature(if_let_guard)] -#![allow(clippy::no_effect, unused, clippy::single_match)] +#![allow(clippy::no_effect, unused, clippy::single_match, invalid_nan_comparisons)] #![warn(clippy::redundant_guards)] #[macro_use] @@ -20,6 +20,8 @@ struct FloatWrapper(f32); fn issue11304() { match 0.1 { x if x == 0.0 => todo!(), + // Pattern matching NAN is illegal + x if x == f64::NAN => todo!(), _ => todo!(), } match FloatWrapper(0.1) { @@ -28,6 +30,13 @@ fn issue11304() { } } +fn issue13681() { + match c"hi" { + x if x == c"hi" => (), + _ => (), + } +} + fn main() { let c = C(1, 2); match c { diff --git a/tests/ui/redundant_guards.stderr b/tests/ui/redundant_guards.stderr index fd12e0832823..7512546450b2 100644 --- a/tests/ui/redundant_guards.stderr +++ b/tests/ui/redundant_guards.stderr @@ -1,11 +1,35 @@ error: redundant guard - --> tests/ui/redundant_guards.rs:34:20 + --> tests/ui/redundant_guards.rs:22:14 + | +LL | x if x == 0.0 => todo!(), + | ^^^^^^^^ + | + = note: `-D clippy::redundant-guards` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::redundant_guards)]` +help: try + | +LL - x if x == 0.0 => todo!(), +LL + 0.0 => todo!(), + | + +error: redundant guard + --> tests/ui/redundant_guards.rs:28:14 + | +LL | x if x == FloatWrapper(0.0) => todo!(), + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - x if x == FloatWrapper(0.0) => todo!(), +LL + FloatWrapper(0.0) => todo!(), + | + +error: redundant guard + --> tests/ui/redundant_guards.rs:43:20 | LL | C(x, y) if let 1 = y => .., | ^^^^^^^^^ | - = note: `-D clippy::redundant-guards` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::redundant_guards)]` help: try | LL - C(x, y) if let 1 = y => .., @@ -13,7 +37,7 @@ LL + C(x, 1) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:40:20 + --> tests/ui/redundant_guards.rs:49:20 | LL | Some(x) if matches!(x, Some(1) if true) => .., | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +48,7 @@ LL | Some(Some(1)) if true => .., | ~~~~~~~ ~~~~~~~ error: redundant guard - --> tests/ui/redundant_guards.rs:41:20 + --> tests/ui/redundant_guards.rs:50:20 | LL | Some(x) if matches!(x, Some(1)) => { | ^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +60,7 @@ LL + Some(Some(1)) => { | error: redundant guard - --> tests/ui/redundant_guards.rs:45:20 + --> tests/ui/redundant_guards.rs:54:20 | LL | Some(x) if let Some(1) = x => .., | ^^^^^^^^^^^^^^^ @@ -48,7 +72,7 @@ LL + Some(Some(1)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:46:20 + --> tests/ui/redundant_guards.rs:55:20 | LL | Some(x) if x == Some(2) => .., | ^^^^^^^^^^^^ @@ -60,7 +84,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:47:20 + --> tests/ui/redundant_guards.rs:56:20 | LL | Some(x) if Some(2) == x => .., | ^^^^^^^^^^^^ @@ -72,7 +96,7 @@ LL + Some(Some(2)) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:72:20 + --> tests/ui/redundant_guards.rs:81:20 | LL | B { e } if matches!(e, Some(A(2))) => .., | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +108,7 @@ LL + B { e: Some(A(2)) } => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:109:20 + --> tests/ui/redundant_guards.rs:118:20 | LL | E::A(y) if y == "not from an or pattern" => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +120,7 @@ LL + E::A("not from an or pattern") => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:116:14 + --> tests/ui/redundant_guards.rs:125:14 | LL | x if matches!(x, Some(0)) => .., | ^^^^^^^^^^^^^^^^^^^^ @@ -108,7 +132,7 @@ LL + Some(0) => .., | error: redundant guard - --> tests/ui/redundant_guards.rs:123:14 + --> tests/ui/redundant_guards.rs:132:14 | LL | i if i == -1 => {}, | ^^^^^^^ @@ -120,7 +144,7 @@ LL + -1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:124:14 + --> tests/ui/redundant_guards.rs:133:14 | LL | i if i == 1 => {}, | ^^^^^^ @@ -132,7 +156,7 @@ LL + 1 => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:186:28 + --> tests/ui/redundant_guards.rs:195:28 | LL | Some(ref x) if x == &1 => {}, | ^^^^^^^ @@ -144,7 +168,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:187:28 + --> tests/ui/redundant_guards.rs:196:28 | LL | Some(ref x) if &1 == x => {}, | ^^^^^^^ @@ -156,7 +180,7 @@ LL + Some(1) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:188:28 + --> tests/ui/redundant_guards.rs:197:28 | LL | Some(ref x) if let &2 = x => {}, | ^^^^^^^^^^ @@ -168,7 +192,7 @@ LL + Some(2) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:189:28 + --> tests/ui/redundant_guards.rs:198:28 | LL | Some(ref x) if matches!(x, &3) => {}, | ^^^^^^^^^^^^^^^ @@ -180,7 +204,7 @@ LL + Some(3) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:209:32 + --> tests/ui/redundant_guards.rs:218:32 | LL | B { ref c, .. } if c == &1 => {}, | ^^^^^^^ @@ -192,7 +216,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:210:32 + --> tests/ui/redundant_guards.rs:219:32 | LL | B { ref c, .. } if &1 == c => {}, | ^^^^^^^ @@ -204,7 +228,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:211:32 + --> tests/ui/redundant_guards.rs:220:32 | LL | B { ref c, .. } if let &1 = c => {}, | ^^^^^^^^^^ @@ -216,7 +240,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:212:32 + --> tests/ui/redundant_guards.rs:221:32 | LL | B { ref c, .. } if matches!(c, &1) => {}, | ^^^^^^^^^^^^^^^ @@ -228,7 +252,7 @@ LL + B { c: 1, .. } => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:222:26 + --> tests/ui/redundant_guards.rs:231:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -240,7 +264,7 @@ LL + Some(Some("")) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:233:26 + --> tests/ui/redundant_guards.rs:242:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -252,7 +276,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:238:26 + --> tests/ui/redundant_guards.rs:247:26 | LL | Some(Some(x)) if x.is_empty() => {}, | ^^^^^^^^^^^^ @@ -264,7 +288,7 @@ LL + Some(Some([])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:249:26 + --> tests/ui/redundant_guards.rs:258:26 | LL | Some(Some(x)) if x.starts_with(&[]) => {}, | ^^^^^^^^^^^^^^^^^^ @@ -276,7 +300,7 @@ LL + Some(Some([..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:254:26 + --> tests/ui/redundant_guards.rs:263:26 | LL | Some(Some(x)) if x.starts_with(&[1]) => {}, | ^^^^^^^^^^^^^^^^^^^ @@ -288,7 +312,7 @@ LL + Some(Some([1, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:259:26 + --> tests/ui/redundant_guards.rs:268:26 | LL | Some(Some(x)) if x.starts_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^^^ @@ -300,7 +324,7 @@ LL + Some(Some([1, 2, ..])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:264:26 + --> tests/ui/redundant_guards.rs:273:26 | LL | Some(Some(x)) if x.ends_with(&[1, 2]) => {}, | ^^^^^^^^^^^^^^^^^^^^ @@ -312,7 +336,7 @@ LL + Some(Some([.., 1, 2])) => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:286:18 + --> tests/ui/redundant_guards.rs:295:18 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -324,7 +348,7 @@ LL + "" => {}, | error: redundant guard - --> tests/ui/redundant_guards.rs:305:22 + --> tests/ui/redundant_guards.rs:314:22 | LL | y if y.is_empty() => {}, | ^^^^^^^^^^^^ @@ -335,5 +359,5 @@ LL - y if y.is_empty() => {}, LL + "" => {}, | -error: aborting due to 28 previous errors +error: aborting due to 30 previous errors From a96a0934de14b4bd921b43695a1b50ea72f3077d Mon Sep 17 00:00:00 2001 From: Tarek Date: Sun, 17 Nov 2024 12:17:44 +0200 Subject: [PATCH 055/330] =?UTF-8?q?feat:=20migrate=C2=A0`reorder=5Fimpl=5F?= =?UTF-8?q?items`=C2=A0assist=20to=20use=C2=A0`SyntaxFactory`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tarek --- .../src/handlers/reorder_impl_items.rs | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs index ada89ce7c40a..d7fa8826125b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs @@ -3,7 +3,7 @@ use ide_db::{FxHashMap, RootDatabase}; use itertools::Itertools; use syntax::{ ast::{self, HasName}, - ted, AstNode, + AstNode, SyntaxElement, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -46,6 +46,11 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> let impl_ast = ctx.find_node_at_offset::()?; let items = impl_ast.assoc_item_list()?; + let parent_node = match ctx.covering_element() { + SyntaxElement::Node(n) => n, + SyntaxElement::Token(t) => t.parent()?, + }; + // restrict the range // if cursor is in assoc_items, abort let assoc_range = items.syntax().text_range(); @@ -94,12 +99,14 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) -> "Sort items by trait definition", target, |builder| { - let assoc_items = - assoc_items.into_iter().map(|item| builder.make_mut(item)).collect::>(); - assoc_items - .into_iter() - .zip(sorted) - .for_each(|(old, new)| ted::replace(old.syntax(), new.clone_for_update().syntax())); + let mut editor = builder.make_editor(&parent_node); + + assoc_items.into_iter().zip(sorted).for_each(|(old, new)| { + // FIXME: remove `clone_for_update` when `SyntaxEditor` handles it for us + editor.replace(old.syntax(), new.clone_for_update().syntax()) + }); + + builder.add_file_edits(ctx.file_id(), editor); }, ) } From 74b95f2e65a1b6c7798e819c87de1ddc61b85610 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 15 Nov 2024 19:59:38 +0100 Subject: [PATCH 056/330] Prepare clippy_utils for publishing - Add metadata to clippy_utils/Cargo.toml file - Add clippy_utils README.md file --- clippy_utils/Cargo.toml | 6 ++++++ clippy_utils/README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 clippy_utils/README.md diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index d136f3bc6f1d..fb2acf700ab3 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -2,6 +2,12 @@ name = "clippy_utils" version = "0.1.84" edition = "2021" +description = "Helpful tools for writing lints, provided as they are used in Clippy" +repository = "https://github.com/rust-lang/rust-clippy" +readme = "README.md" +license = "MIT OR Apache-2.0" +keywords = ["clippy", "lint", "utils"] +categories = ["development-tools"] [dependencies] arrayvec = { version = "0.7", default-features = false } diff --git a/clippy_utils/README.md b/clippy_utils/README.md new file mode 100644 index 000000000000..fb1a3f13f8cb --- /dev/null +++ b/clippy_utils/README.md @@ -0,0 +1,40 @@ +# `clippy-utils` + +Helpful tools for writing lints, provided as they are used in Clippy. + +## Usage + +This crate is only guaranteed to build with this `nightly` toolchain: + + +``` +nightly-2024-11-14 +``` + + +To use `clippy-utils` in your lint, add the following to your `Cargo.toml`: + +``` +clippy_utils = "0.1.XY" +``` + +`XY` is the version of the nightly toolchain above and can be determined with `rustc +nightly-YYYY-MM-DD -V`. + +## :warning: Stability :warning: + +No stability guarantees are made for this crate! Use at your own risk. + +Function signatures can change or be removed without replacement without any prior notice. + +## LICENSE + + + +Copyright 2014-2024 The Rust Project Developers + +Licensed under the Apache License, Version 2.0 +<[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license +<[https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT)>, at your option. Files in the project may +not be copied, modified, or distributed except according to those terms. + + From ef42a66afe1b97731e5fd1ddb4c1f6708edcb224 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Sat, 16 Nov 2024 14:52:42 +0500 Subject: [PATCH 057/330] Do not trigger if_let_mutex strating from Edition 2024 --- clippy_lints/src/if_let_mutex.rs | 11 +++++++++++ ...t_mutex.stderr => if_let_mutex.edition2021.stderr} | 8 ++++---- tests/ui/if_let_mutex.rs | 11 ++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) rename tests/ui/{if_let_mutex.stderr => if_let_mutex.edition2021.stderr} (94%) diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index ba80c099a015..943713654def 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -7,6 +7,7 @@ use rustc_errors::Diag; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::edition::Edition::Edition2024; use rustc_span::sym; declare_clippy_lint! { @@ -14,6 +15,12 @@ declare_clippy_lint! { /// Checks for `Mutex::lock` calls in `if let` expression /// with lock calls in any of the else blocks. /// + /// ### Disabled starting in Edition 2024 + /// This lint is effectively disabled starting in + /// Edition 2024 as `if let ... else` scoping was reworked + /// such that this is no longer an issue. See + /// [Proposal: stabilize if_let_rescope for Edition 2024](https://github.com/rust-lang/rust/issues/131154) + /// /// ### Why is this bad? /// The Mutex lock remains held for the whole /// `if let ... else` block and deadlocks. @@ -45,6 +52,10 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]); impl<'tcx> LateLintPass<'tcx> for IfLetMutex { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if cx.tcx.sess.edition() >= Edition2024 { + return; + } + if let Some(higher::IfLet { let_expr, if_then, diff --git a/tests/ui/if_let_mutex.stderr b/tests/ui/if_let_mutex.edition2021.stderr similarity index 94% rename from tests/ui/if_let_mutex.stderr rename to tests/ui/if_let_mutex.edition2021.stderr index 45df4ac4d679..984d6adbb2a4 100644 --- a/tests/ui/if_let_mutex.stderr +++ b/tests/ui/if_let_mutex.edition2021.stderr @@ -1,5 +1,5 @@ error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:11:5 + --> tests/ui/if_let_mutex.rs:16:5 | LL | if let Err(locked) = m.lock() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -19,7 +19,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::if_let_mutex)]` error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:24:5 + --> tests/ui/if_let_mutex.rs:29:5 | LL | if let Some(locked) = m.lock().unwrap().deref() { | ^ - this Mutex will remain locked for the entire `if let`-block... @@ -37,7 +37,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:46:5 + --> tests/ui/if_let_mutex.rs:51:5 | LL | if let Ok(i) = mutex.lock() { | ^ ----- this Mutex will remain locked for the entire `if let`-block... @@ -54,7 +54,7 @@ LL | | }; = help: move the lock call outside of the `if let ...` expression error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock - --> tests/ui/if_let_mutex.rs:55:5 + --> tests/ui/if_let_mutex.rs:60:5 | LL | if let Ok(_) = m1.lock() { | ^ -- this Mutex will remain locked for the entire `if let`-block... diff --git a/tests/ui/if_let_mutex.rs b/tests/ui/if_let_mutex.rs index bb0eadfca1c7..80eee2939890 100644 --- a/tests/ui/if_let_mutex.rs +++ b/tests/ui/if_let_mutex.rs @@ -1,3 +1,8 @@ +//@ compile-flags: -Zunstable-options + +//@revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 #![warn(clippy::if_let_mutex)] #![allow(clippy::redundant_pattern_matching)] @@ -9,7 +14,7 @@ fn do_stuff(_: T) {} fn if_let() { let m = Mutex::new(1_u8); if let Err(locked) = m.lock() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + //~[edition2021]^ if_let_mutex do_stuff(locked); } else { let lock = m.lock().unwrap(); @@ -22,7 +27,7 @@ fn if_let() { fn if_let_option() { let m = Mutex::new(Some(0_u8)); if let Some(locked) = m.lock().unwrap().deref() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + //~[edition2021]^ if_let_mutex do_stuff(locked); } else { let lock = m.lock().unwrap(); @@ -44,7 +49,7 @@ fn if_let_different_mutex() { fn mutex_ref(mutex: &Mutex) { if let Ok(i) = mutex.lock() { - //~^ ERROR: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a d + //~[edition2021]^ if_let_mutex do_stuff(i); } else { let _x = mutex.lock(); From a2b6b6b085db2459e4331dd6becaac8191c1d84b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 17 Nov 2024 12:25:19 -0800 Subject: [PATCH 058/330] Inline ExprPrecedence::order into Expr::precedence --- clippy_lints/src/dereference.rs | 10 +++++----- clippy_lints/src/loops/single_element_loop.rs | 2 +- clippy_lints/src/matches/manual_utils.rs | 2 +- clippy_lints/src/neg_multiply.rs | 2 +- clippy_lints/src/redundant_slicing.rs | 2 +- .../transmute/transmutes_expressible_as_ptr_casts.rs | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index b167d7f22087..834606094ae0 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -959,7 +959,7 @@ fn report<'tcx>( // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary. /* - expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX { + expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX { Cow::Owned(format!("({expr_str})")) } else { expr_str @@ -999,7 +999,7 @@ fn report<'tcx>( Node::Expr(e) => match e.kind { ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false), ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))), - _ => (e.precedence().order(), false), + _ => (e.precedence(), false), }, _ => (0, false), }; @@ -1012,7 +1012,7 @@ fn report<'tcx>( ); let sugg = if !snip_is_macro - && (calls_field || expr.precedence().order() < precedence) + && (calls_field || expr.precedence() < precedence) && !has_enclosing_paren(&snip) && !is_in_tuple { @@ -1067,7 +1067,7 @@ fn report<'tcx>( let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); let sugg = - if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) { + if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) { format!("{prefix}({snip})") } else { format!("{prefix}{snip}") @@ -1154,7 +1154,7 @@ impl<'tcx> Dereferencing<'tcx> { }, Some(parent) if !parent.span.from_expansion() => { // Double reference might be needed at this point. - if parent.precedence().order() == PREC_UNAMBIGUOUS { + if parent.precedence() == PREC_UNAMBIGUOUS { // Parentheses would be needed here, don't lint. *outer_pat = None; } else { diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index 70f76ced09a4..35dc8e9aa4e2 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( if !prefix.is_empty() && ( // Precedence of internal expression is less than or equal to precedence of `&expr`. - arg_expression.precedence().order() <= PREC_PREFIX || is_range_literal(arg_expression) + arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression) ) { arg_snip = format!("({arg_snip})").into(); diff --git a/clippy_lints/src/matches/manual_utils.rs b/clippy_lints/src/matches/manual_utils.rs index d38560998a5a..9c6df4d8ac0d 100644 --- a/clippy_lints/src/matches/manual_utils.rs +++ b/clippy_lints/src/matches/manual_utils.rs @@ -117,7 +117,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_UNAMBIGUOUS { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS { format!("({scrutinee_str})") } else { scrutinee_str.into() diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index f84d9fadb85c..a0ba2aaf5523 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { { let mut applicability = Applicability::MachineApplicable; let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); - let suggestion = if !from_macro && exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) { + let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) { format!("-({snip})") } else { format!("-{snip}") diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index dc66fb28fa8c..159404e130d6 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr)); let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); - let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence().order() > PREC_PREFIX); + let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX); if expr_ty == indexed_ty { if expr_ref_count > indexed_ref_count { diff --git a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index fca332dba401..cad15b1e9826 100644 --- a/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -1,7 +1,7 @@ use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use rustc_ast::ExprPrecedence; +use rustc_ast::util::parser::AssocOp; use rustc_errors::Applicability; use rustc_hir::{Expr, Node}; use rustc_hir_typeck::cast::check_cast; @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( }; if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id) - && parent.precedence().order() > ExprPrecedence::Cast.order() + && parent.precedence() > AssocOp::As.precedence() as i8 { sugg = format!("({sugg})"); } From 9c8d9504cedcf0088252c22a16698379e35f2099 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Sat, 4 May 2024 15:17:46 +0200 Subject: [PATCH 059/330] Introduce `utils` mod in clippy_dev There was some dependence between the different subcommands of clippy_dev. And this dependence will increased with the introduction of the sync and release subcommands. This moves the common functions to a `utils` module, to decouple the other modules. --- clippy_dev/src/dogfood.rs | 2 +- clippy_dev/src/fmt.rs | 2 +- clippy_dev/src/lib.rs | 60 +------------- clippy_dev/src/lint.rs | 2 +- clippy_dev/src/main.rs | 8 +- clippy_dev/src/new_lint.rs | 21 +---- clippy_dev/src/update_lints.rs | 71 +---------------- clippy_dev/src/utils.rs | 142 +++++++++++++++++++++++++++++++++ 8 files changed, 154 insertions(+), 154 deletions(-) create mode 100644 clippy_dev/src/utils.rs diff --git a/clippy_dev/src/dogfood.rs b/clippy_dev/src/dogfood.rs index a0d57f5ab483..75a4cbd2f92e 100644 --- a/clippy_dev/src/dogfood.rs +++ b/clippy_dev/src/dogfood.rs @@ -1,4 +1,4 @@ -use crate::{clippy_project_root, exit_if_err}; +use crate::utils::{clippy_project_root, exit_if_err}; use std::process::Command; /// # Panics diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 8c61c35533cf..c66738592820 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::utils::clippy_project_root; use itertools::Itertools; use rustc_lexer::{TokenKind, tokenize}; use shell_escape::escape; diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index ad385d5fbd29..d96b79ec26c9 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -14,10 +14,6 @@ extern crate rustc_driver; extern crate rustc_lexer; -use std::io; -use std::path::PathBuf; -use std::process::{self, ExitStatus}; - pub mod dogfood; pub mod fmt; pub mod lint; @@ -25,58 +21,4 @@ pub mod new_lint; pub mod serve; pub mod setup; pub mod update_lints; - -#[cfg(not(windows))] -static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; -#[cfg(windows)] -static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; - -/// Returns the path to the `cargo-clippy` binary -/// -/// # Panics -/// -/// Panics if the path of current executable could not be retrieved. -#[must_use] -pub fn cargo_clippy_path() -> PathBuf { - let mut path = std::env::current_exe().expect("failed to get current executable name"); - path.set_file_name(CARGO_CLIPPY_EXE); - path -} - -/// Returns the path to the Clippy project directory -/// -/// # Panics -/// -/// Panics if the current directory could not be retrieved, there was an error reading any of the -/// Cargo.toml files or ancestor directory is the clippy root directory -#[must_use] -pub fn clippy_project_root() -> PathBuf { - let current_dir = std::env::current_dir().unwrap(); - for path in current_dir.ancestors() { - let result = std::fs::read_to_string(path.join("Cargo.toml")); - if let Err(err) = &result { - if err.kind() == io::ErrorKind::NotFound { - continue; - } - } - - let content = result.unwrap(); - if content.contains("[package]\nname = \"clippy\"") { - return path.to_path_buf(); - } - } - panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); -} - -/// # Panics -/// Panics if given command result was failed. -pub fn exit_if_err(status: io::Result) { - match status.expect("failed to run command").code() { - Some(0) => {}, - Some(n) => process::exit(n), - None => { - eprintln!("Killed by signal"); - process::exit(1); - }, - } -} +pub mod utils; diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs index f308f5dfdfd8..125195397e6c 100644 --- a/clippy_dev/src/lint.rs +++ b/clippy_dev/src/lint.rs @@ -1,4 +1,4 @@ -use crate::{cargo_clippy_path, exit_if_err}; +use crate::utils::{cargo_clippy_path, exit_if_err}; use std::process::{self, Command}; use std::{env, fs}; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index fc15913354cd..f5055b429125 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{Args, Parser, Subcommand}; -use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints}; +use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints, utils}; use std::convert::Infallible; fn main() { @@ -23,9 +23,9 @@ fn main() { if print_only { update_lints::print_lints(); } else if check { - update_lints::update(update_lints::UpdateMode::Check); + update_lints::update(utils::UpdateMode::Check); } else { - update_lints::update(update_lints::UpdateMode::Change); + update_lints::update(utils::UpdateMode::Change); } }, DevCommand::NewLint { @@ -35,7 +35,7 @@ fn main() { r#type, msrv, } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) { - Ok(()) => update_lints::update(update_lints::UpdateMode::Change), + Ok(()) => update_lints::update(utils::UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {e}"), }, DevCommand::Setup(SetupCommand { subcommand }) => match subcommand { diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index ee626d60b864..35dd986ff614 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::utils::{clippy_project_root, clippy_version}; use indoc::{formatdoc, writedoc}; use std::fmt; use std::fmt::Write as _; @@ -186,23 +186,8 @@ fn to_camel_case(name: &str) -> String { } pub(crate) fn get_stabilization_version() -> String { - fn parse_manifest(contents: &str) -> Option { - let version = contents - .lines() - .filter_map(|l| l.split_once('=')) - .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?; - let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else { - return None; - }; - let (minor, patch) = version.split_once('.')?; - Some(format!( - "{}.{}.0", - minor.parse::().ok()?, - patch.parse::().ok()? - )) - } - let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`"); - parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`") + let (minor, patch) = clippy_version(); + format!("{minor}.{patch}.0") } fn get_test_file_contents(lint_name: &str, msrv: bool) -> String { diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 795456ad3c56..612d1c0ae139 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -1,4 +1,4 @@ -use crate::clippy_project_root; +use crate::utils::{UpdateMode, clippy_project_root, exit_with_failure, replace_region_in_file}; use aho_corasick::AhoCorasickBuilder; use itertools::Itertools; use rustc_lexer::{LiteralKind, TokenKind, tokenize, unescape}; @@ -17,12 +17,6 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html"; -#[derive(Clone, Copy, PartialEq, Eq)] -pub enum UpdateMode { - Check, - Change, -} - /// Runs the `update_lints` command. /// /// This updates various generated values from the lint source code. @@ -511,14 +505,6 @@ fn process_file(path: impl AsRef, update_mode: UpdateMode, content: &str) } } -fn exit_with_failure() { - println!( - "Not all lints defined properly. \ - Please run `cargo dev update_lints` to make sure all lints are defined properly." - ); - std::process::exit(1); -} - /// Lint data parsed from the Clippy source code. #[derive(Clone, PartialEq, Eq, Debug)] struct Lint { @@ -851,61 +837,6 @@ fn remove_line_splices(s: &str) -> String { }); res } - -/// Replaces a region in a file delimited by two lines matching regexes. -/// -/// `path` is the relative path to the file on which you want to perform the replacement. -/// -/// See `replace_region_in_text` for documentation of the other options. -/// -/// # Panics -/// -/// Panics if the path could not read or then written -fn replace_region_in_file( - update_mode: UpdateMode, - path: &Path, - start: &str, - end: &str, - write_replacement: impl FnMut(&mut String), -) { - let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display())); - let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) { - Ok(x) => x, - Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()), - }; - - match update_mode { - UpdateMode::Check if contents != new_contents => exit_with_failure(), - UpdateMode::Check => (), - UpdateMode::Change => { - if let Err(e) = fs::write(path, new_contents.as_bytes()) { - panic!("Cannot write to `{}`: {e}", path.display()); - } - }, - } -} - -/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters -/// were found, or the missing delimiter if not. -fn replace_region_in_text<'a>( - text: &str, - start: &'a str, - end: &'a str, - mut write_replacement: impl FnMut(&mut String), -) -> Result { - let (text_start, rest) = text.split_once(start).ok_or(start)?; - let (_, text_end) = rest.split_once(end).ok_or(end)?; - - let mut res = String::with_capacity(text.len() + 4096); - res.push_str(text_start); - res.push_str(start); - write_replacement(&mut res); - res.push_str(end); - res.push_str(text_end); - - Ok(res) -} - fn try_rename_file(old_name: &Path, new_name: &Path) -> bool { match OpenOptions::new().create_new(true).write(true).open(new_name) { Ok(file) => drop(file), diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs new file mode 100644 index 000000000000..b87fcca13b1c --- /dev/null +++ b/clippy_dev/src/utils.rs @@ -0,0 +1,142 @@ +use std::path::{Path, PathBuf}; +use std::process::{self, ExitStatus}; +use std::{fs, io}; + +#[cfg(not(windows))] +static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; +#[cfg(windows)] +static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; + +/// Returns the path to the `cargo-clippy` binary +/// +/// # Panics +/// +/// Panics if the path of current executable could not be retrieved. +#[must_use] +pub fn cargo_clippy_path() -> PathBuf { + let mut path = std::env::current_exe().expect("failed to get current executable name"); + path.set_file_name(CARGO_CLIPPY_EXE); + path +} + +/// Returns the path to the Clippy project directory +/// +/// # Panics +/// +/// Panics if the current directory could not be retrieved, there was an error reading any of the +/// Cargo.toml files or ancestor directory is the clippy root directory +#[must_use] +pub fn clippy_project_root() -> PathBuf { + let current_dir = std::env::current_dir().unwrap(); + for path in current_dir.ancestors() { + let result = fs::read_to_string(path.join("Cargo.toml")); + if let Err(err) = &result { + if err.kind() == io::ErrorKind::NotFound { + continue; + } + } + + let content = result.unwrap(); + if content.contains("[package]\nname = \"clippy\"") { + return path.to_path_buf(); + } + } + panic!("error: Can't determine root of project. Please run inside a Clippy working dir."); +} + +/// # Panics +/// Panics if given command result was failed. +pub fn exit_if_err(status: io::Result) { + match status.expect("failed to run command").code() { + Some(0) => {}, + Some(n) => process::exit(n), + None => { + eprintln!("Killed by signal"); + process::exit(1); + }, + } +} + +pub(crate) fn clippy_version() -> (u32, u32) { + fn parse_manifest(contents: &str) -> Option<(u32, u32)> { + let version = contents + .lines() + .filter_map(|l| l.split_once('=')) + .find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))?; + let Some(("0", version)) = version.get(1..version.len() - 1)?.split_once('.') else { + return None; + }; + let (minor, patch) = version.split_once('.')?; + Some((minor.parse().ok()?, patch.parse().ok()?)) + } + let contents = fs::read_to_string("Cargo.toml").expect("Unable to read `Cargo.toml`"); + parse_manifest(&contents).expect("Unable to find package version in `Cargo.toml`") +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum UpdateMode { + Check, + Change, +} + +pub(crate) fn exit_with_failure() { + println!( + "Not all lints defined properly. \ + Please run `cargo dev update_lints` to make sure all lints are defined properly." + ); + process::exit(1); +} + +/// Replaces a region in a file delimited by two lines matching regexes. +/// +/// `path` is the relative path to the file on which you want to perform the replacement. +/// +/// See `replace_region_in_text` for documentation of the other options. +/// +/// # Panics +/// +/// Panics if the path could not read or then written +pub(crate) fn replace_region_in_file( + update_mode: UpdateMode, + path: &Path, + start: &str, + end: &str, + write_replacement: impl FnMut(&mut String), +) { + let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display())); + let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) { + Ok(x) => x, + Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()), + }; + + match update_mode { + UpdateMode::Check if contents != new_contents => exit_with_failure(), + UpdateMode::Check => (), + UpdateMode::Change => { + if let Err(e) = fs::write(path, new_contents.as_bytes()) { + panic!("Cannot write to `{}`: {e}", path.display()); + } + }, + } +} + +/// Replaces a region in a text delimited by two strings. Returns the new text if both delimiters +/// were found, or the missing delimiter if not. +pub(crate) fn replace_region_in_text<'a>( + text: &str, + start: &'a str, + end: &'a str, + mut write_replacement: impl FnMut(&mut String), +) -> Result { + let (text_start, rest) = text.split_once(start).ok_or(start)?; + let (_, text_end) = rest.split_once(end).ok_or(end)?; + + let mut res = String::with_capacity(text.len() + 4096); + res.push_str(text_start); + res.push_str(start); + write_replacement(&mut res); + res.push_str(end); + res.push_str(text_end); + + Ok(res) +} From bb93c23c0854bbb8aa6a523f0b4462da0f75f6da Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 15 Nov 2024 13:53:31 +0100 Subject: [PATCH 060/330] use `TypingEnv` when no `infcx` is available the behavior of the type system not only depends on the current assumptions, but also the currentnphase of the compiler. This is mostly necessary as we need to decide whether and how to reveal opaque types. We track this via the `TypingMode`. --- clippy_lints/src/assigning_clones.rs | 2 +- clippy_lints/src/bool_assert_comparison.rs | 2 +- clippy_lints/src/dereference.rs | 9 +++++---- clippy_lints/src/drop_forget_ref.rs | 4 ++-- .../src/iter_not_returning_iterator.rs | 2 +- clippy_lints/src/iter_without_into_iter.rs | 2 +- clippy_lints/src/large_const_arrays.rs | 4 ++-- clippy_lints/src/large_futures.rs | 2 +- clippy_lints/src/large_stack_frames.rs | 4 ++-- clippy_lints/src/loops/explicit_iter_loop.rs | 12 ++++++------ clippy_lints/src/methods/needless_collect.rs | 6 +++--- .../src/methods/unnecessary_min_or_max.rs | 2 +- .../src/methods/unnecessary_to_owned.rs | 2 +- clippy_lints/src/methods/zst_offset.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 2 +- clippy_lints/src/non_copy_const.rs | 18 +++++++++--------- .../src/operators/const_comparisons.rs | 2 +- clippy_lints/src/operators/erasing_op.rs | 2 +- clippy_lints/src/operators/float_cmp.rs | 3 +-- clippy_lints/src/redundant_slicing.rs | 2 +- clippy_lints/src/returns.rs | 2 +- .../src/significant_drop_tightening.rs | 2 +- clippy_lints/src/trailing_empty_array.rs | 2 +- clippy_lints/src/transmute/eager_transmute.rs | 4 ++-- .../src/transmute/transmute_undefined_repr.rs | 6 +++--- clippy_lints/src/transmute/utils.rs | 9 +++++---- clippy_lints/src/uninhabited_references.rs | 4 ++-- clippy_utils/src/consts.rs | 12 ++++++------ clippy_utils/src/eager_or_lazy.rs | 2 +- clippy_utils/src/hir_utils.rs | 6 +++--- clippy_utils/src/lib.rs | 2 +- clippy_utils/src/qualify_min_const_fn.rs | 10 ++++++---- clippy_utils/src/ty.rs | 17 +++++++++-------- 33 files changed, 83 insertions(+), 79 deletions(-) diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 0b82c0cd04c1..00626a37ef84 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { }, _ => return, } - && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.param_env, fn_id, fn_gen_args) + && let Ok(Some(resolved_fn)) = Instance::try_resolve(cx.tcx, cx.typing_env(), fn_id, fn_gen_args) // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. diff --git a/clippy_lints/src/bool_assert_comparison.rs b/clippy_lints/src/bool_assert_comparison.rs index 7d89195eeca7..adac2f27ea8c 100644 --- a/clippy_lints/src/bool_assert_comparison.rs +++ b/clippy_lints/src/bool_assert_comparison.rs @@ -62,7 +62,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - }) .is_some_and(|assoc_item| { let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, [])); - let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); + let nty = cx.tcx.normalize_erasing_regions(cx.typing_env(), proj); nty.is_bool() }) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index b167d7f22087..f864b7a5a8af 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -17,7 +17,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -755,7 +755,8 @@ impl TyCoercionStability { DefinedTy::Hir(ty) => Self::for_hir_ty(ty), DefinedTy::Mir(ty) => Self::for_mir_ty( cx.tcx, - ty.param_env, + // FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead. + ty::TypingEnv::from_param_env(ty.param_env), cx.tcx.instantiate_bound_regions_with_erased(ty.value), for_return, ), @@ -823,12 +824,12 @@ impl TyCoercionStability { } } - fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { + fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { let ty::Ref(_, mut ty, _) = *ty.kind() else { return Self::None; }; - ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty); + ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); loop { break match *ty.kind() { ty::Ref(_, ref_ty, _) => { diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 55afdbf22e1f..617982f4da30 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { sym::mem_forget if is_copy => return, sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => return, sym::mem_drop - if !(arg_ty.needs_drop(cx.tcx, cx.param_env) + if !(arg_ty.needs_drop(cx.tcx, cx.typing_env()) || is_must_use_func_call(cx, arg) || is_must_use_ty(cx, arg_ty) || drop_is_single_call_in_arm) => @@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { (DROP_NON_DROP, DROP_NON_DROP_SUMMARY.into(), Some(arg.span)) }, sym::mem_forget => { - if arg_ty.needs_drop(cx.tcx, cx.param_env) { + if arg_ty.needs_drop(cx.tcx, cx.typing_env()) { ( MEM_FORGET, Cow::Owned(format!( diff --git a/clippy_lints/src/iter_not_returning_iterator.rs b/clippy_lints/src/iter_not_returning_iterator.rs index 25105817ad97..4bc6ad0798c9 100644 --- a/clippy_lints/src/iter_not_returning_iterator.rs +++ b/clippy_lints/src/iter_not_returning_iterator.rs @@ -70,7 +70,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(fn_id).instantiate_identity().output()); let ret_ty = cx .tcx - .try_normalize_erasing_regions(cx.param_env, ret_ty) + .try_normalize_erasing_regions(cx.typing_env(), ret_ty) .unwrap_or(ret_ty); if cx .tcx diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index 314d0dfa26ce..906da81b1837 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -215,7 +215,7 @@ impl {self_ty_without_ref} {{ && implements_trait(cx, ret_ty, iterator_did, &[]) && let Some(iter_ty) = make_normalized_projection( cx.tcx, - cx.param_env, + cx.typing_env(), iterator_did, sym::Item, [ret_ty], diff --git a/clippy_lints/src/large_const_arrays.rs b/clippy_lints/src/large_const_arrays.rs index c5a2760234fc..644365c9fe56 100644 --- a/clippy_lints/src/large_const_arrays.rs +++ b/clippy_lints/src/large_const_arrays.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, ParamEnv}; +use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Array(element_type, cst) = ty.kind() && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx - .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree() + .try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_valtree() && let element_count = element_count.to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs index 25f9be8b2d7a..593704f206a1 100644 --- a/clippy_lints/src/large_futures.rs +++ b/clippy_lints/src/large_futures.rs @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeFuture { && let ty = cx.typeck_results().expr_ty(arg) && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() && implements_trait(cx, ty, future_trait_def_id, &[]) - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) && let size = layout.layout.size() && size >= Size::from_bytes(self.future_size_threshold) { diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index d2bdf194adad..5ed948c02bbc 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -150,11 +150,11 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { } let mir = cx.tcx.optimized_mir(def_id); - let param_env = cx.tcx.param_env(def_id); + let typing_env = mir.typing_env(cx.tcx); let sizes_of_locals = || { mir.local_decls.iter().filter_map(|local| { - let layout = cx.tcx.layout_of(param_env.and(local.ty)).ok()?; + let layout = cx.tcx.layout_of(typing_env.as_query_input(local.ty)).ok()?; Some((local, layout.size.bytes())) }) }; diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index ee561ea85ed1..48318682f33c 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -151,7 +151,7 @@ fn is_ref_iterable<'tcx>( // Using by value won't consume anything if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::None, self_ty)); @@ -168,7 +168,7 @@ fn is_ref_iterable<'tcx>( }; if implements_trait(cx, self_ty, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::reborrow(mutbl), self_ty)); @@ -181,7 +181,7 @@ fn is_ref_iterable<'tcx>( // Attempt to borrow let self_ty = Ty::new_ref(cx.tcx, cx.tcx.lifetimes.re_erased, self_ty, mutbl); if implements_trait(cx, self_ty, trait_id, &[]) - && let Some(ty) = make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [self_ty]) + && let Some(ty) = make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [self_ty]) && ty == res_ty { return Some((AdjustKind::borrow(mutbl), self_ty)); @@ -204,7 +204,7 @@ fn is_ref_iterable<'tcx>( && target != self_ty && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_reborrow(mutbl), target)) @@ -222,7 +222,7 @@ fn is_ref_iterable<'tcx>( if is_copy(cx, target) && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::Deref, target)) @@ -240,7 +240,7 @@ fn is_ref_iterable<'tcx>( if self_ty.is_ref() && implements_trait(cx, target, trait_id, &[]) && let Some(ty) = - make_normalized_projection(cx.tcx, cx.param_env, trait_id, sym!(IntoIter), [target]) + make_normalized_projection(cx.tcx, cx.typing_env(), trait_id, sym!(IntoIter), [target]) && ty == res_ty { Some((AdjustKind::auto_borrow(mutbl), target)) diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 9c41528e6476..c00b9b368c43 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -203,10 +203,10 @@ fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool { fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty: Ty<'tcx>) -> bool { if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) && let Some(into_iter_trait) = cx.tcx.get_diagnostic_item(sym::IntoIterator) - && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.param_env, iter_trait, sym::Item, [iter_ty]) + && let Some(iter_item_ty) = make_normalized_projection(cx.tcx, cx.typing_env(), iter_trait, sym::Item, [iter_ty]) && let Some(into_iter_item_proj) = make_projection(cx.tcx, into_iter_trait, sym::Item, [collect_ty]) && let Ok(into_iter_item_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, + cx.typing_env(), Ty::new_projection_from_args(cx.tcx, into_iter_item_proj.def_id, into_iter_item_proj.args), ) { @@ -237,7 +237,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - ) && let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) && let proj_ty = Ty::new_projection_from_args(cx.tcx, iter_item.def_id, args) - && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty) + && let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), proj_ty) { item_ty == EarlyBinder::bind(search_ty).instantiate(cx.tcx, cx.typeck_results().node_args(call_id)) } else { diff --git a/clippy_lints/src/methods/unnecessary_min_or_max.rs b/clippy_lints/src/methods/unnecessary_min_or_max.rs index 062d1348555c..7d01bdc2269b 100644 --- a/clippy_lints/src/methods/unnecessary_min_or_max.rs +++ b/clippy_lints/src/methods/unnecessary_min_or_max.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) { let typeck_results = cx.typeck_results(); - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck_results); if let Some(id) = typeck_results.type_dependent_def_id(expr.hir_id) && (cx.tcx.is_diagnostic_item(sym::cmp_ord_min, id) || cx.tcx.is_diagnostic_item(sym::cmp_ord_max, id)) { diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 82549413fa91..84ea3554a358 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -578,7 +578,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< if output_ty.contains(param_ty) { if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, - cx.param_env, + cx.typing_env(), bound_fn_sig.rebind(output_ty), ) { expr = parent_expr; diff --git a/clippy_lints/src/methods/zst_offset.rs b/clippy_lints/src/methods/zst_offset.rs index d33021c2a7bf..102fa7bc8953 100644 --- a/clippy_lints/src/methods/zst_offset.rs +++ b/clippy_lints/src/methods/zst_offset.rs @@ -7,7 +7,7 @@ use super::ZST_OFFSET; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) { if let ty::RawPtr(ty, _) = cx.typeck_results().expr_ty(recv).kind() - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(*ty)) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(*ty)) && layout.is_zst() { span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value"); diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index c1424b9f1dc8..43b885fbd2c9 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -421,7 +421,7 @@ fn replace_types<'tcx>( .expect_ty(cx.tcx) .to_ty(cx.tcx); - if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) + if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), projection) && args[term_param_ty.index as usize] != GenericArg::from(projected_ty) { deque.push_back((*term_param_ty, projected_ty)); diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 5e20b4064260..57fa4797c5e5 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -278,23 +278,23 @@ impl<'tcx> NonCopyConst<'tcx> { fn is_value_unfrozen_expr(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool { let args = cx.typeck_results().node_args(hir_id); - let result = Self::const_eval_resolve(cx.tcx, cx.param_env, ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); + let result = Self::const_eval_resolve(cx.tcx, cx.typing_env(), ty::UnevaluatedConst::new(def_id, args), DUMMY_SP); Self::is_value_unfrozen_raw(cx, result, ty) } pub fn const_eval_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { - match ty::Instance::try_resolve(tcx, param_env, ct.def, ct.args) { + match ty::Instance::try_resolve(tcx, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None, }; - tcx.const_eval_global_id_for_typeck(param_env, cid, span) + tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) }, Ok(None) => Err(ErrorHandled::TooGeneric(span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)), @@ -321,7 +321,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound. - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); if self.interior_mut.is_interior_mut_ty(cx, normalized) // When there's no default value, lint it only according to its type; // in other words, lint consts whose value *could* be unfrozen, not definitely is. @@ -361,12 +361,12 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { .trait_item_def_id && cx .tcx - .layout_of(cx.tcx.param_env(of_trait_def_id).and( + .layout_of(ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id).as_query_input( // Normalize assoc types because ones originated from generic params // bounded other traits could have their bound at the trait defs; // and, in that case, the definition is *not* generic. cx.tcx.normalize_erasing_regions( - cx.tcx.param_env(of_trait_def_id), + ty::TypingEnv::post_analysis(cx.tcx, of_trait_def_id), cx.tcx.type_of(of_assoc_item).instantiate_identity(), ), )) @@ -376,7 +376,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { // similar to unknown layouts. // e.g. `layout_of(...).is_err() || has_frozen_variant(...);` && let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity() - && let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty) + && let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty) && self.interior_mut.is_interior_mut_ty(cx, normalized) && Self::is_value_unfrozen_poly(cx, *body_id, normalized) { @@ -386,7 +386,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { ItemKind::Impl(Impl { of_trait: None, .. }) => { let ty = cx.tcx.type_of(impl_item.owner_id).instantiate_identity(); // Normalize assoc types originated from generic params. - let normalized = cx.tcx.normalize_erasing_regions(cx.param_env, ty); + let normalized = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); if self.interior_mut.is_interior_mut_ty(cx, normalized) && Self::is_value_unfrozen_poly(cx, *body_id, normalized) diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs index 5d94cfab3b02..1a0bfd8b9970 100644 --- a/clippy_lints/src/operators/const_comparisons.rs +++ b/clippy_lints/src/operators/const_comparisons.rs @@ -26,7 +26,7 @@ fn comparison_to_const<'tcx>( if let ExprKind::Binary(operator, left, right) = expr.kind && let Ok(cmp_op) = CmpOp::try_from(operator.node) { - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), typeck); match (ecx.eval(left), ecx.eval(right)) { (Some(_), Some(_)) => None, (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))), diff --git a/clippy_lints/src/operators/erasing_op.rs b/clippy_lints/src/operators/erasing_op.rs index 24bfe2b050bb..e3fc8d8fea7d 100644 --- a/clippy_lints/src/operators/erasing_op.rs +++ b/clippy_lints/src/operators/erasing_op.rs @@ -39,7 +39,7 @@ fn check_op<'tcx>( other: &Expr<'tcx>, parent: &Expr<'tcx>, ) { - if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) { + if ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), tck).eval_simple(op) == Some(Constant::Int(0)) { if different_types(tck, other, parent) { return; } diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs index ab5f91c1d672..8272d3643d42 100644 --- a/clippy_lints/src/operators/float_cmp.rs +++ b/clippy_lints/src/operators/float_cmp.rs @@ -17,8 +17,7 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) { - let typeck = cx.typeck_results(); - let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let ecx = ConstEvalCtxt::new(cx); let left_is_local = match ecx.eval_with_source(left) { Some((c, s)) if !is_allowed(&c) => s.is_local(), Some(_) => return, diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index dc66fb28fa8c..0ac818c21d9b 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { }); } else if let Some(target_id) = cx.tcx.lang_items().deref_target() { if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions( - cx.param_env, + cx.typing_env(), Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])), ) { if deref_ty == expr_ty { diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 1e0f6dff1abe..aeff31d02d26 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -391,7 +391,7 @@ fn check_final_expr<'tcx>( if let Some(inner) = inner { if for_each_unconsumed_temporary(cx, inner, |temporary_ty| { - if temporary_ty.has_significant_drop(cx.tcx, cx.param_env) + if temporary_ty.has_significant_drop(cx.tcx, cx.typing_env()) && temporary_ty .walk() .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if !re.is_static())) diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index abd8363456df..1a5b958e6a67 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -154,7 +154,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> { let ty = self .cx .tcx - .try_normalize_erasing_regions(self.cx.param_env, ty) + .try_normalize_erasing_regions(self.cx.typing_env(), ty) .unwrap_or(ty); match self.type_cache.entry(ty) { Entry::Occupied(e) => return *e.get(), diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs index 52bb7c4bd68a..50a1577b2884 100644 --- a/clippy_lints/src/trailing_empty_array.rs +++ b/clippy_lints/src/trailing_empty_array.rs @@ -58,7 +58,7 @@ fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: && let Some(last_field) = data.fields().last() && let field_ty = cx .tcx - .normalize_erasing_regions(cx.param_env, cx.tcx.type_of(last_field.def_id).instantiate_identity()) + .normalize_erasing_regions(cx.typing_env(), cx.tcx.type_of(last_field.def_id).instantiate_identity()) && let ty::Array(_, array_len) = *field_ty.kind() && let Some(0) = array_len.try_to_target_usize(cx.tcx) { diff --git a/clippy_lints/src/transmute/eager_transmute.rs b/clippy_lints/src/transmute/eager_transmute.rs index ca9daf2d2a03..1209bd5b34f2 100644 --- a/clippy_lints/src/transmute/eager_transmute.rs +++ b/clippy_lints/src/transmute/eager_transmute.rs @@ -88,8 +88,8 @@ pub(super) fn check<'tcx>( && is_normalizable(cx, cx.param_env, to_ty) // we only want to lint if the target type has a niche that is larger than the one of the source type // e.g. `u8` to `NonZero` should lint, but `NonZero` to `u8` should not - && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty)) - && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty)) + && let Ok(from_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(from_ty)) + && let Ok(to_layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(to_ty)) && match (from_layout.largest_niche, to_layout.largest_niche) { (Some(from_niche), Some(to_niche)) => !range_fully_contained(from_niche.valid_range, to_niche.valid_range), (None, Some(_)) => true, diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index 3b32e4396b9f..4dc1290e8b15 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -244,7 +244,7 @@ enum ReducedTy<'tcx> { /// Reduce structs containing a single non-zero sized field to it's contained type. fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> { loop { - ty = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty).unwrap_or(ty); + ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); return match *ty.kind() { ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ReducedTy::TypeErasure { raw_ptr_only: false } @@ -297,8 +297,8 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> } fn is_zero_sized_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) - && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty)) + if let Ok(ty) = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) + && let Ok(layout) = cx.tcx.layout_of(cx.typing_env().as_query_input(ty)) { layout.layout.size().bytes() == 0 } else { diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs index e8ccd35b4daf..5baa67b1f3e8 100644 --- a/clippy_lints/src/transmute/utils.rs +++ b/clippy_lints/src/transmute/utils.rs @@ -4,10 +4,11 @@ use rustc_middle::ty::Ty; // check if the component types of the transmuted collection and the result have different ABI, // size or alignment pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool { - if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from) - && let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to) - && let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from)) - && let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to)) + let typing_env = cx.typing_env(); + if let Ok(from) = cx.tcx.try_normalize_erasing_regions(typing_env, from) + && let Ok(to) = cx.tcx.try_normalize_erasing_regions(typing_env, to) + && let Ok(from_layout) = cx.tcx.layout_of(typing_env.as_query_input(from)) + && let Ok(to_layout) = cx.tcx.layout_of(typing_env.as_query_input(to)) { from_layout.size != to_layout.size || from_layout.align.abi != to_layout.align.abi } else { diff --git a/clippy_lints/src/uninhabited_references.rs b/clippy_lints/src/uninhabited_references.rs index cfa565cf8037..ee9ef0172538 100644 --- a/clippy_lints/src/uninhabited_references.rs +++ b/clippy_lints/src/uninhabited_references.rs @@ -46,7 +46,7 @@ impl LateLintPass<'_> for UninhabitedReferences { if let ExprKind::Unary(UnOp::Deref, _) = expr.kind { let ty = cx.typeck_results().expr_ty_adjusted(expr); - if ty.is_privately_uninhabited(cx.tcx, cx.param_env) { + if ty.is_privately_uninhabited(cx.tcx, cx.typing_env()) { span_lint( cx, UNINHABITED_REFERENCES, @@ -71,7 +71,7 @@ impl LateLintPass<'_> for UninhabitedReferences { } if let FnRetTy::Return(hir_ty) = fndecl.output && let TyKind::Ref(_, mut_ty) = hir_ty.kind - && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.param_env) + && lower_ty(cx.tcx, mut_ty.ty).is_privately_uninhabited(cx.tcx, cx.typing_env()) { span_lint( cx, diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 24a02c7ef871..52c986462899 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -18,7 +18,7 @@ use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::{Scalar, alloc_range}; -use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; +use rustc_middle::ty::{self, FloatTy, IntTy, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; @@ -387,7 +387,7 @@ impl Ord for FullInt { /// See the module level documentation for some context. pub struct ConstEvalCtxt<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>, source: Cell, } @@ -398,17 +398,17 @@ impl<'tcx> ConstEvalCtxt<'tcx> { pub fn new(cx: &LateContext<'tcx>) -> Self { Self { tcx: cx.tcx, - param_env: cx.param_env, + typing_env: cx.typing_env(), typeck: cx.typeck_results(), source: Cell::new(ConstantSource::Local), } } /// Creates an evaluation context. - pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { + pub fn with_env(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { Self { tcx, - param_env, + typing_env, typeck, source: Cell::new(ConstantSource::Local), } @@ -643,7 +643,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { let args = self.typeck.node_args(id); let result = self .tcx - .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) + .const_eval_resolve(self.typing_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) .ok() .map(|val| mir::Const::from_value(val, ty))?; f(self, result) diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index a2e97919d042..7f0363ac9426 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -105,7 +105,7 @@ fn res_has_significant_drop(res: Res, cx: &LateContext<'_>, e: &Expr<'_>) -> boo { cx.typeck_results() .expr_ty(e) - .has_significant_drop(cx.tcx, cx.param_env) + .has_significant_drop(cx.tcx, cx.typing_env()) } else { false } diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index c73ab4bfa688..ea866a78d87f 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -297,8 +297,8 @@ impl HirEqInterExpr<'_, '_, '_> { if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results && typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right) && let (Some(l), Some(r)) = ( - ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left), - ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_lhs).eval_simple(left), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.typing_env(), typeck_rhs).eval_simple(right), ) && l == r { @@ -813,7 +813,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { #[expect(clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr<'_>) { let simple_const = self.maybe_typeck_results.and_then(|typeck_results| { - ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e) + ConstEvalCtxt::with_env(self.cx.tcx, self.cx.typing_env(), typeck_results).eval_simple(e) }); // const hashing may result in the same hash as some unrelated node, so add a sort of diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 19316a906835..f28e5c9ed0e3 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1631,7 +1631,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool } let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); if let Some(Constant::Int(v)) = - ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e) + ConstEvalCtxt::with_env(cx.tcx, cx.typing_env(), cx.tcx.typeck(enclosing_body)).eval(e) { return value == v; } diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 971f8eeb1b33..abadca714001 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -142,7 +142,7 @@ fn check_rvalue<'tcx>( // We cannot allow this for now. return Err((span, "unsizing casts are only allowed for references right now".into())); }; - let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id)); + let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, ty::TypingEnv::post_analysis(tcx, def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { check_operand(tcx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. @@ -408,15 +408,17 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> return true; } + + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx)); // FIXME(const_trait_impl) constness let obligation = Obligation::new( tcx, ObligationCause::dummy_with_span(body.span), - ConstCx::new(tcx, body).param_env, + param_env, TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]), ); - let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx)); let mut selcx = SelectionContext::new(&infcx); let Some(impl_src) = selcx.select(&obligation).ok().flatten() else { return false; @@ -434,5 +436,5 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> ocx.select_all_or_error().is_empty() } - !ty.needs_drop(tcx, ConstCx::new(tcx, body).param_env) + !ty.needs_drop(tcx, ConstCx::new(tcx, body).typing_env) } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 770cd9c37865..2aad867dc0d6 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -467,7 +467,7 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { if !seen.insert(ty) { return false; } - if !ty.has_significant_drop(cx.tcx, cx.param_env) { + if !ty.has_significant_drop(cx.tcx, cx.typing_env()) { false } // Check for std types which implement drop, but only for memory allocation. @@ -575,8 +575,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// Checks if a given type looks safe to be uninitialized. pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + let typing_env = cx.typing_env().with_reveal_all_normalized(cx.tcx); cx.tcx - .check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty))) + .check_validity_requirement((ValidityRequirement::Uninit, typing_env.as_query_input(ty))) .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty)) } @@ -725,7 +726,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option None, } }, - ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.param_env, ty) { + ty::Alias(ty::Projection, proj) => match cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty) { Ok(normalized_ty) if normalized_ty != ty => ty_sig(cx, normalized_ty), _ => sig_for_projection(cx, proj).or_else(|| sig_from_bounds(cx, ty, cx.param_env.caller_bounds(), None)), }, @@ -1111,12 +1112,12 @@ pub fn make_projection<'tcx>( /// succeeds as well as everything checked by `make_projection`. pub fn make_normalized_projection<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, container_id: DefId, assoc_ty: Symbol, args: impl IntoIterator>>, ) -> Option> { - fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] if let Some((i, arg)) = ty .args @@ -1132,7 +1133,7 @@ pub fn make_normalized_projection<'tcx>( ); return None; } - match tcx.try_normalize_erasing_regions(param_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { + match tcx.try_normalize_erasing_regions(typing_env, Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { Ok(ty) => Some(ty), Err(e) => { debug_assert!(false, "failed to normalize type `{ty}`: {e:#?}"); @@ -1140,7 +1141,7 @@ pub fn make_normalized_projection<'tcx>( }, } } - helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?) + helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?) } /// Helper to check if given type has inner mutability such as [`std::cell::Cell`] or @@ -1300,7 +1301,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl if let Some(deref_did) = cx.tcx.lang_items().deref_trait() && implements_trait(cx, ty, deref_did, &[]) { - make_normalized_projection(cx.tcx, cx.param_env, deref_did, sym::Target, [ty]) + make_normalized_projection(cx.tcx, cx.typing_env(), deref_did, sym::Target, [ty]) } else { None } From d8423ca28c0285edf6b02d883e0f7e27b62a3b90 Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Mon, 18 Nov 2024 14:03:16 +0000 Subject: [PATCH 061/330] `missing_safety_doc` accept capitalized "SAFETY" --- clippy_lints/src/doc/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index df7c37a192ad..a7041b3b649d 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -917,6 +917,7 @@ fn check_doc<'a, Events: Iterator, Range Date: Mon, 18 Nov 2024 16:31:10 +0000 Subject: [PATCH 062/330] Remove extern vectorcall tests --- .../missing_const_for_fn/could_be_const.fixed | 6 +---- .../ui/missing_const_for_fn/could_be_const.rs | 6 +---- .../could_be_const.stderr | 24 +------------------ 3 files changed, 3 insertions(+), 33 deletions(-) diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed index 754fe061c4ae..014fbb85c7a3 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -1,6 +1,6 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] -#![feature(const_trait_impl, abi_vectorcall)] +#![feature(const_trait_impl)] use std::mem::transmute; @@ -211,8 +211,4 @@ mod extern_fn { //~^ ERROR: this could be a `const fn` const extern "system-unwind" fn system_unwind() {} //~^ ERROR: this could be a `const fn` - pub const extern "vectorcall" fn std_call() {} - //~^ ERROR: this could be a `const fn` - pub const extern "vectorcall-unwind" fn std_call_unwind() {} - //~^ ERROR: this could be a `const fn` } diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 460be0733e03..4f7c2cbcf0b4 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -1,6 +1,6 @@ #![warn(clippy::missing_const_for_fn)] #![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)] -#![feature(const_trait_impl, abi_vectorcall)] +#![feature(const_trait_impl)] use std::mem::transmute; @@ -211,8 +211,4 @@ mod extern_fn { //~^ ERROR: this could be a `const fn` extern "system-unwind" fn system_unwind() {} //~^ ERROR: this could be a `const fn` - pub extern "vectorcall" fn std_call() {} - //~^ ERROR: this could be a `const fn` - pub extern "vectorcall-unwind" fn std_call_unwind() {} - //~^ ERROR: this could be a `const fn` } diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index d553c5225565..cc7dfd0888d0 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -316,27 +316,5 @@ help: make the function `const` LL | const extern "system-unwind" fn system_unwind() {} | +++++ -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:214:5 - | -LL | pub extern "vectorcall" fn std_call() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | pub const extern "vectorcall" fn std_call() {} - | +++++ - -error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/could_be_const.rs:216:5 - | -LL | pub extern "vectorcall-unwind" fn std_call_unwind() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function `const` - | -LL | pub const extern "vectorcall-unwind" fn std_call_unwind() {} - | +++++ - -error: aborting due to 26 previous errors +error: aborting due to 24 previous errors From b4a31683c1e9c0b624c4c5341708e9dd1b8698b9 Mon Sep 17 00:00:00 2001 From: David Richey Date: Thu, 14 Nov 2024 12:12:43 -0600 Subject: [PATCH 063/330] Re-add rust-analyzer.cargo.sysrootQueryMetadata --- .../project-model/src/cargo_workspace.rs | 4 +- .../crates/project-model/src/lib.rs | 7 +++ .../crates/project-model/src/sysroot.rs | 55 ++++++++++++----- .../crates/project-model/src/tests.rs | 6 +- .../crates/project-model/src/workspace.rs | 61 ++++++++++--------- .../rust-analyzer/src/cli/analysis_stats.rs | 4 ++ .../crates/rust-analyzer/src/cli/flags.rs | 4 ++ .../rust-analyzer/src/cli/rustc_tests.rs | 8 ++- .../crates/rust-analyzer/src/config.rs | 24 ++++++++ .../crates/rust-analyzer/src/reload.rs | 4 +- .../docs/user/generated_config.adoc | 6 ++ .../rust-analyzer/editors/code/package.json | 18 ++++++ 12 files changed, 150 insertions(+), 51 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 2dc6f0357e3d..cb5738a3b409 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -13,7 +13,7 @@ use serde_json::from_value; use span::Edition; use toolchain::Tool; -use crate::{utf8_stdout, ManifestPath, Sysroot}; +use crate::{utf8_stdout, ManifestPath, Sysroot, SysrootQueryMetadata}; use crate::{CfgOverrides, InvocationStrategy}; /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo @@ -85,6 +85,8 @@ pub struct CargoConfig { pub target: Option, /// Sysroot loading behavior pub sysroot: Option, + /// How to query metadata for the sysroot crate. + pub sysroot_query_metadata: SysrootQueryMetadata, pub sysroot_src: Option, /// rustc private crate source pub rustc_source: Option, diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index 91bdef4889ca..da8afc5d3a18 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -240,3 +240,10 @@ fn parse_cfg(s: &str) -> Result { }; Ok(res) } + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub enum SysrootQueryMetadata { + #[default] + CargoMetadata, + None, +} diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 19f4c35b5add..8df49608c070 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -14,7 +14,7 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf}; use rustc_hash::FxHashMap; use toolchain::{probe_for_binary, Tool}; -use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath}; +use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, SysrootQueryMetadata}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Sysroot { @@ -123,27 +123,43 @@ impl Sysroot { // FIXME: Expose a builder api as loading the sysroot got way too modular and complicated. impl Sysroot { /// Attempts to discover the toolchain's sysroot from the given `dir`. - pub fn discover(dir: &AbsPath, extra_env: &FxHashMap) -> Sysroot { + pub fn discover( + dir: &AbsPath, + extra_env: &FxHashMap, + sysroot_query_metadata: SysrootQueryMetadata, + ) -> Sysroot { let sysroot_dir = discover_sysroot_dir(dir, extra_env); let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| { discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env) }); - Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir) + Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, sysroot_query_metadata) } pub fn discover_with_src_override( current_dir: &AbsPath, extra_env: &FxHashMap, sysroot_src_dir: AbsPathBuf, + sysroot_query_metadata: SysrootQueryMetadata, ) -> Sysroot { let sysroot_dir = discover_sysroot_dir(current_dir, extra_env); - Sysroot::load_core_check(Some(sysroot_dir), Some(Ok(sysroot_src_dir))) + Sysroot::load_core_check( + Some(sysroot_dir), + Some(Ok(sysroot_src_dir)), + sysroot_query_metadata, + ) } - pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot { + pub fn discover_sysroot_src_dir( + sysroot_dir: AbsPathBuf, + sysroot_query_metadata: SysrootQueryMetadata, + ) -> Sysroot { let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir) .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}")); - Sysroot::load_core_check(Some(Ok(sysroot_dir)), Some(sysroot_src_dir)) + Sysroot::load_core_check( + Some(Ok(sysroot_dir)), + Some(sysroot_src_dir), + sysroot_query_metadata, + ) } pub fn discover_rustc_src(&self) -> Option { @@ -186,15 +202,20 @@ impl Sysroot { }) } - pub fn load(sysroot_dir: Option, sysroot_src_dir: Option) -> Sysroot { - Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok)) + pub fn load( + sysroot_dir: Option, + sysroot_src_dir: Option, + sysroot_query_metadata: SysrootQueryMetadata, + ) -> Sysroot { + Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), sysroot_query_metadata) } fn load_core_check( sysroot_dir: Option>, sysroot_src_dir: Option>, + sysroot_query_metadata: SysrootQueryMetadata, ) -> Sysroot { - let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir); + let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, sysroot_query_metadata); if sysroot.error.is_none() { if let Some(src_root) = &sysroot.src_root { let has_core = match &sysroot.mode { @@ -220,6 +241,7 @@ impl Sysroot { fn load_( sysroot_dir: Option>, sysroot_src_dir: Option>, + sysroot_query_metadata: SysrootQueryMetadata, ) -> Sysroot { let sysroot_dir = match sysroot_dir { Some(Ok(sysroot_dir)) => Some(sysroot_dir), @@ -252,12 +274,15 @@ impl Sysroot { } } }; - let library_manifest = ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap(); - if fs::metadata(&library_manifest).is_ok() { - if let Some(sysroot) = - Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir) - { - return sysroot; + if sysroot_query_metadata == SysrootQueryMetadata::CargoMetadata { + let library_manifest = + ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap(); + if fs::metadata(&library_manifest).is_ok() { + if let Some(sysroot) = + Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir) + { + return sysroot; + } } } tracing::debug!("Stitching sysroot library: {sysroot_src_dir}"); diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index ef115494a888..f3cf2d83eaca 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -13,7 +13,8 @@ use triomphe::Arc; use crate::{ sysroot::SysrootMode, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides, - ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, WorkspaceBuildScripts, + ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, SysrootQueryMetadata, + WorkspaceBuildScripts, }; fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { @@ -116,7 +117,7 @@ fn get_fake_sysroot() -> Sysroot { // fake sysroot, so we give them both the same path: let sysroot_dir = AbsPathBuf::assert(sysroot_path); let sysroot_src_dir = sysroot_dir.clone(); - Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir)) + Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), SysrootQueryMetadata::CargoMetadata) } fn rooted_project_json(data: ProjectJsonData) -> ProjectJson { @@ -231,6 +232,7 @@ fn smoke_test_real_sysroot_cargo() { let sysroot = Sysroot::discover( AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))), &Default::default(), + SysrootQueryMetadata::CargoMetadata, ); assert!(matches!(sysroot.mode(), SysrootMode::Workspace(_))); let project_workspace = ProjectWorkspace { diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index d53639e24232..f5ba71fcd05f 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -211,34 +211,35 @@ impl ProjectWorkspace { let project_location = project_json.parent().to_path_buf(); let project_json: ProjectJson = ProjectJson::new(Some(project_json.clone()), &project_location, data); - ProjectWorkspace::load_inline( - project_json, - config.target.as_deref(), - &config.extra_env, - &config.cfg_overrides, - ) + ProjectWorkspace::load_inline(project_json, config) } ProjectManifest::CargoScript(rust_file) => { ProjectWorkspace::load_detached_file(rust_file, config)? } ProjectManifest::CargoToml(cargo_toml) => { let sysroot = match (&config.sysroot, &config.sysroot_src) { - (Some(RustLibSource::Discover), None) => { - Sysroot::discover(cargo_toml.parent(), &config.extra_env) - } + (Some(RustLibSource::Discover), None) => Sysroot::discover( + cargo_toml.parent(), + &config.extra_env, + config.sysroot_query_metadata, + ), (Some(RustLibSource::Discover), Some(sysroot_src)) => { Sysroot::discover_with_src_override( cargo_toml.parent(), &config.extra_env, sysroot_src.clone(), + config.sysroot_query_metadata, ) } - (Some(RustLibSource::Path(path)), None) => { - Sysroot::discover_sysroot_src_dir(path.clone()) - } - (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => { - Sysroot::load(Some(sysroot.clone()), Some(sysroot_src.clone())) - } + (Some(RustLibSource::Path(path)), None) => Sysroot::discover_sysroot_src_dir( + path.clone(), + config.sysroot_query_metadata, + ), + (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => Sysroot::load( + Some(sysroot.clone()), + Some(sysroot_src.clone()), + config.sysroot_query_metadata, + ), (None, _) => Sysroot::empty(), }; tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot"); @@ -352,20 +353,19 @@ impl ProjectWorkspace { Ok(res) } - pub fn load_inline( - project_json: ProjectJson, - target: Option<&str>, - extra_env: &FxHashMap, - cfg_overrides: &CfgOverrides, - ) -> ProjectWorkspace { - let sysroot = Sysroot::load(project_json.sysroot.clone(), project_json.sysroot_src.clone()); + pub fn load_inline(project_json: ProjectJson, config: &CargoConfig) -> ProjectWorkspace { + let sysroot = Sysroot::load( + project_json.sysroot.clone(), + project_json.sysroot_src.clone(), + config.sysroot_query_metadata, + ); let cfg_config = RustcCfgConfig::Rustc(&sysroot); let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot); let toolchain = match get_toolchain_version( project_json.path(), &sysroot, Tool::Rustc, - extra_env, + &config.extra_env, "rustc ", ) { Ok(it) => it, @@ -375,15 +375,16 @@ impl ProjectWorkspace { } }; - let rustc_cfg = rustc_cfg::get(target, extra_env, cfg_config); - let data_layout = target_data_layout::get(data_layout_config, target, extra_env); + let target = config.target.as_deref(); + let rustc_cfg = rustc_cfg::get(target, &config.extra_env, cfg_config); + let data_layout = target_data_layout::get(data_layout_config, target, &config.extra_env); ProjectWorkspace { kind: ProjectWorkspaceKind::Json(project_json), sysroot, rustc_cfg, toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), - cfg_overrides: cfg_overrides.clone(), + cfg_overrides: config.cfg_overrides.clone(), } } @@ -393,8 +394,12 @@ impl ProjectWorkspace { ) -> anyhow::Result { let dir = detached_file.parent(); let sysroot = match &config.sysroot { - Some(RustLibSource::Path(path)) => Sysroot::discover_sysroot_src_dir(path.clone()), - Some(RustLibSource::Discover) => Sysroot::discover(dir, &config.extra_env), + Some(RustLibSource::Path(path)) => { + Sysroot::discover_sysroot_src_dir(path.clone(), config.sysroot_query_metadata) + } + Some(RustLibSource::Discover) => { + Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata) + } None => Sysroot::empty(), }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 155fb6f7c88c..802d0c69a47a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -65,6 +65,10 @@ impl flags::AnalysisStats { true => None, false => Some(RustLibSource::Discover), }, + sysroot_query_metadata: match self.no_query_sysroot_metadata { + true => project_model::SysrootQueryMetadata::None, + false => project_model::SysrootQueryMetadata::CargoMetadata, + }, all_targets: true, set_test: !self.no_test, cfg_overrides: CfgOverrides { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index ff24602144a9..920a2a37efb6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -71,6 +71,9 @@ xflags::xflags! { optional --with-deps /// Don't load sysroot crates (`std`, `core` & friends). optional --no-sysroot + /// Don't run cargo metadata on the sysroot to analyze its third-party dependencies. + /// Requires --no-sysroot to not be set. + optional --no-query-sysroot-metadata /// Don't set #[cfg(test)]. optional --no-test @@ -235,6 +238,7 @@ pub struct AnalysisStats { pub only: Option, pub with_deps: bool, pub no_sysroot: bool, + pub no_query_sysroot_metadata: bool, pub no_test: bool, pub disable_build_scripts: bool, pub disable_proc_macros: bool, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 30378db0b388..6483afc85b21 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -13,7 +13,7 @@ use profile::StopWatch; use project_model::target_data_layout::RustcDataLayoutConfig; use project_model::{ target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, - RustLibSource, Sysroot, + RustLibSource, Sysroot, SysrootQueryMetadata, }; use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice}; @@ -74,7 +74,11 @@ impl Tester { ..Default::default() }; - let sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env); + let sysroot = Sysroot::discover( + tmp_file.parent().unwrap(), + &cargo_config.extra_env, + SysrootQueryMetadata::CargoMetadata, + ); let data_layout = target_data_layout::get( RustcDataLayoutConfig::Rustc(&sysroot), None, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index f5b0fcecf390..37d45255e29d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -558,6 +558,9 @@ config_data! { /// /// This option does not take effect until rust-analyzer is restarted. cargo_sysroot: Option = Some("discover".to_owned()), + /// How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer + /// to analyze third-party dependencies of the standard libraries. + cargo_sysrootQueryMetadata: SysrootQueryMetadata = SysrootQueryMetadata::CargoMetadata, /// Relative path to the sysroot library sources. If left unset, this will default to /// `{cargo.sysroot}/lib/rustlib/src/rust/library`. /// @@ -1868,6 +1871,12 @@ impl Config { }, target: self.cargo_target(source_root).clone(), sysroot, + sysroot_query_metadata: match self.cargo_sysrootQueryMetadata(None) { + SysrootQueryMetadata::CargoMetadata => { + project_model::SysrootQueryMetadata::CargoMetadata + } + SysrootQueryMetadata::None => project_model::SysrootQueryMetadata::None, + }, sysroot_src, rustc_source, cfg_overrides: project_model::CfgOverrides { @@ -2559,6 +2568,13 @@ pub enum NumThreads { Concrete(usize), } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum SysrootQueryMetadata { + CargoMetadata, + None, +} + macro_rules! _default_val { (@verbatim: $s:literal, $ty:ty) => {{ let default_: $ty = serde_json::from_str(&$s).unwrap(); @@ -3410,6 +3426,14 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json } ] }, + "SysrootQueryMetadata" => set! { + "type": "string", + "enum": ["none", "cargo_metadata"], + "enumDescriptions": [ + "Do not query sysroot metadata, always use stitched sysroot.", + "Use `cargo metadata` to query sysroot metadata." + ], + }, _ => panic!("missing entry for {ty}: {default} (field {field})"), } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 0b24833358dd..bc85afa0e494 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -316,9 +316,7 @@ impl GlobalState { LinkedProject::InlineJsonProject(it) => { let workspace = project_model::ProjectWorkspace::load_inline( it.clone(), - cargo_config.target.as_deref(), - &cargo_config.extra_env, - &cargo_config.cfg_overrides, + &cargo_config, ); Ok(workspace) } diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 463718835b91..052d0a2a41d0 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -135,6 +135,12 @@ Unsetting this disables sysroot loading. This option does not take effect until rust-analyzer is restarted. -- +[[rust-analyzer.cargo.sysrootQueryMetadata]]rust-analyzer.cargo.sysrootQueryMetadata (default: `"cargo_metadata"`):: ++ +-- +How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer +to analyze third-party dependencies of the standard libraries. +-- [[rust-analyzer.cargo.sysrootSrc]]rust-analyzer.cargo.sysrootSrc (default: `null`):: + -- diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index b868622b3a52..82c43b76fdd5 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -816,6 +816,24 @@ } } }, + { + "title": "cargo", + "properties": { + "rust-analyzer.cargo.sysrootQueryMetadata": { + "markdownDescription": "How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer\nto analyze third-party dependencies of the standard libraries.", + "default": "cargo_metadata", + "type": "string", + "enum": [ + "none", + "cargo_metadata" + ], + "enumDescriptions": [ + "Do not query sysroot metadata, always use stitched sysroot.", + "Use `cargo metadata` to query sysroot metadata." + ] + } + } + }, { "title": "cargo", "properties": { From eaec0cab7e302263e8791c2724c6f399ddb31ad1 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Mon, 21 Oct 2024 20:37:19 -0400 Subject: [PATCH 064/330] Fix 13578 (#13583) changelog: don't consider lifetimes in bounded types unused (fix `extra_unused_lifetimes` FP #13578) --- clippy_lints/src/lifetimes.rs | 56 +++++++++++++++++++++++++----- tests/ui/extra_unused_lifetimes.rs | 7 ++++ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index ce0e1a24a7b5..bf898d0800ba 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::trait_ref_of_method; use itertools::Itertools; +use rustc_ast::visit::{try_visit, walk_list}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; @@ -11,8 +12,8 @@ use rustc_hir::intravisit::{ }; use rustc_hir::{ BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, - Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, - PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items, + HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, + PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, lang_items, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -483,6 +484,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ struct Usage { lifetime: Lifetime, in_where_predicate: bool, + in_bounded_ty: bool, in_generics_arg: bool, } @@ -490,11 +492,15 @@ struct LifetimeChecker<'cx, 'tcx, F> { cx: &'cx LateContext<'tcx>, map: FxIndexMap>, where_predicate_depth: usize, + bounded_ty_depth: usize, generic_args_depth: usize, phantom: std::marker::PhantomData, } -impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> { +impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> +where + F: NestedFilter<'tcx>, +{ fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> { let map = generics .params @@ -510,10 +516,30 @@ impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> { cx, map, where_predicate_depth: 0, + bounded_ty_depth: 0, generic_args_depth: 0, phantom: std::marker::PhantomData, } } + + // `visit_where_bound_predicate` is based on: + // https://github.com/rust-lang/rust/blob/864cee3ea383cc8254ba394ba355e648faa9cfa5/compiler/rustc_hir/src/intravisit.rs#L936-L939 + fn visit_where_bound_predicate( + &mut self, + hir_id: HirId, + bounded_ty: &'tcx Ty<'tcx>, + bounds: &'tcx [GenericBound<'tcx>], + bound_generic_params: &'tcx [GenericParam<'tcx>], + ) { + try_visit!(self.visit_id(hir_id)); + + self.bounded_ty_depth += 1; + try_visit!(self.visit_ty(bounded_ty)); + self.bounded_ty_depth -= 1; + + walk_list!(self, visit_param_bound, bounds); + walk_list!(self, visit_generic_param, bound_generic_params); + } } impl<'tcx, F> Visitor<'tcx> for LifetimeChecker<'_, 'tcx, F> @@ -531,6 +557,7 @@ where usages.push(Usage { lifetime: *lifetime, in_where_predicate: self.where_predicate_depth != 0, + in_bounded_ty: self.bounded_ty_depth != 0, in_generics_arg: self.generic_args_depth != 0, }); } @@ -538,7 +565,19 @@ where fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) { self.where_predicate_depth += 1; - walk_where_predicate(self, predicate); + if let &WherePredicate::BoundPredicate(WhereBoundPredicate { + hir_id, + bounded_ty, + bounds, + bound_generic_params, + origin: _, + span: _, + }) = predicate + { + self.visit_where_bound_predicate(hir_id, bounded_ty, bounds, bound_generic_params); + } else { + walk_where_predicate(self, predicate); + } self.where_predicate_depth -= 1; } @@ -562,7 +601,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, for (def_id, usages) in checker.map { if usages .iter() - .all(|usage| usage.in_where_predicate && !usage.in_generics_arg) + .all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg) { span_lint( cx, @@ -589,7 +628,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' for (&def_id, usages) in &checker.map { if usages .iter() - .all(|usage| usage.in_where_predicate && !usage.in_generics_arg) + .all(|usage| usage.in_where_predicate && !usage.in_bounded_ty && !usage.in_generics_arg) { span_lint( cx, @@ -605,8 +644,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' // An `impl` lifetime is elidable if it satisfies the following conditions: // - It is used exactly once. -// - That single use is not in `GenericArgs` in a `WherePredicate`. (Note that `GenericArgs` are -// different from `GenericParam`s.) +// - That single use is not in a bounded type or `GenericArgs` in a `WherePredicate`. (Note that +// `GenericArgs` are different from `GenericParam`s.) fn report_elidable_impl_lifetimes<'tcx>( cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>, @@ -623,6 +662,7 @@ fn report_elidable_impl_lifetimes<'tcx>( } | Usage { lifetime, + in_bounded_ty: false, in_generics_arg: false, .. }, diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index 17d2ed9f50cf..aa964af3fc2d 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -134,4 +134,11 @@ struct Human<'a> { pub name: &'a str, } +// https://github.com/rust-lang/rust-clippy/issues/13578 +mod issue_13578 { + pub trait Foo {} + + impl<'a, T: 'a> Foo for Option where &'a T: Foo {} +} + fn main() {} From effe9ac712da3ae7488c5b7f1211d2f2609a22d7 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Mon, 18 Nov 2024 23:07:19 +0100 Subject: [PATCH 065/330] improve selection handling for `merge_match_arms` --- .../crates/ide-assists/src/assist_context.rs | 3 + .../src/handlers/merge_match_arms.rs | 101 +++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index 1d2d3350f7c7..0146369f298b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -116,6 +116,9 @@ impl<'a> AssistContext<'a> { pub(crate) fn find_node_at_offset(&self) -> Option { find_node_at_offset(self.source_file.syntax(), self.offset()) } + pub(crate) fn find_node_at_trimmed_offset(&self) -> Option { + find_node_at_offset(self.source_file.syntax(), self.trimmed_range.start()) + } pub(crate) fn find_node_at_range(&self) -> Option { find_node_at_range(self.source_file.syntax(), self.trimmed_range) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index 4608e9494bca..f83de931eaba 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -34,7 +34,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; // } // ``` pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let current_arm = ctx.find_node_at_offset::()?; + let current_arm = ctx.find_node_at_trimmed_offset::()?; // Don't try to handle arms with guards for now - can add support for this later if current_arm.guard().is_some() { return None; @@ -42,12 +42,21 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let current_expr = current_arm.expr()?; let current_text_range = current_arm.syntax().text_range(); let current_arm_types = get_arm_types(ctx, ¤t_arm); + let multi_arm_selection = !ctx.has_empty_selection() + && ctx.selection_trimmed().end() > current_arm.syntax().text_range().end(); // We check if the following match arms match this one. We could, but don't, // compare to the previous match arm as well. let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next)) .take_while(|arm| match arm.expr() { Some(expr) if arm.guard().is_none() => { + // don't include match arms that start after our selection + if multi_arm_selection + && arm.syntax().text_range().start() >= ctx.selection_trimmed().end() + { + return false; + } + let same_text = expr.syntax().text() == current_expr.syntax().text(); if !same_text { return false; @@ -298,6 +307,96 @@ fn main() { ) } + #[test] + fn merge_match_arms_selection_has_leading_whitespace() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + $0 X::A => 0, + X::B => 0,$0 + X::C => 1, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 1, + } +} +"#, + ); + } + + #[test] + fn merge_match_arms_stops_at_end_of_selection() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + $0 X::A => 0, + X::B => 0, + $0X::C => 0, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 0, + } +} +"#, + ); + } + + #[test] + fn merge_match_arms_works_despite_accidental_selection() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::$0A$0 => 0, + X::B => 0, + X::C => 1, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 1, + } +} +"#, + ); + } + #[test] fn merge_match_arms_rejects_guards() { check_assist_not_applicable( From 66715532ab313f506f77897567b5ad823f7c4266 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 15 Nov 2024 21:06:17 +0100 Subject: [PATCH 066/330] Add `cargo dev sync` subcommand Currently this only provides the feature to auto-update the nightly version in the `rust-toolchain` file and the `clippy_utils/README.md` file. The actual sync to and from the Rust repo will be added with the move to Josh. --- clippy_dev/Cargo.toml | 1 + clippy_dev/src/lib.rs | 1 + clippy_dev/src/main.rs | 20 +++++++++++++++++++- clippy_dev/src/sync.rs | 33 +++++++++++++++++++++++++++++++++ rust-toolchain | 2 ++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 clippy_dev/src/sync.rs diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 952a8711fb4e..d3a103eaf4c6 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] aho-corasick = "1.0" +chrono = { version = "0.4.38", default-features = false, features = ["clock"] } clap = { version = "4.4", features = ["derive"] } indoc = "1.0" itertools = "0.12" diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index d96b79ec26c9..6505b33d3452 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -20,5 +20,6 @@ pub mod lint; pub mod new_lint; pub mod serve; pub mod setup; +pub mod sync; pub mod update_lints; pub mod utils; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index f5055b429125..541ce50b6e05 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{Args, Parser, Subcommand}; -use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints, utils}; +use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, sync, update_lints, utils}; use std::convert::Infallible; fn main() { @@ -75,6 +75,9 @@ fn main() { uplift, } => update_lints::rename(&old_name, new_name.as_ref().unwrap_or(&old_name), uplift), DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, &reason), + DevCommand::Sync(SyncCommand { subcommand }) => match subcommand { + SyncSubcommand::UpdateNightly => sync::update_nightly(), + }, } } @@ -225,6 +228,8 @@ enum DevCommand { /// The reason for deprecation reason: String, }, + /// Sync between the rust repo and the Clippy repo + Sync(SyncCommand), } #[derive(Args)] @@ -291,3 +296,16 @@ enum RemoveSubcommand { /// Remove the tasks added with 'cargo dev setup vscode-tasks' VscodeTasks, } + +#[derive(Args)] +struct SyncCommand { + #[command(subcommand)] + subcommand: SyncSubcommand, +} + +#[derive(Subcommand)] +enum SyncSubcommand { + #[command(name = "update_nightly")] + /// Update nightly version in rust-toolchain and `clippy_utils` + UpdateNightly, +} diff --git a/clippy_dev/src/sync.rs b/clippy_dev/src/sync.rs new file mode 100644 index 000000000000..3522d182e90a --- /dev/null +++ b/clippy_dev/src/sync.rs @@ -0,0 +1,33 @@ +use std::fmt::Write; +use std::path::Path; + +use chrono::offset::Utc; + +use crate::utils::{UpdateMode, replace_region_in_file}; + +pub fn update_nightly() { + // Update rust-toolchain nightly version + let date = Utc::now().format("%Y-%m-%d").to_string(); + replace_region_in_file( + UpdateMode::Change, + Path::new("rust-toolchain"), + "# begin autogenerated nightly\n", + "# end autogenerated nightly", + |res| { + writeln!(res, "channel = \"nightly-{date}\"").unwrap(); + }, + ); + + // Update clippy_utils nightly version + replace_region_in_file( + UpdateMode::Change, + Path::new("clippy_utils/README.md"), + "\n", + "", + |res| { + writeln!(res, "```").unwrap(); + writeln!(res, "nightly-{date}").unwrap(); + writeln!(res, "```").unwrap(); + }, + ); +} diff --git a/rust-toolchain b/rust-toolchain index e32e0cb36047..0a2e9d89b6e8 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,6 @@ [toolchain] +# begin autogenerated nightly channel = "nightly-2024-11-14" +# end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" From 93d5ccdba7ce49525a43fd0c05b707aedbf8aa12 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Fri, 15 Nov 2024 21:12:30 +0100 Subject: [PATCH 067/330] Add `cargo dev release` subcommand Currently this only provides the feature to auto-update the versions in the `Cargo.toml` files. With the move to Josh, a command to get beta and stable release commits will be added. --- Cargo.toml | 2 ++ clippy_config/Cargo.toml | 2 ++ clippy_dev/src/lib.rs | 1 + clippy_dev/src/main.rs | 20 +++++++++++++++++++- clippy_dev/src/release.rs | 27 +++++++++++++++++++++++++++ clippy_lints/Cargo.toml | 2 ++ clippy_utils/Cargo.toml | 2 ++ 7 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 clippy_dev/src/release.rs diff --git a/Cargo.toml b/Cargo.toml index ee9c57ab8350..79b9af7b0bf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy" +# begin autogenerated version version = "0.1.84" +# end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index 0cd0cabc3a6e..d1158b48e921 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy_config" +# begin autogenerated version version = "0.1.84" +# end autogenerated version edition = "2021" publish = false diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 6505b33d3452..9280369c23b8 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -18,6 +18,7 @@ pub mod dogfood; pub mod fmt; pub mod lint; pub mod new_lint; +pub mod release; pub mod serve; pub mod setup; pub mod sync; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 541ce50b6e05..56ed60256f16 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, unused_lifetimes)] use clap::{Args, Parser, Subcommand}; -use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, sync, update_lints, utils}; +use clippy_dev::{dogfood, fmt, lint, new_lint, release, serve, setup, sync, update_lints, utils}; use std::convert::Infallible; fn main() { @@ -78,6 +78,9 @@ fn main() { DevCommand::Sync(SyncCommand { subcommand }) => match subcommand { SyncSubcommand::UpdateNightly => sync::update_nightly(), }, + DevCommand::Release(ReleaseCommand { subcommand }) => match subcommand { + ReleaseSubcommand::BumpVersion => release::bump_version(), + }, } } @@ -230,6 +233,8 @@ enum DevCommand { }, /// Sync between the rust repo and the Clippy repo Sync(SyncCommand), + /// Manage Clippy releases + Release(ReleaseCommand), } #[derive(Args)] @@ -309,3 +314,16 @@ enum SyncSubcommand { /// Update nightly version in rust-toolchain and `clippy_utils` UpdateNightly, } + +#[derive(Args)] +struct ReleaseCommand { + #[command(subcommand)] + subcommand: ReleaseSubcommand, +} + +#[derive(Subcommand)] +enum ReleaseSubcommand { + #[command(name = "bump_version")] + /// Bump the version in the Cargo.toml files + BumpVersion, +} diff --git a/clippy_dev/src/release.rs b/clippy_dev/src/release.rs new file mode 100644 index 000000000000..ac7551687010 --- /dev/null +++ b/clippy_dev/src/release.rs @@ -0,0 +1,27 @@ +use std::fmt::Write; +use std::path::Path; + +use crate::utils::{UpdateMode, clippy_version, replace_region_in_file}; + +const CARGO_TOML_FILES: [&str; 4] = [ + "clippy_config/Cargo.toml", + "clippy_lints/Cargo.toml", + "clippy_utils/Cargo.toml", + "Cargo.toml", +]; + +pub fn bump_version() { + let (minor, mut patch) = clippy_version(); + patch += 1; + for file in &CARGO_TOML_FILES { + replace_region_in_file( + UpdateMode::Change, + Path::new(file), + "# begin autogenerated version\n", + "# end autogenerated version", + |res| { + writeln!(res, "version = \"0.{minor}.{patch}\"").unwrap(); + }, + ); + } +} diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 63ea6faf60db..be99dcc2c7c5 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy_lints" +# begin autogenerated version version = "0.1.84" +# end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index fb2acf700ab3..4f95889a53a7 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,8 @@ [package] name = "clippy_utils" +# begin autogenerated version version = "0.1.84" +# end autogenerated version edition = "2021" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" From 809b420e16d462e925399be8c7289fb18bac8689 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 19 Nov 2024 16:13:55 +0100 Subject: [PATCH 068/330] move `fn is_item_raw` to `TypingEnv` --- clippy_lints/src/casts/ptr_as_ptr.rs | 2 +- clippy_lints/src/dereference.rs | 2 +- clippy_lints/src/functions/must_use.rs | 2 +- clippy_lints/src/let_if_seq.rs | 2 +- clippy_lints/src/methods/manual_inspect.rs | 6 +++--- clippy_lints/src/mut_mut.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/transmute/transmute_ptr_to_ptr.rs | 2 +- clippy_lints/src/transmute/transmute_undefined_repr.rs | 4 ++-- clippy_lints/src/types/redundant_allocation.rs | 2 +- clippy_lints/src/types/vec_box.rs | 2 +- clippy_lints/src/unnecessary_box_returns.rs | 2 +- clippy_utils/src/ty.rs | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index 86c5f6b9f0ba..46d67e615c73 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -39,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut)) // The `U` in `pointer::cast` have to be `Sized` // as explained here: https://github.com/rust-lang/rust/issues/60602. - && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) { let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index f864b7a5a8af..9049739dddb4 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1028,7 +1028,7 @@ fn report<'tcx>( State::ExplicitDeref { mutability } => { if is_block_like(expr) && let ty::Ref(_, ty, _) = data.adjusted_ty.kind() - && ty.is_sized(cx.tcx, cx.param_env) + && ty.is_sized(cx.tcx, cx.typing_env()) { // Rustc bug: auto deref doesn't work on block expression when targeting sized types. return; diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index c74ba088b78e..175d92d2d790 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -198,7 +198,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(adt, args) => { - tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) + tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.typing_env()) || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc)) && args.types().any(|ty| is_mutable_ty(cx, ty, tys)) }, diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 0e488cee6b74..5db28e9ae9b8 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let has_interior_mutability = !cx .typeck_results() .node_type(canonical_id) - .is_freeze(cx.tcx, cx.param_env); + .is_freeze(cx.tcx, cx.typing_env()); if has_interior_mutability { return; } diff --git a/clippy_lints/src/methods/manual_inspect.rs b/clippy_lints/src/methods/manual_inspect.rs index 223b0630bfd4..7aa13d8d5b6e 100644 --- a/clippy_lints/src/methods/manual_inspect.rs +++ b/clippy_lints/src/methods/manual_inspect.rs @@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: _ => {}, } } - requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); break; } }, @@ -158,9 +158,9 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: } if can_lint - && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)) + && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())) // This case could be handled, but a fair bit of care would need to be taken. - && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.param_env)) + && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { if requires_deref { edits.push((param.span.shrink_to_lo(), "&".into())); diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 6cddd7ea813b..e2ab5e98504a 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -80,7 +80,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> { "generally you want to avoid `&mut &mut _` if possible", ); } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() { - if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) { + if ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) { span_lint_hir( self.cx, MUT_MUT, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 0775d7abdbb3..ad0ab1485302 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -180,7 +180,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !is_self(arg) && !ty.is_mutable_ptr() && !is_copy(cx, ty) - && ty.is_sized(cx.tcx, cx.param_env) + && ty.is_sized(cx.tcx, cx.typing_env()) && !allowed_traits.iter().any(|&t| { implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::< ty::GenericArg<'tcx>, diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index a00fd01a62e0..f69cb9be4cae 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 0772b284968a..bf6700b1b6ba 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { if from_mutbl == to_mutbl - && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) && msrv.meets(msrvs::POINTER_CAST) { diag.span_suggestion_verbose( diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index 4dc1290e8b15..48d65eb15d9a 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -206,12 +206,12 @@ fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: T continue; }, (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)), _) - if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) => { (true, false) }, (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _))) - if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) => { (false, true) }, diff --git a/clippy_lints/src/types/redundant_allocation.rs b/clippy_lints/src/types/redundant_allocation.rs index 1a656088b174..de3456a8ba5f 100644 --- a/clippy_lints/src/types/redundant_allocation.rs +++ b/clippy_lints/src/types/redundant_allocation.rs @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: // here because `mod.rs` guarantees this lint is only run on types outside of bodies and // is not run on locals. let ty = lower_ty(cx.tcx, hir_ty); - if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) { + if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.typing_env()) { return false; } hir_ty.span diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs index 230239335c65..9b236d3bda55 100644 --- a/clippy_lints/src/types/vec_box.rs +++ b/clippy_lints/src/types/vec_box.rs @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>( && let boxed_alloc_ty = last.args.get(1) && let ty_ty = lower_ty(cx.tcx, boxed_ty) && !ty_ty.has_escaping_bound_vars() - && ty_ty.is_sized(cx.tcx, cx.param_env) + && ty_ty.is_sized(cx.tcx, cx.typing_env()) && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) && ty_ty_size < box_size_threshold // https://github.com/rust-lang/rust-clippy/issues/7114 diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs index 14f4aa6676b6..34df1d5560a1 100644 --- a/clippy_lints/src/unnecessary_box_returns.rs +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -82,7 +82,7 @@ impl UnnecessaryBoxReturns { // It's sometimes useful to return Box if T is unsized, so don't lint those. // Also, don't lint if we know that T is very large, in which case returning // a Box may be beneficial. - if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { + if boxed_ty.is_sized(cx.tcx, cx.typing_env()) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { span_lint_and_then( cx, UNNECESSARY_BOX_RETURNS, diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 2aad867dc0d6..fff516b730dd 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain; /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) } /// This checks whether a given type is known to implement Debug. From d8e5f7ad8a10824a0de614d6f1276ebe2d84322e Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 19 Nov 2024 19:31:02 +0100 Subject: [PATCH 069/330] remove `TypingMode::from_param_env` in clippy --- clippy_lints/src/dereference.rs | 15 +++--- clippy_lints/src/derive.rs | 14 +++-- clippy_lints/src/loops/explicit_iter_loop.rs | 8 +-- .../src/needless_borrows_for_generic_args.rs | 6 +-- clippy_lints/src/needless_pass_by_value.rs | 11 ++-- clippy_utils/src/lib.rs | 54 ++++++++++--------- clippy_utils/src/ty.rs | 37 +++++-------- 7 files changed, 77 insertions(+), 68 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 9049739dddb4..fce7f9985ea1 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -15,6 +15,7 @@ use rustc_hir::{ self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TyKind, UnOp, }; +use rustc_hir::def_id::DefId; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; @@ -753,11 +754,10 @@ impl TyCoercionStability { fn for_defined_ty<'tcx>(cx: &LateContext<'tcx>, ty: DefinedTy<'tcx>, for_return: bool) -> Self { match ty { DefinedTy::Hir(ty) => Self::for_hir_ty(ty), - DefinedTy::Mir(ty) => Self::for_mir_ty( + DefinedTy::Mir { def_site_def_id, ty } => Self::for_mir_ty( cx.tcx, - // FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead. - ty::TypingEnv::from_param_env(ty.param_env), - cx.tcx.instantiate_bound_regions_with_erased(ty.value), + def_site_def_id, + cx.tcx.instantiate_bound_regions_with_erased(ty), for_return, ), } @@ -824,12 +824,15 @@ impl TyCoercionStability { } } - fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { + fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, def_site_def_id: Option, ty: Ty<'tcx>, for_return: bool) -> Self { let ty::Ref(_, mut ty, _) = *ty.kind() else { return Self::None; }; - ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + if let Some(def_id) = def_site_def_id { + let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id); + ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + } loop { break match *ty.kind() { ty::Ref(_, ref_ty, _) => { diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 0db6a822ec05..3b6b3c89858b 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -454,13 +454,13 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && !has_non_exhaustive_attr(cx.tcx, *adt) && !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id) - && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) + && let typing_env = typing_env_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) && let Some(local_def_id) = adt.did().as_local() // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) + .all(|ty| implements_trait_with_env(cx.tcx, typing_env, ty, eq_trait_def_id, None, &[])) { span_lint_hir_and_then( cx, @@ -485,7 +485,7 @@ fn ty_implements_eq_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, eq_trait_id: De } /// Creates the `ParamEnv` used for the give type's derived `Eq` impl. -fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv<'_> { +fn typing_env_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ty::TypingEnv<'_> { // Initial map from generic index to param def. // Vec<(param_def, needs_eq)> let mut params = tcx @@ -506,7 +506,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } } - ParamEnv::new( + let param_env = ParamEnv::new( tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { ClauseKind::Trait(TraitPredicate { @@ -517,5 +517,9 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> }), )), Reveal::UserFacing, - ) + ); + ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env, + } } diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index 48318682f33c..d999e1a05857 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -115,11 +115,11 @@ fn is_ref_iterable<'tcx>( .tcx .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output - && let param_env = cx.tcx.param_env(fn_id) - && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[]) + && let typing_env = ty::TypingEnv::non_body_analysis(cx.tcx, fn_id) + && implements_trait_with_env(cx.tcx, typing_env, req_self_ty, trait_id, Some(fn_id), &[]) && let Some(into_iter_ty) = - make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) - && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) + make_normalized_projection_with_regions(cx.tcx, typing_env, trait_id, sym!(IntoIter), [req_self_ty]) + && let req_res_ty = normalize_with_regions(cx.tcx, typing_env, req_res_ty) && into_iter_ty == req_res_ty { let adjustments = typeck.expr_adjustments(self_arg); diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index 43b885fbd2c9..9ebef531bc5c 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -85,8 +85,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { && use_cx.same_ctxt && !use_cx.is_ty_unified && let use_node = use_cx.use_node(cx) - && let Some(DefinedTy::Mir(ty)) = use_node.defined_ty(cx) - && let ty::Param(ty) = *ty.value.skip_binder().kind() + && let Some(DefinedTy::Mir { def_site_def_id: _, ty }) = use_node.defined_ty(cx) + && let ty::Param(param_ty) = *ty.skip_binder().kind() && let Some((hir_id, fn_id, i)) = match use_node { ExprUseNode::MethodArg(_, _, 0) => None, ExprUseNode::MethodArg(hir_id, None, i) => cx @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { fn_id, cx.typeck_results().node_args(hir_id), i, - ty, + param_ty, expr, &self.msrv, ) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index ad0ab1485302..b65ec8c3c482 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -182,9 +182,14 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { && !is_copy(cx, ty) && ty.is_sized(cx.tcx, cx.typing_env()) && !allowed_traits.iter().any(|&t| { - implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::< - ty::GenericArg<'tcx>, - >::None]) + implements_trait_with_env_from_iter( + cx.tcx, + cx.typing_env(), + ty, + t, + None, + [None::>] + ) }) && !implements_borrow_trait && !all_borrowable_trait diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index f28e5c9ed0e3..6408cc938cb8 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -116,8 +116,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, ParamEnv, - ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, + self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, + Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; @@ -2712,9 +2712,17 @@ pub fn walk_to_expr_usage<'tcx, T>( pub enum DefinedTy<'tcx> { // Used for locals and closures defined within the function. Hir(&'tcx hir::Ty<'tcx>), - /// Used for function signatures, and constant and static values. This includes the `ParamEnv` - /// from the definition site. - Mir(ParamEnvAnd<'tcx, Binder<'tcx, Ty<'tcx>>>), + /// Used for function signatures, and constant and static values. The type is + /// in the context of its definition site. We also track the `def_id` of its + /// definition site. + /// + /// WARNING: As the `ty` in in the scope of the definition, not of the function + /// using it, you must be very careful with how you use it. Using it in the wrong + /// scope easily results in ICEs. + Mir { + def_site_def_id: Option, + ty: Binder<'tcx, Ty<'tcx>>, + }, } /// The context an expressions value is used in. @@ -2833,10 +2841,10 @@ impl<'tcx> ExprUseNode<'tcx> { pub fn defined_ty(&self, cx: &LateContext<'tcx>) -> Option> { match *self { Self::LetStmt(LetStmt { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)), - Self::ConstStatic(id) => Some(DefinedTy::Mir( - cx.param_env - .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())), - )), + Self::ConstStatic(id) => Some(DefinedTy::Mir { + def_site_def_id: Some(id.def_id.to_def_id()), + ty: Binder::dummy(cx.tcx.type_of(id).instantiate_identity()), + }), Self::Return(id) => { if let Node::Expr(Expr { kind: ExprKind::Closure(c), @@ -2848,9 +2856,8 @@ impl<'tcx> ExprUseNode<'tcx> { FnRetTy::Return(ty) => Some(DefinedTy::Hir(ty)), } } else { - Some(DefinedTy::Mir( - cx.param_env.and(cx.tcx.fn_sig(id).instantiate_identity().output()), - )) + let ty = cx.tcx.fn_sig(id).instantiate_identity().output(); + Some(DefinedTy::Mir { def_site_def_id: Some(id.def_id.to_def_id()), ty }) } }, Self::Field(field) => match get_parent_expr_for_hir(cx, field.hir_id) { @@ -2866,12 +2873,9 @@ impl<'tcx> ExprUseNode<'tcx> { .find(|f| f.name == field.ident.name) .map(|f| (adt, f)) }) - .map(|(adt, field_def)| { - DefinedTy::Mir( - cx.tcx - .param_env(adt.did()) - .and(Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity())), - ) + .map(|(adt, field_def)| DefinedTy::Mir { + def_site_def_id: Some(adt.did()), + ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()), }), _ => None, }, @@ -2880,17 +2884,19 @@ impl<'tcx> ExprUseNode<'tcx> { let (hir_ty, ty) = sig.input_with_hir(i)?; Some(match hir_ty { Some(hir_ty) => DefinedTy::Hir(hir_ty), - None => DefinedTy::Mir( - sig.predicates_id() - .map_or(ParamEnv::empty(), |id| cx.tcx.param_env(id)) - .and(ty), - ), + None => DefinedTy::Mir { + def_site_def_id: sig.predicates_id(), + ty, + } }) }, Self::MethodArg(id, _, i) => { let id = cx.typeck_results().type_dependent_def_id(id)?; let sig = cx.tcx.fn_sig(id).skip_binder(); - Some(DefinedTy::Mir(cx.tcx.param_env(id).and(sig.input(i)))) + Some(DefinedTy::Mir { + def_site_def_id: Some(id), + ty: sig.input(i), + }) }, Self::LetStmt(_) | Self::FieldAccess(..) | Self::Callee | Self::Other | Self::AddrOf(..) => None, } diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index fff516b730dd..3498606dfd39 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, UintTy, Upcast, VariantDef, VariantDiscr, + TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -226,7 +226,7 @@ pub fn implements_trait<'tcx>( trait_id: DefId, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x))) + implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, trait_id, None, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. @@ -235,19 +235,19 @@ pub fn implements_trait<'tcx>( /// environment, used for checking const traits. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, callee_id: Option, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) + implements_trait_with_env_from_iter(tcx, typing_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait_from_env` but takes the arguments as an iterator. pub fn implements_trait_with_env_from_iter<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, callee_id: Option, @@ -268,7 +268,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( return false; } - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let args = args .into_iter() .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())) @@ -1239,12 +1239,12 @@ impl<'tcx> InteriorMut<'tcx> { pub fn make_normalized_projection_with_regions<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, container_id: DefId, assoc_ty: Symbol, args: impl IntoIterator>>, ) -> Option> { - fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] if let Some((i, arg)) = ty .args @@ -1261,10 +1261,8 @@ pub fn make_normalized_projection_with_regions<'tcx>( return None; } let cause = ObligationCause::dummy(); - match tcx - .infer_ctxt() - .build(TypingMode::from_param_env(param_env)) - .at(&cause, param_env) + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + match infcx.at(&cause, param_env) .query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { Ok(ty) => Some(ty.value), @@ -1274,20 +1272,13 @@ pub fn make_normalized_projection_with_regions<'tcx>( }, } } - helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?) + helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?) } -pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { +pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let cause = ObligationCause::dummy(); - match tcx - .infer_ctxt() - .build(TypingMode::from_param_env(param_env)) - .at(&cause, param_env) - .query_normalize(ty) - { - Ok(ty) => ty.value, - Err(_) => ty, - } + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + infcx.at(&cause, param_env).query_normalize(ty).map_or(ty, |ty| ty.value) } /// Checks if the type is `core::mem::ManuallyDrop<_>` From c783d1e387d0fbf35c19d76d5ea357c5d4a5d607 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 19 Nov 2024 20:10:42 +0100 Subject: [PATCH 070/330] `InterpCx` store `TypingEnv` instead of a `ParamEnv` --- clippy_lints/src/non_copy_const.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 57fa4797c5e5..5416e00fe0cb 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -270,8 +270,8 @@ impl<'tcx> NonCopyConst<'tcx> { instance, promoted: None, }; - let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx); - let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP); + let typing_env = ty::TypingEnv::post_analysis(cx.tcx, def_id); + let result = cx.tcx.const_eval_global_id_for_typeck(typing_env, cid, DUMMY_SP); Self::is_value_unfrozen_raw(cx, result, ty) } @@ -294,7 +294,7 @@ impl<'tcx> NonCopyConst<'tcx> { instance, promoted: None, }; - tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) + tcx.const_eval_global_id_for_typeck(typing_env, cid, span) }, Ok(None) => Err(ErrorHandled::TooGeneric(span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)), From 425346a1bcbc54fa27109143dfc5338938d5ca93 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 19 Nov 2024 21:38:47 +0100 Subject: [PATCH 071/330] Use a better message for unnecessary_map_or lint Suggested by @smoelius. --- .../src/methods/unnecessary_map_or.rs | 2 +- tests/ui/unnecessary_map_or.stderr | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index 74c0c35f9aa9..1199d2897610 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -135,7 +135,7 @@ pub(super) fn check<'a>( cx, UNNECESSARY_MAP_OR, expr.span, - "this `map_or` is redundant", + "this `map_or` can be simplified", format!("use {method} instead"), sugg, applicability, diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index 025eb24d465f..890abb012288 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -1,4 +1,4 @@ -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:12:13 | LL | let _ = Some(5).map_or(false, |n| n == 5); @@ -7,13 +7,13 @@ LL | let _ = Some(5).map_or(false, |n| n == 5); = note: `-D clippy::unnecessary-map-or` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:13:13 | LL | let _ = Some(5).map_or(true, |n| n != 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) != Some(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:14:13 | LL | let _ = Some(5).map_or(false, |n| { @@ -23,7 +23,7 @@ LL | | n == 5 LL | | }); | |______^ help: use a standard comparison instead: `(Some(5) == Some(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:18:13 | LL | let _ = Some(5).map_or(false, |n| { @@ -41,85 +41,85 @@ LL + 6 >= 5 LL ~ }); | -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:22:13 | LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![5]).is_some_and(|n| n == [5])` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:23:13 | LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![1]).is_some_and(|n| vec![2] == n)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:24:13 | LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == n)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:25:13 | LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 })` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:26:13 | LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `Ok::, i32>(vec![5]).is_ok_and(|n| n == [5])` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:27:13 | LL | let _ = Ok::(5).map_or(false, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Ok::(5) == Ok(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:28:13 | LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:29:13 | LL | let _ = Some(5).map_or(true, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| n == 5)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:30:13 | LL | let _ = Some(5).map_or(true, |n| 5 == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(|n| 5 == n)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:54:13 | LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:59:13 | LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(func)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:60:13 | LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(func)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:61:13 | LL | let _ = Some(5).map_or(true, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_none_or instead: `Some(5).is_none_or(func)` -error: this `map_or` is redundant +error: this `map_or` can be simplified --> tests/ui/unnecessary_map_or.rs:66:13 | LL | let _ = r.map_or(false, |x| x == 8); From ff6c4b731bc1df7f2a02c7dd6e94028371590db3 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Mon, 2 Sep 2024 01:13:07 +0800 Subject: [PATCH 072/330] reduce false positives of tail-expr-drop-order from consumed values take 2 open up coroutines tweak the wordings the lint works up until 2021 We were missing one case, for ADTs, which was causing `Result` to yield incorrect results. only include field spans with significant types deduplicate and eliminate field spans switch to emit spans to impl Drops Co-authored-by: Niko Matsakis collect drops instead of taking liveness diff apply some suggestions and add explantory notes small fix on the cache let the query recurse through coroutine new suggestion format with extracted variable name fine-tune the drop span and messages bugfix on runtime borrows tweak message wording filter out ecosystem types earlier apply suggestions clippy check lint level at session level further restrict applicability of the lint translate bid into nop for stable mir detect cycle in type structure --- clippy_utils/src/qualify_min_const_fn.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index abadca714001..345c46f944a5 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -233,6 +233,7 @@ fn check_statement<'tcx>( | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::ConstEvalCounter + | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::Nop => Ok(()), } } From 78d0a2aaac61e404a86ba4656f5deefbb8a53fbc Mon Sep 17 00:00:00 2001 From: xFrednet Date: Thu, 21 Nov 2024 13:50:31 +0000 Subject: [PATCH 073/330] Update version attributes for 1.83 lints --- clippy_lints/src/manual_div_ceil.rs | 2 +- clippy_lints/src/manual_is_power_of_two.rs | 2 +- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/non_zero_suggestions.rs | 2 +- clippy_lints/src/zombie_processes.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs index 07af2ddb0def..bbb89bee8355 100644 --- a/clippy_lints/src/manual_div_ceil.rs +++ b/clippy_lints/src/manual_div_ceil.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// let y: i32 = 4; /// let div = x.div_ceil(y); /// ``` - #[clippy::version = "1.81.0"] + #[clippy::version = "1.83.0"] pub MANUAL_DIV_CEIL, complexity, "manually reimplementing `div_ceil`" diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs index a11d3e4624c7..4fee3bf7aa9f 100644 --- a/clippy_lints/src/manual_is_power_of_two.rs +++ b/clippy_lints/src/manual_is_power_of_two.rs @@ -27,7 +27,7 @@ declare_clippy_lint! { /// let a: u32 = 4; /// let result = a.is_power_of_two(); /// ``` - #[clippy::version = "1.82.0"] + #[clippy::version = "1.83.0"] pub MANUAL_IS_POWER_OF_TWO, pedantic, "manually reimplementing `is_power_of_two`" diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 8aba650472b4..b856c929cf67 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -114,7 +114,7 @@ declare_clippy_lint! { /// let _ = FooStruct{}; /// } /// ``` - #[clippy::version = "pre 1.29.0"] + #[clippy::version = "1.83.0"] pub USED_UNDERSCORE_ITEMS, pedantic, "using a item which is prefixed with an underscore" diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs index aefb665b52e2..f6ce1d1d5867 100644 --- a/clippy_lints/src/non_zero_suggestions.rs +++ b/clippy_lints/src/non_zero_suggestions.rs @@ -39,7 +39,7 @@ declare_clippy_lint! { /// let r2 = x % NonZeroU64::from(y); /// } /// ``` - #[clippy::version = "1.81.0"] + #[clippy::version = "1.83.0"] pub NON_ZERO_SUGGESTIONS, restriction, "suggests using `NonZero#` from `u#` or `i#` for more efficient and type-safe conversions" diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs index 8d9241cc7d9a..4a13c10166f8 100644 --- a/clippy_lints/src/zombie_processes.rs +++ b/clippy_lints/src/zombie_processes.rs @@ -35,7 +35,7 @@ declare_clippy_lint! { /// let mut child = Command::new("ls").spawn().expect("failed to execute child"); /// child.wait().expect("failed to wait on child"); /// ``` - #[clippy::version = "1.74.0"] + #[clippy::version = "1.83.0"] pub ZOMBIE_PROCESSES, suspicious, "not waiting on a spawned child process" From 404e47aa84b16cab60008cb74eead08475e83960 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 29 Oct 2024 17:53:40 +0100 Subject: [PATCH 074/330] Add new lint `doc_include_without_cfg` --- CHANGELOG.md | 1 + README.md | 2 +- book/src/README.md | 2 +- clippy_config/src/conf.rs | 2 +- clippy_lints/src/declared_lints.rs | 1 + .../src/doc/include_in_doc_without_cfg.rs | 45 +++++++++++++++++++ clippy_lints/src/doc/mod.rs | 28 ++++++++++++ tests/ui/doc/doc_include_without_cfg.fixed | 40 +++++++++++++++++ tests/ui/doc/doc_include_without_cfg.rs | 40 +++++++++++++++++ tests/ui/doc/doc_include_without_cfg.stderr | 17 +++++++ tests/ui/missing_doc_crate.rs | 1 + 11 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/doc/include_in_doc_without_cfg.rs create mode 100644 tests/ui/doc/doc_include_without_cfg.fixed create mode 100644 tests/ui/doc/doc_include_without_cfg.rs create mode 100644 tests/ui/doc/doc_include_without_cfg.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bdbc91db939..1af7f349b8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5440,6 +5440,7 @@ Released 2018-09-13 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression +[`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown diff --git a/README.md b/README.md index ec76a6dfb08e..1690e2beb16f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 750 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category. diff --git a/book/src/README.md b/book/src/README.md index 7bdfb97c3acf..23527ba896af 100644 --- a/book/src/README.md +++ b/book/src/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 750 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index b0faac6d2a8e..263637aacd2f 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -154,7 +154,7 @@ macro_rules! define_Conf { )*) => { /// Clippy lint configuration pub struct Conf { - $($(#[doc = $doc])+ pub $name: $ty,)* + $($(#[cfg_attr(doc, doc = $doc)])+ pub $name: $ty,)* } mod defaults { diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index d8918d37afa9..fdb778d3ac0b 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -134,6 +134,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_names::DISALLOWED_NAMES_INFO, crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, + crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, crate::doc::DOC_MARKDOWN_INFO, diff --git a/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/clippy_lints/src/doc/include_in_doc_without_cfg.rs new file mode 100644 index 000000000000..49978d4a6555 --- /dev/null +++ b/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -0,0 +1,45 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_opt; +use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute}; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_span::sym; + +use super::DOC_INCLUDE_WITHOUT_CFG; + +pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { + for attr in attrs { + if !attr.span.from_expansion() + && let AttrKind::Normal(ref normal) = attr.kind + && normal.item.path == sym::doc + && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && !attr.span.contains(meta.span) + // Since the `include_str` is already expanded at this point, we can only take the + // whole attribute snippet and then modify for our suggestion. + && let Some(snippet) = snippet_opt(cx, attr.span) + // We cannot remove this because a `#[doc = include_str!("...")]` attribute can occupy + // several lines. + && let Some(start) = snippet.find('[') + && let Some(end) = snippet.rfind(']') + && let snippet = &snippet[start + 1..end] + // We check that the expansion actually comes from `include_str!` and not just from + // another macro. + && let Some(sub_snippet) = snippet.trim().strip_prefix("doc") + && let Some(sub_snippet) = sub_snippet.trim().strip_prefix("=") + && sub_snippet.trim().starts_with("include_str!") + { + span_lint_and_sugg( + cx, + DOC_INCLUDE_WITHOUT_CFG, + attr.span, + "included a file in documentation unconditionally", + "use `cfg_attr(doc, doc = \"...\")`", + format!( + "#{}[cfg_attr(doc, {snippet})]", + if attr.style == AttrStyle::Inner { "!" } else { "" } + ), + Applicability::MachineApplicable, + ); + } + } +} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index df7c37a192ad..dae7fab47dfa 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::lint_without_lint_pass)] + mod lazy_continuation; mod too_long_first_doc_paragraph; @@ -33,6 +35,7 @@ use std::ops::Range; use url::Url; mod empty_line_after; +mod include_in_doc_without_cfg; mod link_with_quotes; mod markdown; mod missing_headers; @@ -532,6 +535,29 @@ declare_clippy_lint! { "empty line after doc comments" } +declare_clippy_lint! { + /// ### What it does + /// Checks if included files in doc comments are included only for `cfg(doc)`. + /// + /// ### Why is this bad? + /// These files are not useful for compilation but will still be included. + /// Also, if any of these non-source code file is updated, it will trigger a + /// recompilation. + /// + /// ### Example + /// ```ignore + /// #![doc = include_str!("some_file.md")] + /// ``` + /// Use instead: + /// ```no_run + /// #![cfg_attr(doc, doc = include_str!("some_file.md"))] + /// ``` + #[clippy::version = "1.84.0"] + pub DOC_INCLUDE_WITHOUT_CFG, + pedantic, + "check if files included in documentation are behind `cfg(doc)`" +} + pub struct Documentation { valid_idents: FxHashSet, check_private_items: bool, @@ -561,6 +587,7 @@ impl_lint_pass!(Documentation => [ EMPTY_LINE_AFTER_OUTER_ATTR, EMPTY_LINE_AFTER_DOC_COMMENTS, TOO_LONG_FIRST_DOC_PARAGRAPH, + DOC_INCLUDE_WITHOUT_CFG, ]); impl<'tcx> LateLintPass<'tcx> for Documentation { @@ -690,6 +717,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ Some(("fake".into(), "fake".into())) } + include_in_doc_without_cfg::check(cx, attrs); if suspicious_doc_comments::check(cx, attrs) || empty_line_after::check(cx, attrs) || is_doc_hidden(attrs) { return None; } diff --git a/tests/ui/doc/doc_include_without_cfg.fixed b/tests/ui/doc/doc_include_without_cfg.fixed new file mode 100644 index 000000000000..d4ae810d7385 --- /dev/null +++ b/tests/ui/doc/doc_include_without_cfg.fixed @@ -0,0 +1,40 @@ +#![warn(clippy::doc_include_without_cfg)] +// Should not lint. +#![doc(html_playground_url = "https://playground.example.com/")] +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg +// Should not lint. +#![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#![doc = "some doc"] +//! more doc + +macro_rules! man_link { + ($a:literal, $b:literal) => { + concat!($a, $b) + }; +} + +// Should not lint! +macro_rules! tst { + ($(#[$attr:meta])*) => { + $(#[$attr])* + fn blue() { + println!("Hello, world!"); + } + } +} + +tst! { + /// This is a test with no included file +} + +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] //~ doc_include_without_cfg +// Should not lint. +#[doc = man_link!("bla", "blob")] +#[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#[doc = "some doc"] +/// more doc +fn main() { + // test code goes here +} diff --git a/tests/ui/doc/doc_include_without_cfg.rs b/tests/ui/doc/doc_include_without_cfg.rs new file mode 100644 index 000000000000..c82f6bf20356 --- /dev/null +++ b/tests/ui/doc/doc_include_without_cfg.rs @@ -0,0 +1,40 @@ +#![warn(clippy::doc_include_without_cfg)] +// Should not lint. +#![doc(html_playground_url = "https://playground.example.com/")] +#![doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg +// Should not lint. +#![cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#![doc = "some doc"] +//! more doc + +macro_rules! man_link { + ($a:literal, $b:literal) => { + concat!($a, $b) + }; +} + +// Should not lint! +macro_rules! tst { + ($(#[$attr:meta])*) => { + $(#[$attr])* + fn blue() { + println!("Hello, world!"); + } + } +} + +tst! { + /// This is a test with no included file +} + +#[doc = include_str!("../approx_const.rs")] //~ doc_include_without_cfg +// Should not lint. +#[doc = man_link!("bla", "blob")] +#[cfg_attr(feature = "whatever", doc = include_str!("../approx_const.rs"))] +#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))] +#[doc = "some doc"] +/// more doc +fn main() { + // test code goes here +} diff --git a/tests/ui/doc/doc_include_without_cfg.stderr b/tests/ui/doc/doc_include_without_cfg.stderr new file mode 100644 index 000000000000..17ea53c7c318 --- /dev/null +++ b/tests/ui/doc/doc_include_without_cfg.stderr @@ -0,0 +1,17 @@ +error: included a file in documentation unconditionally + --> tests/ui/doc/doc_include_without_cfg.rs:4:1 + | +LL | #![doc = include_str!("../approx_const.rs")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#![cfg_attr(doc, doc = include_str!("../approx_const.rs"))]` + | + = note: `-D clippy::doc-include-without-cfg` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_include_without_cfg)]` + +error: included a file in documentation unconditionally + --> tests/ui/doc/doc_include_without_cfg.rs:31:1 + | +LL | #[doc = include_str!("../approx_const.rs")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `cfg_attr(doc, doc = "...")`: `#[cfg_attr(doc, doc = include_str!("../approx_const.rs"))]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/missing_doc_crate.rs b/tests/ui/missing_doc_crate.rs index e00c7fbfed15..fdb23af279df 100644 --- a/tests/ui/missing_doc_crate.rs +++ b/tests/ui/missing_doc_crate.rs @@ -1,4 +1,5 @@ #![warn(clippy::missing_docs_in_private_items)] +#![allow(clippy::doc_include_without_cfg)] #![doc = include_str!("../../README.md")] fn main() {} From 01ff36a6b9e9134421c4e353ccbc904fdfe53be6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 22 Nov 2024 02:31:42 +0000 Subject: [PATCH 075/330] Get rid of HIR const checker --- compiler/rustc_const_eval/messages.ftl | 8 +- .../rustc_const_eval/src/check_consts/ops.rs | 11 +- compiler/rustc_interface/src/passes.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 5 - compiler/rustc_middle/src/util/call_kind.rs | 7 + compiler/rustc_passes/messages.ftl | 2 - compiler/rustc_passes/src/check_const.rs | 236 ------------------ compiler/rustc_passes/src/errors.rs | 7 - compiler/rustc_passes/src/lib.rs | 2 - tests/ui/coercion/coerce-loop-issue-122561.rs | 12 +- .../coercion/coerce-loop-issue-122561.stderr | 73 +----- tests/ui/consts/const-fn-error.rs | 5 +- tests/ui/consts/const-fn-error.stderr | 41 +-- tests/ui/consts/const-for-feature-gate.rs | 5 +- tests/ui/consts/const-for-feature-gate.stderr | 36 +-- tests/ui/consts/const-for.rs | 4 +- tests/ui/consts/const-for.stderr | 7 +- tests/ui/consts/const-try-feature-gate.rs | 5 +- tests/ui/consts/const-try-feature-gate.stderr | 23 +- tests/ui/consts/const-try.rs | 4 +- tests/ui/consts/const-try.stderr | 4 +- tests/ui/consts/control-flow/loop.rs | 12 +- tests/ui/consts/control-flow/loop.stderr | 63 ++--- tests/ui/consts/control-flow/try.rs | 6 +- tests/ui/consts/control-flow/try.stderr | 23 +- tests/ui/consts/try-operator.stderr | 16 +- tests/ui/issues/issue-50582.rs | 1 - tests/ui/issues/issue-50582.stderr | 15 +- tests/ui/issues/issue-50585.rs | 1 - tests/ui/issues/issue-50585.stderr | 15 +- tests/ui/never_type/issue-52443.rs | 5 +- tests/ui/never_type/issue-52443.stderr | 35 +-- .../ui/traits/const-traits/hir-const-check.rs | 6 +- .../const-traits/hir-const-check.stderr | 23 +- .../ice-126148-failed-to-normalize.rs | 4 +- .../ice-126148-failed-to-normalize.stderr | 4 +- .../trait-default-body-stability.stderr | 4 +- .../rustc_must_implement_one_of_misuse.stderr | 24 +- 38 files changed, 151 insertions(+), 604 deletions(-) delete mode 100644 compiler/rustc_passes/src/check_const.rs diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index f93f4d36e454..c31c94495d01 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -110,7 +110,7 @@ const_eval_extern_type_field = `extern type` field does not have a known offset const_eval_fn_ptr_call = function pointers need an RFC before allowed to be called in {const_eval_const_context}s const_eval_for_loop_into_iter_non_const = - cannot convert `{$ty}` into an iterator in {const_eval_const_context}s + cannot use `for` loop on `{$ty}` in {const_eval_const_context}s const_eval_frame_note = {$times -> [0] {const_eval_frame_note_inner} @@ -324,11 +324,11 @@ const_eval_ptr_as_bytes_1 = this code performed an operation that depends on the underlying bytes representing a pointer const_eval_ptr_as_bytes_2 = the absolute address of a pointer is not known at compile-time, so such operations are not supported -const_eval_question_branch_non_const = - `?` cannot determine the branch of `{$ty}` in {const_eval_const_context}s +const_eval_question_branch_non_const = + `?` is not allowed on `{$ty}` in {const_eval_const_context}s const_eval_question_from_residual_non_const = - `?` cannot convert from residual of `{$ty}` in {const_eval_const_context}s + `?` is not allowed on `{$ty}` in {const_eval_const_context}s const_eval_range = in the range {$lo}..={$hi} const_eval_range_lower = greater or equal to {$lo} diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 8ba6b89aad4d..aed83ce4ea6a 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -180,8 +180,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }; } - let mut err = match kind { - CallDesugaringKind::ForLoopIntoIter => { + // Don't point at the trait if this is a desugaring... + // FIXME(const_trait_impl): we could perhaps do this for `Iterator`. + match kind { + CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => { error!(NonConstForLoopIntoIter) } CallDesugaringKind::QuestionBranch => { @@ -196,10 +198,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { CallDesugaringKind::Await => { error!(NonConstAwait) } - }; - - diag_trait(&mut err, self_ty, kind.trait_def_id(tcx)); - err + } } CallKind::FnCall { fn_trait_id, self_ty } => { let note = match self_ty.kind() { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 43a98782016b..04da9e42f0ac 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -828,7 +828,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.ensure().check_mod_attrs(module); tcx.ensure().check_mod_naked_functions(module); tcx.ensure().check_mod_unstable_api_usage(module); - tcx.ensure().check_mod_const_bodies(module); }); }, { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 76338be33aad..20d4a13b0c04 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -958,11 +958,6 @@ rustc_queries! { desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } } - /// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`). - query check_mod_const_bodies(key: LocalModDefId) { - desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) } - } - /// Checks the loops in the module. query check_mod_loops(key: LocalModDefId) { desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) } diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index acfb78b3f6ef..df5b73ac1bdf 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -14,6 +14,8 @@ use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, Typing pub enum CallDesugaringKind { /// for _ in x {} calls x.into_iter() ForLoopIntoIter, + /// for _ in x {} calls iter.next() + ForLoopNext, /// x? calls x.branch() QuestionBranch, /// x? calls type_of(x)::from_residual() @@ -28,6 +30,7 @@ impl CallDesugaringKind { pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId { match self { Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(), + Self::ForLoopNext => tcx.require_lang_item(LangItem::Iterator, None), Self::QuestionBranch | Self::TryBlockFromOutput => { tcx.require_lang_item(LangItem::Try, None) } @@ -121,6 +124,10 @@ pub fn call_kind<'tcx>( && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop) { Some((CallDesugaringKind::ForLoopIntoIter, method_args.type_at(0))) + } else if tcx.is_lang_item(method_did, LangItem::IteratorNext) + && fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop) + { + Some((CallDesugaringKind::ForLoopNext, method_args.type_at(0))) } else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) { if tcx.is_lang_item(method_did, LangItem::TryTraitBranch) { Some((CallDesugaringKind::QuestionBranch, method_args.type_at(0))) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 08098ae7f6cb..22d824e65cde 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -705,8 +705,6 @@ passes_should_be_applied_to_trait = attribute should be applied to a trait .label = not a trait -passes_skipping_const_checks = skipping const checks - passes_stability_promotable = attribute cannot be applied to an expression diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs deleted file mode 100644 index f5ece513956e..000000000000 --- a/compiler/rustc_passes/src/check_const.rs +++ /dev/null @@ -1,236 +0,0 @@ -//! This pass checks HIR bodies that may be evaluated at compile-time (e.g., `const`, `static`, -//! `const fn`) for structured control flow (e.g. `if`, `while`), which is forbidden in a const -//! context. -//! -//! By the time the MIR const-checker runs, these high-level constructs have been lowered to -//! control-flow primitives (e.g., `Goto`, `SwitchInt`), making it tough to properly attribute -//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips -//! through, but errors for structured control flow in a `const` should be emitted here. - -use rustc_hir::def_id::{LocalDefId, LocalModDefId}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_middle::hir::nested_filter; -use rustc_middle::query::Providers; -use rustc_middle::span_bug; -use rustc_middle::ty::TyCtxt; -use rustc_session::parse::feature_err; -use rustc_span::{Span, Symbol, sym}; -use {rustc_attr as attr, rustc_hir as hir}; - -use crate::errors::SkippingConstChecks; - -/// An expression that is not *always* legal in a const context. -#[derive(Clone, Copy)] -enum NonConstExpr { - Loop(hir::LoopSource), - Match(hir::MatchSource), -} - -impl NonConstExpr { - fn name(self) -> String { - match self { - Self::Loop(src) => format!("`{}`", src.name()), - Self::Match(src) => format!("`{}`", src.name()), - } - } - - fn required_feature_gates(self) -> Option<&'static [Symbol]> { - use hir::LoopSource::*; - use hir::MatchSource::*; - - let gates: &[_] = match self { - Self::Match(AwaitDesugar) => { - return None; - } - - Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for], - - Self::Match(TryDesugar(_)) => &[sym::const_try], - - // All other expressions are allowed. - Self::Loop(Loop | While) | Self::Match(Normal | Postfix | FormatArgs) => &[], - }; - - Some(gates) - } -} - -fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { - let mut vis = CheckConstVisitor::new(tcx); - tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis); -} - -pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_const_bodies, ..*providers }; -} - -#[derive(Copy, Clone)] -struct CheckConstVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - const_kind: Option, - def_id: Option, -} - -impl<'tcx> CheckConstVisitor<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> Self { - CheckConstVisitor { tcx, const_kind: None, def_id: None } - } - - /// Emits an error when an unsupported expression is found in a const context. - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn const_check_violated(&self, expr: NonConstExpr, span: Span) { - let Self { tcx, def_id, const_kind } = *self; - - let features = tcx.features(); - let required_gates = expr.required_feature_gates(); - - let is_feature_allowed = |feature_gate| { - // All features require that the corresponding gate be enabled, - // even if the function has `#[rustc_allow_const_fn_unstable(the_gate)]`. - if !tcx.features().enabled(feature_gate) { - return false; - } - - // If `def_id` is `None`, we don't need to consider stability attributes. - let def_id = match def_id { - Some(x) => x, - None => return true, - }; - - // If the function belongs to a trait, then it must enable the const_trait_impl - // feature to use that trait function (with a const default body). - if tcx.trait_of_item(def_id.to_def_id()).is_some() { - return true; - } - - // If this crate is not using stability attributes, or this function is not claiming to be a - // stable `const fn`, that is all that is required. - if !tcx.features().staged_api() || tcx.has_attr(def_id, sym::rustc_const_unstable) { - return true; - } - - // However, we cannot allow stable `const fn`s to use unstable features without an explicit - // opt-in via `rustc_allow_const_fn_unstable`. - let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id)); - attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate) - }; - - match required_gates { - // Don't emit an error if the user has enabled the requisite feature gates. - Some(gates) if gates.iter().copied().all(is_feature_allowed) => return, - - // `-Zunleash-the-miri-inside-of-you` only works for expressions that don't have a - // corresponding feature gate. This encourages nightly users to use feature gates when - // possible. - None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => { - tcx.dcx().emit_warn(SkippingConstChecks { span }); - return; - } - - _ => {} - } - - let const_kind = - const_kind.expect("`const_check_violated` may only be called inside a const context"); - - let required_gates = required_gates.unwrap_or(&[]); - let missing_gates: Vec<_> = - required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect(); - - match missing_gates.as_slice() { - [] => { - span_bug!( - span, - "we should not have reached this point, since `.await` is denied earlier" - ); - } - - [missing_primary, ref missing_secondary @ ..] => { - let msg = - format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name()); - let mut err = feature_err(&tcx.sess, *missing_primary, span, msg); - - // If multiple feature gates would be required to enable this expression, include - // them as help messages. Don't emit a separate error for each missing feature gate. - // - // FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This - // is a pretty narrow case, however. - tcx.disabled_nightly_features( - &mut err, - def_id.map(|id| tcx.local_def_id_to_hir_id(id)), - missing_secondary.into_iter().map(|gate| (String::new(), *gate)), - ); - - err.emit(); - } - } - } - - /// Saves the parent `const_kind` before calling `f` and restores it afterwards. - fn recurse_into( - &mut self, - kind: Option, - def_id: Option, - f: impl FnOnce(&mut Self), - ) { - let parent_def_id = self.def_id; - let parent_kind = self.const_kind; - self.def_id = def_id; - self.const_kind = kind; - f(self); - self.def_id = parent_def_id; - self.const_kind = parent_kind; - } -} - -impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { - let kind = Some(hir::ConstContext::Const { inline: false }); - self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon)); - } - - fn visit_inline_const(&mut self, block: &'tcx hir::ConstBlock) { - let kind = Some(hir::ConstContext::Const { inline: true }); - self.recurse_into(kind, None, |this| intravisit::walk_inline_const(this, block)); - } - - fn visit_body(&mut self, body: &hir::Body<'tcx>) { - let owner = self.tcx.hir().body_owner_def_id(body.id()); - let kind = self.tcx.hir().body_const_context(owner); - self.recurse_into(kind, Some(owner), |this| intravisit::walk_body(this, body)); - } - - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - match &e.kind { - // Skip the following checks if we are not currently in a const context. - _ if self.const_kind.is_none() => {} - - hir::ExprKind::Loop(_, _, source, _) => { - self.const_check_violated(NonConstExpr::Loop(*source), e.span); - } - - hir::ExprKind::Match(_, _, source) => { - let non_const_expr = match source { - // These are handled by `ExprKind::Loop` above. - hir::MatchSource::ForLoopDesugar => None, - - _ => Some(NonConstExpr::Match(*source)), - }; - - if let Some(expr) = non_const_expr { - self.const_check_violated(expr, e.span); - } - } - - _ => {} - } - - intravisit::walk_expr(self, e); - } -} diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 2d1734c03143..8568e36fe30b 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1670,13 +1670,6 @@ pub(crate) struct ProcMacroBadSig { pub kind: ProcMacroKind, } -#[derive(Diagnostic)] -#[diag(passes_skipping_const_checks)] -pub(crate) struct SkippingConstChecks { - #[primary_span] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_unreachable_due_to_uninhabited)] pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> { diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 8f53b71319d5..1aa077ad2bb5 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -19,7 +19,6 @@ use rustc_middle::query::Providers; pub mod abi_test; mod check_attr; -mod check_const; pub mod dead; mod debugger_visualizer; mod diagnostic_items; @@ -43,7 +42,6 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { check_attr::provide(providers); - check_const::provide(providers); dead::provide(providers); debugger_visualizer::provide(providers); diagnostic_items::provide(providers); diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs index e08884ad6a4a..50a2aacc91ad 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.rs +++ b/tests/ui/coercion/coerce-loop-issue-122561.rs @@ -39,8 +39,7 @@ fn for_single_line() -> bool { for i in 0.. { return false; } } // b. format the suggestion correctly so // that it's readable fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { -//~^ ERROR `for` is not allowed in a `const` -//~| ERROR mismatched types + //~^ ERROR mismatched types true } @@ -84,16 +83,14 @@ fn loop_() -> bool { const C: i32 = { for i in 0.. { - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR mismatched types + //~^ ERROR mismatched types } }; fn main() { let _ = [10; { for i in 0..5 { - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR mismatched types + //~^ ERROR mismatched types } }]; @@ -105,6 +102,5 @@ fn main() { let _ = |a: &[(); for x in 0..2 {}]| {}; - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR mismatched types + //~^ ERROR mismatched types } diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr index 0f77fd1364d6..90e9f41c2910 100644 --- a/tests/ui/coercion/coerce-loop-issue-122561.stderr +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -1,5 +1,5 @@ warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:48:5 + --> $DIR/coerce-loop-issue-122561.rs:47:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` @@ -7,57 +7,11 @@ LL | while true { = note: `#[warn(while_true)]` on by default warning: denote infinite loops with `loop { ... }` - --> $DIR/coerce-loop-issue-122561.rs:72:5 + --> $DIR/coerce-loop-issue-122561.rs:71:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` -error[E0658]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:41:24 - | -LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:86:5 - | -LL | / for i in 0.. { -LL | | -LL | | -LL | | } - | |_____^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:94:9 - | -LL | / for i in 0..5 { -LL | | -LL | | -LL | | } - | |_________^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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]: `for` is not allowed in a `const` - --> $DIR/coerce-loop-issue-122561.rs:107:23 - | -LL | let _ = |a: &[(); for x in 0..2 {}]| {}; - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0308]: mismatched types --> $DIR/coerce-loop-issue-122561.rs:41:24 | @@ -71,11 +25,10 @@ LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool { | +++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:86:5 + --> $DIR/coerce-loop-issue-122561.rs:85:5 | LL | / for i in 0.. { LL | | -LL | | LL | | } | |_____^ expected `i32`, found `()` | @@ -174,7 +127,7 @@ LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` val | ++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:48:5 + --> $DIR/coerce-loop-issue-122561.rs:47:5 | LL | fn while_inifinite() -> bool { | ---- expected `bool` because of return type @@ -193,7 +146,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:57:5 + --> $DIR/coerce-loop-issue-122561.rs:56:5 | LL | fn while_finite() -> bool { | ---- expected `bool` because of return type @@ -213,7 +166,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:65:5 + --> $DIR/coerce-loop-issue-122561.rs:64:5 | LL | fn while_zero_times() -> bool { | ---- expected `bool` because of return type @@ -231,7 +184,7 @@ LL + /* `bool` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:72:5 + --> $DIR/coerce-loop-issue-122561.rs:71:5 | LL | fn while_never_type() -> ! { | - expected `!` because of return type @@ -251,11 +204,10 @@ LL + /* `loop {}` or `panic!("...")` */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:94:9 + --> $DIR/coerce-loop-issue-122561.rs:92:9 | LL | / for i in 0..5 { LL | | -LL | | LL | | } | |_________^ expected `usize`, found `()` | @@ -267,7 +219,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:101:9 + --> $DIR/coerce-loop-issue-122561.rs:98:9 | LL | / while false { LL | | @@ -282,7 +234,7 @@ LL + /* `usize` value */ | error[E0308]: mismatched types - --> $DIR/coerce-loop-issue-122561.rs:107:23 + --> $DIR/coerce-loop-issue-122561.rs:104:23 | LL | let _ = |a: &[(); for x in 0..2 {}]| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` @@ -293,7 +245,6 @@ help: consider returning a value here LL | let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {}; | +++++++++++++++++++ -error: aborting due to 18 previous errors; 2 warnings emitted +error: aborting due to 14 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-fn-error.rs b/tests/ui/consts/const-fn-error.rs index 42061ef0670f..b71517824232 100644 --- a/tests/ui/consts/const-fn-error.rs +++ b/tests/ui/consts/const-fn-error.rs @@ -3,9 +3,8 @@ const X : usize = 2; const fn f(x: usize) -> usize { let mut sum = 0; for i in 0..x { - //~^ ERROR cannot convert - //~| ERROR `for` is not allowed in a `const fn` - //~| ERROR cannot call non-const fn + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` sum += i; } sum diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index 42a6f2704c9e..3d4cf6539c89 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -1,29 +1,4 @@ -error[E0658]: `for` is not allowed in a `const fn` - --> $DIR/const-fn-error.rs:5:5 - | -LL | / for i in 0..x { -LL | | -LL | | -LL | | -LL | | sum += i; -LL | | } - | |_____^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range` into an iterator in constant functions - --> $DIR/const-fn-error.rs:5:14 - | -LL | for i in 0..x { - | ^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constant functions +error[E0015]: cannot use `for` loop on `std::ops::Range` in constant functions --> $DIR/const-fn-error.rs:5:14 | LL | for i in 0..x { @@ -31,7 +6,15 @@ LL | for i in 0..x { | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error[E0015]: cannot use `for` loop on `std::ops::Range` in constant functions + --> $DIR/const-fn-error.rs:5:14 + | +LL | for i in 0..x { + | ^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index d74178662b3a..b643e63c0969 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -2,9 +2,8 @@ const _: () = { for _ in 0..5 {} - //~^ error: `for` is not allowed in a `const` - //~| ERROR: cannot convert - //~| ERROR: cannot call + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 6e099a3159d9..29db5d24ac86 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -1,24 +1,4 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/const-for-feature-gate.rs:4:5 - | -LL | for _ in 0..5 {} - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range` into an iterator in constants - --> $DIR/const-for-feature-gate.rs:4:14 - | -LL | for _ in 0..5 {} - | ^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} @@ -26,7 +6,15 @@ LL | for _ in 0..5 {} | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs index 4f8034e73f09..6f7895457c53 100644 --- a/tests/ui/consts/const-for.rs +++ b/tests/ui/consts/const-for.rs @@ -2,8 +2,8 @@ const _: () = { for _ in 0..5 {} - //~^ error: cannot call - //~| error: cannot convert + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 78336dc93e85..d1308a8dedc8 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -1,20 +1,19 @@ -error[E0015]: cannot convert `std::ops::Range` into an iterator in constants +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs index 1cc045bf6124..09985079e8e8 100644 --- a/tests/ui/consts/const-try-feature-gate.rs +++ b/tests/ui/consts/const-try-feature-gate.rs @@ -2,9 +2,8 @@ const fn t() -> Option<()> { Some(())?; - //~^ error: `?` is not allowed in a `const fn` - //~| ERROR: cannot convert - //~| ERROR: cannot determine + //~^ ERROR `?` is not allowed + //~| ERROR `?` is not allowed None } diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index dc1dabc2f4f6..0ad19d05b382 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -1,34 +1,19 @@ -error[E0658]: `?` is not allowed in a `const fn` +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/const-try-feature-gate.rs:4:5 | LL | Some(())?; | ^^^^^^^^^ | - = note: see issue #74935 for more information - = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions - --> $DIR/const-try-feature-gate.rs:4:5 - | -LL | Some(())?; - | ^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/const-try-feature-gate.rs:4:5 | LL | Some(())?; | ^^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index d30b22accef9..26aa9230a398 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -33,8 +33,8 @@ impl const Try for TryMe { const fn t() -> TryMe { TryMe?; - //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions - //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions + //~^ ERROR `?` is not allowed on + //~| ERROR `?` is not allowed on TryMe } diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index 1f4f814cb936..abb03a74c82a 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -16,7 +16,7 @@ LL | impl const Try for TryMe { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/const-try.rs:35:5 | LL | TryMe?; @@ -24,7 +24,7 @@ LL | TryMe?; | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/const-try.rs:35:5 | LL | TryMe?; diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index f8d9f3ddb9b2..b02c31c4c25b 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -50,15 +50,15 @@ const _: i32 = { const _: i32 = { let mut x = 0; - for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - //~^ ERROR: cannot call - //~| ERROR: cannot convert + for i in 0..4 { + //~^ ERROR: cannot use `for` + //~| ERROR: cannot use `for` x += i; } - for i in 0..4 { //~ ERROR `for` is not allowed in a `const` - //~^ ERROR: cannot call - //~| ERROR: cannot convert + for i in 0..4 { + //~^ ERROR: cannot use `for` + //~| ERROR: cannot use `for` x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 5e43c70e9dfb..b91371f9dc21 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -1,42 +1,4 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:53:5 - | -LL | / for i in 0..4 { -LL | | -LL | | -LL | | x += i; -LL | | } - | |_____^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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]: `for` is not allowed in a `const` - --> $DIR/loop.rs:59:5 - | -LL | / for i in 0..4 { -LL | | -LL | | -LL | | x += i; -LL | | } - | |_____^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0015]: cannot convert `std::ops::Range` into an iterator in constants - --> $DIR/loop.rs:53:14 - | -LL | for i in 0..4 { - | ^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/loop.rs:53:14 | LL | for i in 0..4 { @@ -44,17 +6,16 @@ LL | for i in 0..4 { | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot convert `std::ops::Range` into an iterator in constants - --> $DIR/loop.rs:59:14 +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants + --> $DIR/loop.rs:53:14 | LL | for i in 0..4 { | ^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/loop.rs:59:14 | LL | for i in 0..4 { @@ -62,7 +23,15 @@ LL | for i in 0..4 { | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 6 previous errors +error[E0015]: cannot use `for` loop on `std::ops::Range` in constants + --> $DIR/loop.rs:59:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs index 5c6957df4056..67083e1a39b5 100644 --- a/tests/ui/consts/control-flow/try.rs +++ b/tests/ui/consts/control-flow/try.rs @@ -3,9 +3,9 @@ const fn opt() -> Option { let x = Some(2); - x?; //~ ERROR `?` is not allowed in a `const fn` - //~^ ERROR: cannot convert - //~| ERROR: cannot determine + x?; + //~^ ERROR: `?` is not allowed + //~| ERROR: `?` is not allowed None } diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index 5e2c77318e78..62a3e3ce6bc3 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -1,34 +1,19 @@ -error[E0658]: `?` is not allowed in a `const fn` +error[E0015]: `?` is not allowed on `Option` in constant functions --> $DIR/try.rs:6:5 | LL | x?; | ^^ | - = note: see issue #74935 for more information - = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option` in constant functions - --> $DIR/try.rs:6:5 - | -LL | x?; - | ^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option` in constant functions +error[E0015]: `?` is not allowed on `Option` in constant functions --> $DIR/try.rs:6:5 | LL | x?; | ^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index 40d96ed3a100..fc37039d2606 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -4,44 +4,36 @@ error[E0635]: unknown feature `const_convert` LL | #![feature(const_convert)] | ^^^^^^^^^^^^^ -error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions +error[E0015]: `?` is not allowed on `Result<(), ()>` in constant functions --> $DIR/try-operator.rs:10:9 | LL | Err(())?; | ^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/result.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Result` in constant functions +error[E0015]: `?` is not allowed on `Result` in constant functions --> $DIR/try-operator.rs:10:9 | LL | Err(())?; | ^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/result.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 | LL | None?; | ^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 | LL | None?; | ^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 5 previous errors diff --git a/tests/ui/issues/issue-50582.rs b/tests/ui/issues/issue-50582.rs index 2d5c93587529..1358e0bde4c8 100644 --- a/tests/ui/issues/issue-50582.rs +++ b/tests/ui/issues/issue-50582.rs @@ -1,5 +1,4 @@ fn main() { Vec::<[(); 1 + for x in 0..1 {}]>::new(); //~^ ERROR cannot add - //~| ERROR `for` is not allowed in a `const` } diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr index af7a36f62fb8..168f5894fb03 100644 --- a/tests/ui/issues/issue-50582.stderr +++ b/tests/ui/issues/issue-50582.stderr @@ -1,13 +1,3 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/issue-50582.rs:2:20 - | -LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0277]: cannot add `()` to `{integer}` --> $DIR/issue-50582.rs:2:18 | @@ -26,7 +16,6 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); `&f64` implements `Add` and 56 others -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-50585.rs b/tests/ui/issues/issue-50585.rs index a2f11c98d5a3..ca2ece8d53be 100644 --- a/tests/ui/issues/issue-50585.rs +++ b/tests/ui/issues/issue-50585.rs @@ -1,5 +1,4 @@ fn main() { |y: Vec<[(); for x in 0..2 {}]>| {}; //~^ ERROR mismatched types - //~| ERROR `for` is not allowed in a `const` } diff --git a/tests/ui/issues/issue-50585.stderr b/tests/ui/issues/issue-50585.stderr index e7f13e634750..7e83ea35fbbd 100644 --- a/tests/ui/issues/issue-50585.stderr +++ b/tests/ui/issues/issue-50585.stderr @@ -1,13 +1,3 @@ -error[E0658]: `for` is not allowed in a `const` - --> $DIR/issue-50585.rs:2:18 - | -LL | |y: Vec<[(); for x in 0..2 {}]>| {}; - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0308]: mismatched types --> $DIR/issue-50585.rs:2:18 | @@ -20,7 +10,6 @@ help: consider returning a value here LL | |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {}; | +++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs index dcda2b9536aa..b112842030ef 100644 --- a/tests/ui/never_type/issue-52443.rs +++ b/tests/ui/never_type/issue-52443.rs @@ -7,7 +7,6 @@ fn main() { //~^ WARN denote infinite loops with [(); { for _ in 0usize.. {}; 0}]; - //~^ ERROR `for` is not allowed in a `const` - //~| ERROR cannot convert - //~| ERROR cannot call + //~^ ERROR cannot use `for` + //~| ERROR cannot use `for` } diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index 2207ceb50336..1c5a0d65142f 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -6,16 +6,6 @@ LL | [(); {while true {break}; 0}]; | = note: `#[warn(while_true)]` on by default -error[E0658]: `for` is not allowed in a `const` - --> $DIR/issue-52443.rs:9:12 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #87575 for more information - = help: add `#![feature(const_for)]` 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[E0308]: mismatched types --> $DIR/issue-52443.rs:2:10 | @@ -41,17 +31,7 @@ help: give the `break` a value of the expected type LL | [(); loop { break 42 }]; | ++ -error[E0015]: cannot convert `RangeFrom` into an iterator in constants - --> $DIR/issue-52443.rs:9:21 - | -LL | [(); { for _ in 0usize.. {}; 0}]; - | ^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants +error[E0015]: cannot use `for` loop on `RangeFrom` in constants --> $DIR/issue-52443.rs:9:21 | LL | [(); { for _ in 0usize.. {}; 0}]; @@ -59,7 +39,16 @@ LL | [(); { for _ in 0usize.. {}; 0}]; | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 5 previous errors; 1 warning emitted +error[E0015]: cannot use `for` loop on `RangeFrom` in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -Some errors have detailed explanations: E0015, E0308, E0658. +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0015, E0308. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs index ea1783b7c2cc..c485fb121841 100644 --- a/tests/ui/traits/const-traits/hir-const-check.rs +++ b/tests/ui/traits/const-traits/hir-const-check.rs @@ -11,9 +11,9 @@ pub trait MyTrait { impl const MyTrait for () { fn method(&self) -> Option<()> { - Some(())?; //~ ERROR `?` is not allowed in a `const fn` - //~^ ERROR `?` cannot determine the branch of `Option<()>` in constant functions - //~| ERROR `?` cannot convert from residual of `Option<()>` in constant functions + Some(())?; + //~^ ERROR `?` is not allowed on + //~| ERROR `?` is not allowed on None } } diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr index ef5dba0dc0e6..d66a7ea31449 100644 --- a/tests/ui/traits/const-traits/hir-const-check.stderr +++ b/tests/ui/traits/const-traits/hir-const-check.stderr @@ -1,34 +1,19 @@ -error[E0658]: `?` is not allowed in a `const fn` +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/hir-const-check.rs:14:9 | LL | Some(())?; | ^^^^^^^^^ | - = note: see issue #74935 for more information - = help: add `#![feature(const_try)]` 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[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions - --> $DIR/hir-const-check.rs:14:9 - | -LL | Some(())?; - | ^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions +error[E0015]: `?` is not allowed on `Option<()>` in constant functions --> $DIR/hir-const-check.rs:14:9 | LL | Some(())?; | ^^^^^^^^^ | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0015, E0658. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs index 9ce81031b270..3473be565c18 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs @@ -18,8 +18,8 @@ impl const Try for TryMe { const fn t() -> TryMe { TryMe?; - //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions - //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions + //~^ ERROR `?` is not allowed on + //~| ERROR `?` is not allowed on TryMe } diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr index db047bfd94db..9bd493e5fdbb 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr @@ -33,7 +33,7 @@ LL | impl const Try for TryMe { = help: implement the missing item: `fn from_output(_: ::Output) -> Self { todo!() }` = help: implement the missing item: `fn branch(self) -> ControlFlow<::Residual, ::Output> { todo!() }` -error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/ice-126148-failed-to-normalize.rs:20:5 | LL | TryMe?; @@ -41,7 +41,7 @@ LL | TryMe?; | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions +error[E0015]: `?` is not allowed on `TryMe` in constant functions --> $DIR/ice-126148-failed-to-normalize.rs:20:5 | LL | TryMe?; diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr index 5806b6d6fd21..b471cb81c3b8 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.stderr +++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr @@ -16,7 +16,7 @@ LL | impl const FromResidual for T { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error[E0015]: `?` cannot determine the branch of `T` in constant functions +error[E0015]: `?` is not allowed on `T` in constant functions --> $DIR/trait-default-body-stability.rs:45:9 | LL | T? @@ -24,7 +24,7 @@ LL | T? | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: `?` cannot convert from residual of `T` in constant functions +error[E0015]: `?` is not allowed on `T` in constant functions --> $DIR/trait-default-body-stability.rs:45:9 | LL | T? diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index 03a4017b3d7f..38e692521ca2 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -22,18 +22,6 @@ LL | LL | struct Struct {} | ---------------- not a trait -error: function not found in this trait - --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 - | -LL | #[rustc_must_implement_one_of(a, b)] - | ^ - -error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args - --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 - | -LL | #[rustc_must_implement_one_of(a)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 | @@ -46,6 +34,18 @@ error: function not found in this trait LL | #[rustc_must_implement_one_of(a, b)] | ^ +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 + | +LL | #[rustc_must_implement_one_of(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 | From 70d53bb364ced275c2e893763a1d6f8772ea1cdb Mon Sep 17 00:00:00 2001 From: xFrednet Date: Thu, 21 Nov 2024 13:59:05 +0000 Subject: [PATCH 076/330] Changelog for Clippy 1.83 :robot: --- CHANGELOG.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd3124ee9a3b..1fefd3e37e08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,56 @@ document. ## Unreleased / Beta / In Rust Nightly -[0f8eabd6...master](https://github.com/rust-lang/rust-clippy/compare/0f8eabd6...master) +[aa0d5513...master](https://github.com/rust-lang/rust-clippy/compare/aa0d5513...master) + +## Rust 1.83 + +Current stable, released 2024-11-28 + +[View all 64 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-08-25T09%3A59%3A01Z..2024-10-03T13%3A42%3A56Z+base%3Amaster) + +### Important Change + +* Removed the implicit `cargo-clippy` feature set by Clippy as announced here: + + [#13246](https://github.com/rust-lang/rust-clippy/pull/13246) + +### New Lints + +* Added [`unused_trait_names`] to `restriction` + [#13322](https://github.com/rust-lang/rust-clippy/pull/13322) +* Added [`unnecessary_first_then_check`] to `complexity` + [#13421](https://github.com/rust-lang/rust-clippy/pull/13421) +* Added [`non_zero_suggestions`] to `restriction` + [#13167](https://github.com/rust-lang/rust-clippy/pull/13167) +* Added [`manual_is_power_of_two`] to `pedantic` + [#13327](https://github.com/rust-lang/rust-clippy/pull/13327) +* Added [`manual_div_ceil`] to `complexity` + [#12987](https://github.com/rust-lang/rust-clippy/pull/12987) +* Added [`zombie_processes`] to `suspicious` + [#11476](https://github.com/rust-lang/rust-clippy/pull/11476) +* Added [`used_underscore_items`] to `pedantic` + [#13294](https://github.com/rust-lang/rust-clippy/pull/13294) + +### Moves and Deprecations + +* Moved [`ref_option`] to `pedantic` (From `nursery`) + [#13469](https://github.com/rust-lang/rust-clippy/pull/13469) +* Moved [`manual_c_str_literals`] to `complexity` (From `pedantic` now warn-by-default) + [#13263](https://github.com/rust-lang/rust-clippy/pull/13263) +* Moved [`empty_line_after_doc_comments`] to `suspicious` (From `nursery` now warn-by-default) + [#13091](https://github.com/rust-lang/rust-clippy/pull/13091) +* Moved [`empty_line_after_outer_attr`] to `suspicious` (From `nursery` now warn-by-default) + [#13091](https://github.com/rust-lang/rust-clippy/pull/13091) + +### Enhancements + +* [`missing_panics_doc`]: No longer lints in const environments + [#13382](https://github.com/rust-lang/rust-clippy/pull/13382) ## Rust 1.82 -Current stable, released 2024-10-17 +Released 2024-10-17 [View all 108 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-07-11T20%3A12%3A07Z..2024-08-24T20%3A55%3A35Z+base%3Amaster) From 9f7fb41272647ee9db7038a9588aa5a70e38405e Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 22 Nov 2024 14:17:45 +0100 Subject: [PATCH 077/330] fix: multipart suggestions for derivable_impls --- clippy_lints/src/derivable_impls.rs | 48 +++-- tests/ui/derivable_impls.fixed | 295 ++++++++++++++++++++++++++++ tests/ui/derivable_impls.rs | 2 - tests/ui/derivable_impls.stderr | 60 +++--- 4 files changed, 343 insertions(+), 62 deletions(-) create mode 100644 tests/ui/derivable_impls.fixed diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 2b2644213222..9569081ad088 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -132,17 +132,15 @@ fn check_struct<'tcx>( if should_emit { let struct_span = cx.tcx.def_span(adt_def.did()); + let suggestions = vec![ + (item.span, String::new()), // Remove the manual implementation + (struct_span.shrink_to_lo(), "#[derive(Default)]\n".to_string()), // Add the derive attribute + ]; + span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { - diag.span_suggestion_hidden( - item.span, - "remove the manual implementation...", - String::new(), - Applicability::MachineApplicable, - ); - diag.span_suggestion( - struct_span.shrink_to_lo(), - "...and instead derive it", - "#[derive(Default)]\n".to_string(), + diag.multipart_suggestion( + "replace the manual implementation with a derive attribute", + suggestions, Applicability::MachineApplicable, ); }); @@ -161,23 +159,23 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex let indent_enum = indent_of(cx, enum_span).unwrap_or(0); let variant_span = cx.tcx.def_span(variant_def.def_id); let indent_variant = indent_of(cx, variant_span).unwrap_or(0); - span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { - diag.span_suggestion_hidden( - item.span, - "remove the manual implementation...", - String::new(), - Applicability::MachineApplicable, - ); - diag.span_suggestion( + + let suggestions = vec![ + (item.span, String::new()), // Remove the manual implementation + ( enum_span.shrink_to_lo(), - "...and instead derive it...", - format!("#[derive(Default)]\n{indent}", indent = " ".repeat(indent_enum),), - Applicability::MachineApplicable, - ); - diag.span_suggestion( + format!("#[derive(Default)]\n{}", " ".repeat(indent_enum)), + ), // Add the derive attribute + ( variant_span.shrink_to_lo(), - "...and mark the default variant", - format!("#[default]\n{indent}", indent = " ".repeat(indent_variant),), + format!("#[default]\n{}", " ".repeat(indent_variant)), + ), // Mark the default variant + ]; + + span_lint_and_then(cx, DERIVABLE_IMPLS, item.span, "this `impl` can be derived", |diag| { + diag.multipart_suggestion( + "replace the manual implementation with a derive attribute and mark the default variant", + suggestions, Applicability::MachineApplicable, ); }); diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed new file mode 100644 index 000000000000..c85f384fd6eb --- /dev/null +++ b/tests/ui/derivable_impls.fixed @@ -0,0 +1,295 @@ +#![allow(dead_code)] + +use std::collections::HashMap; + +#[derive(Default)] +struct FooDefault<'a> { + a: bool, + b: i32, + c: u64, + d: Vec, + e: FooND1, + f: FooND2, + g: HashMap, + h: (i32, Vec), + i: [Vec; 3], + j: [i32; 5], + k: Option, + l: &'a [i32], +} + + +#[derive(Default)] +struct TupleDefault(bool, i32, u64); + + +struct FooND1 { + a: bool, +} + +impl std::default::Default for FooND1 { + fn default() -> Self { + Self { a: true } + } +} + +struct FooND2 { + a: i32, +} + +impl std::default::Default for FooND2 { + fn default() -> Self { + Self { a: 5 } + } +} + +struct FooNDNew { + a: bool, +} + +impl FooNDNew { + fn new() -> Self { + Self { a: true } + } +} + +impl Default for FooNDNew { + fn default() -> Self { + Self::new() + } +} + +struct FooNDVec(Vec); + +impl Default for FooNDVec { + fn default() -> Self { + Self(vec![5, 12]) + } +} + +#[derive(Default)] +struct StrDefault<'a>(&'a str); + + +#[derive(Default)] +struct AlreadyDerived(i32, bool); + +macro_rules! mac { + () => { + 0 + }; + ($e:expr) => { + struct X(u32); + impl Default for X { + fn default() -> Self { + Self($e) + } + } + }; +} + +mac!(0); + +#[derive(Default)] +struct Y(u32); + +struct RustIssue26925 { + a: Option, +} + +// We should watch out for cases where a manual impl is needed because a +// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925). +// For example, a struct with Option does not require T: Default, but a derive adds +// that type bound anyways. So until #26925 get fixed we should disable lint +// for the following case +impl Default for RustIssue26925 { + fn default() -> Self { + Self { a: None } + } +} + +struct SpecializedImpl { + a: A, + b: B, +} + +impl Default for SpecializedImpl { + fn default() -> Self { + Self { + a: T::default(), + b: T::default(), + } + } +} + +#[derive(Default)] +struct WithoutSelfCurly { + a: bool, +} + + +#[derive(Default)] +struct WithoutSelfParan(bool); + + +// https://github.com/rust-lang/rust-clippy/issues/7655 + +pub struct SpecializedImpl2 { + v: Vec, +} + +impl Default for SpecializedImpl2 { + fn default() -> Self { + Self { v: Vec::new() } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/7654 + +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, +} + +/// `#000000` +impl Default for Color { + fn default() -> Self { + Color { r: 0, g: 0, b: 0 } + } +} + +pub struct Color2 { + pub r: u8, + pub g: u8, + pub b: u8, +} + +impl Default for Color2 { + /// `#000000` + fn default() -> Self { + Self { r: 0, g: 0, b: 0 } + } +} + +#[derive(Default)] +pub struct RepeatDefault1 { + a: [i8; 32], +} + + +pub struct RepeatDefault2 { + a: [i8; 33], +} + +impl Default for RepeatDefault2 { + fn default() -> Self { + RepeatDefault2 { a: [0; 33] } + } +} + +// https://github.com/rust-lang/rust-clippy/issues/7753 + +pub enum IntOrString { + Int(i32), + String(String), +} + +impl Default for IntOrString { + fn default() -> Self { + IntOrString::Int(0) + } +} + +#[derive(Default)] +pub enum SimpleEnum { + Foo, + #[default] + Bar, +} + + +pub enum NonExhaustiveEnum { + Foo, + #[non_exhaustive] + Bar, +} + +impl Default for NonExhaustiveEnum { + fn default() -> Self { + NonExhaustiveEnum::Bar + } +} + +// https://github.com/rust-lang/rust-clippy/issues/10396 + +#[derive(Default)] +struct DefaultType; + +struct GenericType { + t: T, +} + +impl Default for GenericType { + fn default() -> Self { + Self { t: Default::default() } + } +} + +struct InnerGenericType { + t: T, +} + +impl Default for InnerGenericType { + fn default() -> Self { + Self { t: Default::default() } + } +} + +struct OtherGenericType { + inner: InnerGenericType, +} + +impl Default for OtherGenericType { + fn default() -> Self { + Self { + inner: Default::default(), + } + } +} + +mod issue10158 { + pub trait T {} + + #[derive(Default)] + pub struct S {} + impl T for S {} + + pub struct Outer { + pub inner: Box, + } + + impl Default for Outer { + fn default() -> Self { + Outer { + // Box::::default() adjusts to Box + inner: Box::::default(), + } + } + } +} + +mod issue11368 { + pub struct A { + a: u32, + } + + impl Default for A { + #[track_caller] + fn default() -> Self { + Self { a: 0 } + } + } +} + +fn main() {} diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index 58f7771b6275..21d73ba8b777 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -1,7 +1,5 @@ #![allow(dead_code)] -//@no-rustfix: need to change the suggestion to a multipart suggestion - use std::collections::HashMap; struct FooDefault<'a> { diff --git a/tests/ui/derivable_impls.stderr b/tests/ui/derivable_impls.stderr index d3adfa60e10f..c22569145bdb 100644 --- a/tests/ui/derivable_impls.stderr +++ b/tests/ui/derivable_impls.stderr @@ -1,5 +1,5 @@ error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:22:1 + --> tests/ui/derivable_impls.rs:20:1 | LL | / impl std::default::Default for FooDefault<'_> { LL | | fn default() -> Self { @@ -12,15 +12,14 @@ LL | | } | = note: `-D clippy::derivable-impls` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::derivable_impls)]` - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct FooDefault<'a> { +LL ~ struct FooDefault<'a> { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:43:1 + --> tests/ui/derivable_impls.rs:41:1 | LL | / impl std::default::Default for TupleDefault { LL | | fn default() -> Self { @@ -29,15 +28,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct TupleDefault(bool, i32, u64); +LL ~ struct TupleDefault(bool, i32, u64); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:95:1 + --> tests/ui/derivable_impls.rs:93:1 | LL | / impl Default for StrDefault<'_> { LL | | fn default() -> Self { @@ -46,15 +44,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct StrDefault<'a>(&'a str); +LL ~ struct StrDefault<'a>(&'a str); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:121:1 + --> tests/ui/derivable_impls.rs:119:1 | LL | / impl Default for Y { LL | | fn default() -> Self { @@ -63,15 +60,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct Y(u32); +LL ~ struct Y(u32); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:160:1 + --> tests/ui/derivable_impls.rs:158:1 | LL | / impl Default for WithoutSelfCurly { LL | | fn default() -> Self { @@ -80,15 +76,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct WithoutSelfCurly { +LL ~ struct WithoutSelfCurly { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:168:1 + --> tests/ui/derivable_impls.rs:166:1 | LL | / impl Default for WithoutSelfParan { LL | | fn default() -> Self { @@ -97,15 +92,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | struct WithoutSelfParan(bool); +LL ~ struct WithoutSelfParan(bool); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:218:1 + --> tests/ui/derivable_impls.rs:216:1 | LL | / impl Default for RepeatDefault1 { LL | | fn default() -> Self { @@ -114,15 +108,14 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it +help: replace the manual implementation with a derive attribute | LL + #[derive(Default)] -LL | pub struct RepeatDefault1 { +LL ~ pub struct RepeatDefault1 { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:252:1 + --> tests/ui/derivable_impls.rs:250:1 | LL | / impl Default for SimpleEnum { LL | | fn default() -> Self { @@ -131,14 +124,11 @@ LL | | } LL | | } | |_^ | - = help: remove the manual implementation... -help: ...and instead derive it... +help: replace the manual implementation with a derive attribute and mark the default variant | LL + #[derive(Default)] -LL | pub enum SimpleEnum { - | -help: ...and mark the default variant - | +LL ~ pub enum SimpleEnum { +LL | Foo, LL ~ #[default] LL ~ Bar, | From f0bb475f80f39da2ba9c7919c8729eaa9a7bc76d Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren <3190756+Kampfkarren@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:16:46 -0800 Subject: [PATCH 078/330] Remove incorrect "no default" text from trivial_copy_size_limit --- clippy_config/src/conf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 9eef3d9e4fce..41b56b45d9ae 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -678,7 +678,7 @@ define_Conf! { #[lints(arbitrary_source_item_ordering)] trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(), /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by - /// reference. By default there is no limit + /// reference. #[default_text = "target_pointer_width * 2"] #[lints(trivially_copy_pass_by_ref)] trivial_copy_size_limit: Option = None, From 431c500c6071008a00b63db1936af8516b5863ef Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 14 Nov 2024 17:43:52 +0100 Subject: [PATCH 079/330] Print env var in --print=deployment-target The deployment target environment variable is OS-specific, and if you're in a place where you're asking `rustc` for the deployment target, you're likely to also wanna know the environment variable. --- compiler/rustc_codegen_ssa/src/back/apple.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 5 +-- .../run-make/apple-deployment-target/rmake.rs | 34 ++++++++++++------- tests/run-make/apple-sdk-version/rmake.rs | 3 +- tests/ui/print-request/macos-target.rs | 1 + tests/ui/print-request/macos-target.stdout | 2 +- 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 93d90cd16b24..d9c5c3e5af96 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -97,7 +97,7 @@ fn minimum_deployment_target(target: &Target) -> OSVersion { } /// Name of the environment variable used to fetch the deployment target on the given OS. -fn deployment_target_env_var(os: &str) -> &'static str { +pub fn deployment_target_env_var(os: &str) -> &'static str { match os { "macos" => "MACOSX_DEPLOYMENT_TARGET", "ios" => "IPHONEOS_DEPLOYMENT_TARGET", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c270ce16726d..6d8a321536b4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -875,8 +875,9 @@ fn print_crate_info( DeploymentTarget => { if sess.target.is_like_osx { println_info!( - "deployment_target={}", - apple::pretty_version(apple::deployment_target(sess)) + "{}={}", + apple::deployment_target_env_var(&sess.target.os), + apple::pretty_version(apple::deployment_target(sess)), ) } else { #[allow(rustc::diagnostic_outside_of_impl)] diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index fed6d310770c..0ae95cb1f4b1 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -24,21 +24,31 @@ fn minos(file: &str, version: &str) { fn main() { // These versions should generally be higher than the default versions - let (env_var, example_version, higher_example_version) = match apple_os() { - "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"), + let (example_version, higher_example_version) = match apple_os() { + "macos" => ("12.0", "13.0"), // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0 - "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => { - ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0") - } - "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"), - "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"), - "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"), - "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"), + "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => ("10.0", "10.0"), + "ios" => ("15.0", "16.0"), + "watchos" => ("7.0", "9.0"), + "tvos" => ("14.0", "15.0"), + "visionos" => ("1.1", "1.2"), _ => unreachable!(), }; - let default_version = - rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8(); - let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim(); + + // Remove env vars to get `rustc`'s default + let output = rustc() + .target(target()) + .env_remove("MACOSX_DEPLOYMENT_TARGET") + .env_remove("IPHONEOS_DEPLOYMENT_TARGET") + .env_remove("WATCHOS_DEPLOYMENT_TARGET") + .env_remove("TVOS_DEPLOYMENT_TARGET") + .env_remove("XROS_DEPLOYMENT_TARGET") + .print("deployment-target") + .run() + .stdout_utf8(); + let (env_var, default_version) = output.split_once('=').unwrap(); + let env_var = env_var.trim(); + let default_version = default_version.trim(); // Test that version makes it to the object file. run_in_tmpdir(|| { diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs index 6463ec004035..43e805772043 100644 --- a/tests/run-make/apple-sdk-version/rmake.rs +++ b/tests/run-make/apple-sdk-version/rmake.rs @@ -26,8 +26,7 @@ fn main() { // Fetch rustc's inferred deployment target. let current_deployment_target = rustc().target(target()).print("deployment-target").run().stdout_utf8(); - let current_deployment_target = - current_deployment_target.strip_prefix("deployment_target=").unwrap().trim(); + let current_deployment_target = current_deployment_target.split('=').last().unwrap().trim(); // Fetch current SDK version via. xcrun. // diff --git a/tests/ui/print-request/macos-target.rs b/tests/ui/print-request/macos-target.rs index 197edd024746..af74babbed48 100644 --- a/tests/ui/print-request/macos-target.rs +++ b/tests/ui/print-request/macos-target.rs @@ -1,5 +1,6 @@ //@ only-apple //@ compile-flags: --print deployment-target +//@ normalize-stdout-test: "\w*_DEPLOYMENT_TARGET" -> "$$OS_DEPLOYMENT_TARGET" //@ normalize-stdout-test: "\d+\." -> "$$CURRENT_MAJOR_VERSION." //@ normalize-stdout-test: "\d+" -> "$$CURRENT_MINOR_VERSION" //@ check-pass diff --git a/tests/ui/print-request/macos-target.stdout b/tests/ui/print-request/macos-target.stdout index f55ef568ed67..34ade570969f 100644 --- a/tests/ui/print-request/macos-target.stdout +++ b/tests/ui/print-request/macos-target.stdout @@ -1 +1 @@ -deployment_target=$CURRENT_MAJOR_VERSION.$CURRENT_MINOR_VERSION +$OS_DEPLOYMENT_TARGET=$CURRENT_MAJOR_VERSION.$CURRENT_MINOR_VERSION From 45e1a3a6f413801519ccd0f1829ce51ecc836a44 Mon Sep 17 00:00:00 2001 From: Fridtjof Stoldt Date: Fri, 22 Nov 2024 20:47:47 +0000 Subject: [PATCH 080/330] Update CHANGELOG.md Co-authored-by: Philipp Krones --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fefd3e37e08..e9c8d222c555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,11 +41,11 @@ Current stable, released 2024-11-28 * Moved [`ref_option`] to `pedantic` (From `nursery`) [#13469](https://github.com/rust-lang/rust-clippy/pull/13469) -* Moved [`manual_c_str_literals`] to `complexity` (From `pedantic` now warn-by-default) +* Moved [`manual_c_str_literals`] to `complexity` (From `pedantic`, now warn-by-default) [#13263](https://github.com/rust-lang/rust-clippy/pull/13263) -* Moved [`empty_line_after_doc_comments`] to `suspicious` (From `nursery` now warn-by-default) +* Moved [`empty_line_after_doc_comments`] to `suspicious` (From `nursery`, now warn-by-default) [#13091](https://github.com/rust-lang/rust-clippy/pull/13091) -* Moved [`empty_line_after_outer_attr`] to `suspicious` (From `nursery` now warn-by-default) +* Moved [`empty_line_after_outer_attr`] to `suspicious` (From `nursery`, now warn-by-default) [#13091](https://github.com/rust-lang/rust-clippy/pull/13091) ### Enhancements From c31a097d7533a1df9435119e40f649b88a0d387e Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Fri, 22 Nov 2024 17:47:15 -0500 Subject: [PATCH 081/330] aix: create shim for lgammaf_r --- library/std/src/sys/cmath.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index 2997e908fa1b..829042381a24 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -26,6 +26,7 @@ extern "C" { pub fn tgamma(n: f64) -> f64; pub fn tgammaf(n: f32) -> f32; pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + #[cfg(not(target_os = "aix"))] pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; pub fn acosf128(n: f128) -> f128; @@ -56,13 +57,20 @@ extern "C" { }} } +// On AIX, we don't have lgammaf_r only the f64 version, so we can +// use the f64 version lgamma_r +#[cfg(target_os = "aix")] +pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { + lgamma_r(n.into(), s) as f32 +} + // On 32-bit x86 MSVC these functions aren't defined, so we just define shims // which promote everything to f64, perform the calculation, and then demote // back to f32. While not precisely correct should be "correct enough" for now. cfg_if::cfg_if! { if #[cfg(all(target_os = "windows", target_env = "msvc", target_arch = "x86"))] { #[inline] - pub unsafe fn acosf(n: f32) -> f32 { + pub unsafe fn acosf(n: f32) -> f32 { f64::acos(n as f64) as f32 } From dd920fa31de604e620cb8d46710823ccacd78abe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 01:37:49 +0000 Subject: [PATCH 082/330] Move pin ergonomics tests --- .../{pin-reborrow-arg.rs => pin-ergonomics/reborrow-arg.rs} | 0 .../reborrow-const-as-mut.rs} | 0 .../reborrow-const-as-mut.stderr} | 0 .../{pin-reborrow-once.rs => pin-ergonomics/reborrow-once.rs} | 0 .../reborrow-once.stderr} | 0 .../{pin-reborrow-self.rs => pin-ergonomics/reborrow-self.rs} | 0 .../reborrow-shorter.rs} | 0 .../{pin-sugar-ambiguity.rs => pin-ergonomics/sugar-ambiguity.rs} | 0 .../{pin-sugar-no-const.rs => pin-ergonomics/sugar-no-const.rs} | 0 .../sugar-no-const.stderr} | 0 tests/ui/async-await/{pin-sugar.rs => pin-ergonomics/sugar.rs} | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/async-await/{pin-reborrow-arg.rs => pin-ergonomics/reborrow-arg.rs} (100%) rename tests/ui/async-await/{pin-reborrow-const-as-mut.rs => pin-ergonomics/reborrow-const-as-mut.rs} (100%) rename tests/ui/async-await/{pin-reborrow-const-as-mut.stderr => pin-ergonomics/reborrow-const-as-mut.stderr} (100%) rename tests/ui/async-await/{pin-reborrow-once.rs => pin-ergonomics/reborrow-once.rs} (100%) rename tests/ui/async-await/{pin-reborrow-once.stderr => pin-ergonomics/reborrow-once.stderr} (100%) rename tests/ui/async-await/{pin-reborrow-self.rs => pin-ergonomics/reborrow-self.rs} (100%) rename tests/ui/async-await/{pin-reborrow-shorter.rs => pin-ergonomics/reborrow-shorter.rs} (100%) rename tests/ui/async-await/{pin-sugar-ambiguity.rs => pin-ergonomics/sugar-ambiguity.rs} (100%) rename tests/ui/async-await/{pin-sugar-no-const.rs => pin-ergonomics/sugar-no-const.rs} (100%) rename tests/ui/async-await/{pin-sugar-no-const.stderr => pin-ergonomics/sugar-no-const.stderr} (100%) rename tests/ui/async-await/{pin-sugar.rs => pin-ergonomics/sugar.rs} (100%) diff --git a/tests/ui/async-await/pin-reborrow-arg.rs b/tests/ui/async-await/pin-ergonomics/reborrow-arg.rs similarity index 100% rename from tests/ui/async-await/pin-reborrow-arg.rs rename to tests/ui/async-await/pin-ergonomics/reborrow-arg.rs diff --git a/tests/ui/async-await/pin-reborrow-const-as-mut.rs b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.rs similarity index 100% rename from tests/ui/async-await/pin-reborrow-const-as-mut.rs rename to tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.rs diff --git a/tests/ui/async-await/pin-reborrow-const-as-mut.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr similarity index 100% rename from tests/ui/async-await/pin-reborrow-const-as-mut.stderr rename to tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr diff --git a/tests/ui/async-await/pin-reborrow-once.rs b/tests/ui/async-await/pin-ergonomics/reborrow-once.rs similarity index 100% rename from tests/ui/async-await/pin-reborrow-once.rs rename to tests/ui/async-await/pin-ergonomics/reborrow-once.rs diff --git a/tests/ui/async-await/pin-reborrow-once.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr similarity index 100% rename from tests/ui/async-await/pin-reborrow-once.stderr rename to tests/ui/async-await/pin-ergonomics/reborrow-once.stderr diff --git a/tests/ui/async-await/pin-reborrow-self.rs b/tests/ui/async-await/pin-ergonomics/reborrow-self.rs similarity index 100% rename from tests/ui/async-await/pin-reborrow-self.rs rename to tests/ui/async-await/pin-ergonomics/reborrow-self.rs diff --git a/tests/ui/async-await/pin-reborrow-shorter.rs b/tests/ui/async-await/pin-ergonomics/reborrow-shorter.rs similarity index 100% rename from tests/ui/async-await/pin-reborrow-shorter.rs rename to tests/ui/async-await/pin-ergonomics/reborrow-shorter.rs diff --git a/tests/ui/async-await/pin-sugar-ambiguity.rs b/tests/ui/async-await/pin-ergonomics/sugar-ambiguity.rs similarity index 100% rename from tests/ui/async-await/pin-sugar-ambiguity.rs rename to tests/ui/async-await/pin-ergonomics/sugar-ambiguity.rs diff --git a/tests/ui/async-await/pin-sugar-no-const.rs b/tests/ui/async-await/pin-ergonomics/sugar-no-const.rs similarity index 100% rename from tests/ui/async-await/pin-sugar-no-const.rs rename to tests/ui/async-await/pin-ergonomics/sugar-no-const.rs diff --git a/tests/ui/async-await/pin-sugar-no-const.stderr b/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr similarity index 100% rename from tests/ui/async-await/pin-sugar-no-const.stderr rename to tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr diff --git a/tests/ui/async-await/pin-sugar.rs b/tests/ui/async-await/pin-ergonomics/sugar.rs similarity index 100% rename from tests/ui/async-await/pin-sugar.rs rename to tests/ui/async-await/pin-ergonomics/sugar.rs From 9455373d203addf6f34fc8ee25a9ee5211314dcb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 01:41:14 +0000 Subject: [PATCH 083/330] Don't type error if we fail to coerce Pin because it doesnt contain a ref --- compiler/rustc_hir_typeck/src/coercion.rs | 11 ++++++++--- .../pin-ergonomics/coerce-non-pointer-pin.rs | 10 ++++++++++ .../pin-ergonomics/coerce-non-pointer-pin.stderr | 11 +++++++++++ .../pin-ergonomics/reborrow-const-as-mut.stderr | 4 ++-- .../async-await/pin-ergonomics/reborrow-once.stderr | 2 +- .../async-await/pin-ergonomics/sugar-no-const.stderr | 2 +- 6 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs create mode 100644 tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 11e03229265a..bf41dcbe4a36 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -215,7 +215,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - // Examine the supertype and consider auto-borrowing. + // Examine the supertype and consider type-specific coercions, such + // as auto-borrowing, coercing pointer mutability, a `dyn*` coercion, + // or pin-ergonomics. match *b.kind() { ty::RawPtr(_, b_mutbl) => { return self.coerce_unsafe_ptr(a, b, b_mutbl); @@ -230,7 +232,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if self.tcx.features().pin_ergonomics() && self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => { - return self.coerce_pin(a, b); + let pin_coerce = self.commit_if_ok(|_| self.coerce_pin_ref(a, b)); + if pin_coerce.is_ok() { + return pin_coerce; + } } _ => {} } @@ -797,7 +802,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { /// - `Pin>` as `Pin<&T>` /// - `Pin>` as `Pin<&mut T>` #[instrument(skip(self), level = "trace")] - fn coerce_pin(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { + fn coerce_pin_ref(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { // We need to make sure the two types are compatible for coercion. // Then we will build a ReborrowPin adjustment and return that as an InferOk. diff --git a/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs new file mode 100644 index 000000000000..a95665f126d1 --- /dev/null +++ b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.rs @@ -0,0 +1,10 @@ +//@ check-pass + +#![feature(pin_ergonomics)] +//~^ WARN the feature `pin_ergonomics` is incomplete + +use std::pin::Pin; + +fn main() { + let _: Pin> = Box::pin(()); +} diff --git a/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr new file mode 100644 index 000000000000..2deb5b09884c --- /dev/null +++ b/tests/ui/async-await/pin-ergonomics/coerce-non-pointer-pin.stderr @@ -0,0 +1,11 @@ +warning: the feature `pin_ergonomics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/coerce-non-pointer-pin.rs:3:12 + | +LL | #![feature(pin_ergonomics)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #130494 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr index 2c2d9ec27174..36bbf1c493ab 100644 --- a/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr +++ b/tests/ui/async-await/pin-ergonomics/reborrow-const-as-mut.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pin-reborrow-const-as-mut.rs:14:9 + --> $DIR/reborrow-const-as-mut.rs:14:9 | LL | foo(x); | --- ^ types differ in mutability @@ -9,7 +9,7 @@ LL | foo(x); = note: expected struct `Pin<&mut Foo>` found struct `Pin<&Foo>` note: function defined here - --> $DIR/pin-reborrow-const-as-mut.rs:10:4 + --> $DIR/reborrow-const-as-mut.rs:10:4 | LL | fn foo(_: Pin<&mut Foo>) { | ^^^ ---------------- diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr index b8fde8ffee89..a1ea2b4a57a7 100644 --- a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr +++ b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `*x.__pointer` as mutable more than once at a time - --> $DIR/pin-reborrow-once.rs:12:14 + --> $DIR/reborrow-once.rs:12:14 | LL | twice(x, x); | ----- - ^ second mutable borrow occurs here diff --git a/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr b/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr index 5f01156c1f0a..822cfffcb8c6 100644 --- a/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr +++ b/tests/ui/async-await/pin-ergonomics/sugar-no-const.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `::`, `;`, `<`, or `=`, found `i32` - --> $DIR/pin-sugar-no-const.rs:7:18 + --> $DIR/sugar-no-const.rs:7:18 | LL | let _x: &pin i32 = todo!(); | - ^^^ expected one of `!`, `(`, `::`, `;`, `<`, or `=` From 50fb40a987746e8847091ce354b649be4a44cde1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 05:24:39 +0000 Subject: [PATCH 084/330] Delay a bug when encountering an impl with unconstrained generics in codegen_select --- compiler/rustc_traits/src/codegen.rs | 21 +++++++++++++------ tests/crashes/126646.rs | 18 ---------------- .../resolve-impl-before-constrain-check.rs | 20 ++++++++++++++++++ ...resolve-impl-before-constrain-check.stderr | 9 ++++++++ 4 files changed, 44 insertions(+), 24 deletions(-) delete mode 100644 tests/crashes/126646.rs create mode 100644 tests/ui/traits/resolve-impl-before-constrain-check.rs create mode 100644 tests/ui/traits/resolve-impl-before-constrain-check.stderr diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 57225df0819d..e5276e6d5158 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -74,12 +74,21 @@ pub(crate) fn codegen_select_candidate<'tcx>( } let impl_source = infcx.resolve_vars_if_possible(impl_source); - let impl_source = infcx.tcx.erase_regions(impl_source); - if impl_source.has_infer() { - // Unused lifetimes on an impl get replaced with inference vars, but never resolved, - // causing the return value of a query to contain inference vars. We do not have a concept - // for this and will in fact ICE in stable hashing of the return value. So bail out instead. - infcx.tcx.dcx().has_errors().unwrap(); + let impl_source = tcx.erase_regions(impl_source); + if impl_source.has_non_region_infer() { + // Unused generic types or consts on an impl get replaced with inference vars, + // but never resolved, causing the return value of a query to contain inference + // vars. We do not have a concept for this and will in fact ICE in stable hashing + // of the return value. So bail out instead. + match impl_source { + ImplSource::UserDefined(impl_) => { + tcx.dcx().span_delayed_bug( + tcx.def_span(impl_.impl_def_id), + "this impl has unconstrained generic parameters", + ); + } + _ => unreachable!(), + } return Err(CodegenObligationError::FulfillmentError); } diff --git a/tests/crashes/126646.rs b/tests/crashes/126646.rs deleted file mode 100644 index 24e3530320a8..000000000000 --- a/tests/crashes/126646.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: rust-lang/rust#126646 -mod foo { - pub trait Callable { - type Output; - fn call() -> Self::Output; - } - - impl<'a, V: ?Sized> Callable for &'a () { - type Output = (); - } -} -use foo::*; - -fn test<'a>() -> impl Sized { - <&'a () as Callable>::call() -} - -fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.rs b/tests/ui/traits/resolve-impl-before-constrain-check.rs new file mode 100644 index 000000000000..87f9c241e402 --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.rs @@ -0,0 +1,20 @@ +// Need a different module so we try to build the mir for `test` +// before analyzing `mod foo`. + +mod foo { + pub trait Callable { + fn call(); + } + + impl Callable for () { + //~^ ERROR the type parameter `V` is not constrained by the impl trait, self type, or predicates + fn call() {} + } +} +use foo::*; + +fn test() -> impl Sized { + <() as Callable>::call() +} + +fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr new file mode 100644 index 000000000000..e8e569ba625e --- /dev/null +++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates + --> $DIR/resolve-impl-before-constrain-check.rs:9:10 + | +LL | impl Callable for () { + | ^ unconstrained type parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0207`. From 1931fb825bb18a4bf6f2af6e0249dcf72119c263 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 Nov 2024 08:05:19 +0100 Subject: [PATCH 085/330] remove is_trivially_const_drop --- clippy_utils/src/qualify_min_const_fn.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 345c46f944a5..3c9ea4bfaf44 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -404,12 +404,11 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> // FIXME(const_trait_impl, fee1-dead) revert to const destruct once it works again #[expect(unused)] fn is_ty_const_destruct_unused<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { - // Avoid selecting for simple cases, such as builtin types. - if ty::util::is_trivially_const_drop(ty) { - return true; + // If this doesn't need drop at all, then don't select `~const Destruct`. + if !ty.needs_drop(tcx, body.typing_env(tcx)) { + return false; } - let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(body.typing_env(tcx)); // FIXME(const_trait_impl) constness From 78fa111a48001abf372911b50d7d7ed25424d489 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 20 Nov 2024 11:31:49 +0100 Subject: [PATCH 086/330] no more Reveal :( --- clippy_lints/src/derive.rs | 2 -- clippy_utils/src/ty.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 3b6b3c89858b..1a34b87e42a2 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -11,7 +11,6 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::traits::Reveal; use rustc_middle::ty::{ self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, TraitPredicate, Ty, TyCtxt, Upcast, }; @@ -516,7 +515,6 @@ fn typing_env_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId .upcast(tcx) }), )), - Reveal::UserFacing, ); ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index 3498606dfd39..03e1a814a860 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -575,7 +575,7 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// Checks if a given type looks safe to be uninitialized. pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - let typing_env = cx.typing_env().with_reveal_all_normalized(cx.tcx); + let typing_env = cx.typing_env().with_post_analysis_normalized(cx.tcx); cx.tcx .check_validity_requirement((ValidityRequirement::Uninit, typing_env.as_query_input(ty))) .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty)) From a3efe3bc29abbb70da0c2836eef769e40c85dfe9 Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Sat, 23 Nov 2024 13:46:40 -0500 Subject: [PATCH 087/330] Update request entry point file path in architecture.md --- src/tools/rust-analyzer/docs/dev/architecture.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/dev/architecture.md b/src/tools/rust-analyzer/docs/dev/architecture.md index 6aa57b2f9be9..9c9e05a429bf 100644 --- a/src/tools/rust-analyzer/docs/dev/architecture.md +++ b/src/tools/rust-analyzer/docs/dev/architecture.md @@ -42,7 +42,7 @@ The underlying engine makes sure that model is computed lazily (on-demand) and c `crates/rust-analyzer/src/bin/main.rs` contains the main function which spawns LSP. This is *the* entry point, but it front-loads a lot of complexity, so it's fine to just skim through it. -`crates/rust-analyzer/src/handlers/requests.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. +`crates/rust-analyzer/src/handlers/request.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. `Analysis` and `AnalysisHost` types define the main API for consumers of IDE services. From 80df2c4cede1ac58eac55c3d50b72f34dae6c65f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Nov 2024 19:38:44 +0100 Subject: [PATCH 088/330] Use a better description of an internal function --- clippy_utils/src/hir_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index c73ab4bfa688..205c921f7cf3 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -732,7 +732,7 @@ pub fn over(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) - left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) } -/// Counts how many elements of the slices are equal as per `eq_fn`. +/// Counts how many elements at the beginning of the slices are equal as per `eq_fn`. pub fn count_eq( left: &mut dyn Iterator, right: &mut dyn Iterator, From e73e9f9af202206372d1fc0bbe215aad376c0482 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 23 Nov 2024 14:31:20 -0500 Subject: [PATCH 089/330] Add simd_relaxed_fma intrinsic --- .../rustc_codegen_cranelift/src/intrinsics/simd.rs | 3 ++- compiler/rustc_codegen_gcc/src/intrinsic/simd.rs | 1 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 ++ compiler/rustc_hir_analysis/src/check/intrinsic.rs | 4 +++- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/simd.rs | 10 ++++++++++ tests/ui/simd/intrinsic/float-math-pass.rs | 4 ++++ 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index f787b8a6fd94..e0ebe30752af 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -415,7 +415,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - sym::simd_fma => { + // FIXME: simd_relaxed_fma doesn't relax to non-fused multiply-add + sym::simd_fma | sym::simd_relaxed_fma => { intrinsic_args!(fx, args => (a, b, c); intrinsic); if !a.layout().ty.is_simd() { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 604678a9af4c..79d1a06dd467 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -772,6 +772,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_flog => "log", sym::simd_floor => "floor", sym::simd_fma => "fma", + sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary sym::simd_fpowi => "__builtin_powi", sym::simd_fpow => "pow", sym::simd_fsin => "sin", diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index da7f94e8cf71..d8b055137b35 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1534,6 +1534,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), + sym::simd_relaxed_fma => ("fmuladd", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), @@ -1572,6 +1573,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( | sym::simd_fpowi | sym::simd_fsin | sym::simd_fsqrt + | sym::simd_relaxed_fma | sym::simd_round | sym::simd_trunc ) { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 3e33120901f6..7434bbf180b9 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -641,7 +641,9 @@ pub fn check_intrinsic_type( | sym::simd_round | sym::simd_trunc => (1, 0, vec![param(0)], param(0)), sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)), - sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)), + sym::simd_fma | sym::simd_relaxed_fma => { + (1, 0, vec![param(0), param(0), param(0)], param(0)) + } sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)), sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)), sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3d0ec2afa2b7..17b6c5d41d2a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1840,6 +1840,7 @@ symbols! { simd_reduce_mul_unordered, simd_reduce_or, simd_reduce_xor, + simd_relaxed_fma, simd_rem, simd_round, simd_saturating_add, diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 5ddca9c4dce8..945bbe34df31 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -612,6 +612,16 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn simd_fma(x: T, y: T, z: T) -> T; + /// Computes `(x*y) + z` for each element, with unspecified rounding. + /// + /// This may be equivalent to `simd_fma`, or it may relax to rounding each + /// operation if that's more efficient. + /// + /// `T` must be a vector of floats. + #[cfg(not(bootstrap))] + #[rustc_nounwind] + pub fn simd_relaxed_fma(x: T, y: T, z: T) -> T; + // Computes the sine of each element. /// /// `T` must be a vector of floats. diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs index 9b14d410acbe..24b9941133ee 100644 --- a/tests/ui/simd/intrinsic/float-math-pass.rs +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -23,6 +23,7 @@ extern "rust-intrinsic" { fn simd_fexp(x: T) -> T; fn simd_fexp2(x: T) -> T; fn simd_fma(x: T, y: T, z: T) -> T; + fn simd_relaxed_fma(x: T, y: T, z: T) -> T; fn simd_flog(x: T) -> T; fn simd_flog10(x: T) -> T; fn simd_flog2(x: T) -> T; @@ -77,6 +78,9 @@ fn main() { let r = simd_fma(x, h, h); assert_approx_eq!(x, r); + let r = simd_relaxed_fma(x, h, h); + assert_approx_eq!(x, r); + let r = simd_fsqrt(x); assert_approx_eq!(x, r); From 9fd8e99d91f7029016b9097d1311c1045f35667f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Nov 2024 19:22:01 +0100 Subject: [PATCH 090/330] Prevent ICE in case of a bound constraint on generic argument --- clippy_utils/src/hir_utils.rs | 11 ++++++----- tests/ui/trait_duplication_in_bounds.fixed | 17 ++++++++++++++++- tests/ui/trait_duplication_in_bounds.rs | 17 ++++++++++++++++- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index c73ab4bfa688..7bc708366511 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -603,11 +603,7 @@ impl HirEqInterExpr<'_, '_, '_> { } fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool { - left.ident.name == right.ident.name - && self.eq_ty( - left.ty().expect("expected assoc type binding"), - right.ty().expect("expected assoc type binding"), - ) + left.ident.name == right.ident.name && both_some_and(left.ty(), right.ty(), |l, r| self.eq_ty(l, r)) } fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool { @@ -727,6 +723,11 @@ pub fn both(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bo .map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y))) } +/// Checks if the two `Option`s are both `Some` and pass the predicate function. +pub fn both_some_and(l: Option, r: Option, mut pred: impl FnMut(X, Y) -> bool) -> bool { + l.is_some_and(|l| r.is_some_and(|r| pred(l, r))) +} + /// Checks if two slices are equal as per `eq_fn`. pub fn over(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool { left.len() == right.len() && left.iter().zip(right).all(|(x, y)| eq_fn(x, y)) diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed index 779431303aed..e57c79553c30 100644 --- a/tests/ui/trait_duplication_in_bounds.fixed +++ b/tests/ui/trait_duplication_in_bounds.fixed @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![allow(unused)] -#![feature(const_trait_impl)] +#![feature(associated_const_equality, const_trait_impl)] use std::any::Any; @@ -179,3 +179,18 @@ fn main() { let _x: fn(_) = f::<()>; let _x: fn(_) = f::; } + +// #13706 +fn assoc_tys_bounds() +where + T: Iterator + Iterator, +{ +} +trait AssocConstTrait { + const ASSOC: usize; +} +fn assoc_const_args() +where + T: AssocConstTrait + AssocConstTrait, +{ +} diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index 3e974dc0a8f2..ee84d3c30118 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![allow(unused)] -#![feature(const_trait_impl)] +#![feature(associated_const_equality, const_trait_impl)] use std::any::Any; @@ -179,3 +179,18 @@ fn main() { let _x: fn(_) = f::<()>; let _x: fn(_) = f::; } + +// #13706 +fn assoc_tys_bounds() +where + T: Iterator + Iterator, +{ +} +trait AssocConstTrait { + const ASSOC: usize; +} +fn assoc_const_args() +where + T: AssocConstTrait + AssocConstTrait, +{ +} From 943c3bc3db590b8549f76eee814bef58b68a37f8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 23 Nov 2024 17:10:08 -0700 Subject: [PATCH 091/330] Add note about caveat for `cfg(doc)` For example, we definitely wouldn't want to do this in libcore. --- clippy_lints/src/doc/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index fd6ae21a5f85..993335e8248c 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -539,11 +539,15 @@ declare_clippy_lint! { /// ### What it does /// Checks if included files in doc comments are included only for `cfg(doc)`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// These files are not useful for compilation but will still be included. /// Also, if any of these non-source code file is updated, it will trigger a /// recompilation. /// + /// Excluding this will currently result in the file being left out if + /// the item's docs are inlined from another crate. This may be fixed in a + /// future version of rustdoc. + /// /// ### Example /// ```ignore /// #![doc = include_str!("some_file.md")] @@ -554,7 +558,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.84.0"] pub DOC_INCLUDE_WITHOUT_CFG, - pedantic, + restriction, "check if files included in documentation are behind `cfg(doc)`" } From 402f6a3530e23b5c822bae0ba10ea1bb4bd55047 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 23 Nov 2024 19:17:27 -0500 Subject: [PATCH 092/330] Match simd_relaxed_fma documentation to fmuladd intrinsic --- library/core/src/intrinsics/simd.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 945bbe34df31..0d24b0558c59 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -612,10 +612,14 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn simd_fma(x: T, y: T, z: T) -> T; - /// Computes `(x*y) + z` for each element, with unspecified rounding. + /// Computes `(x*y) + z` for each element, non-deterministically executing either + /// a fused multiply-add or two operations with rounding of the intermediate result. /// - /// This may be equivalent to `simd_fma`, or it may relax to rounding each - /// operation if that's more efficient. + /// The operation is fused if the code generator determines that target instruction + /// set has support for a fused operation, and that the fused operation is more efficient + /// than the equivalent, separate pair of mul and add instructions. It is unspecified + /// whether or not a fused operation is selected, and that may depend on optimization + /// level and context, for example. /// /// `T` must be a vector of floats. #[cfg(not(bootstrap))] From 45791dde8e0d258d794e561b9dff53f1dbb16377 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 24 Nov 2024 01:20:28 +0100 Subject: [PATCH 093/330] Support linker arguments that contain commas --- compiler/rustc_codegen_ssa/src/back/linker.rs | 51 +++++++++++++++---- .../src/back/linker/tests.rs | 25 +++++++++ 2 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/back/linker/tests.rs diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 6ee599c9964c..162ea38dfd5c 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -24,6 +24,9 @@ use super::command::Command; use super::symbol_export; use crate::errors; +#[cfg(test)] +mod tests; + /// Disables non-English messages from localized linkers. /// Such messages may cause issues with text encoding on Windows (#35785) /// and prevent inspection of linker output in case of errors, which we occasionally do. @@ -178,23 +181,53 @@ fn verbatim_args( } l } +/// Add underlying linker arguments to C compiler command, by wrapping them in +/// `-Wl` or `-Xlinker`. +fn convert_link_args_to_cc_args( + cmd: &mut Command, + args: impl IntoIterator, IntoIter: ExactSizeIterator>, +) { + let args = args.into_iter(); + if args.len() == 0 { + return; + } + + let mut combined_arg = OsString::from("-Wl"); + for arg in args { + // If the argument itself contains a comma, we need to emit it + // as `-Xlinker`, otherwise we can use `-Wl`. + if arg.as_ref().as_encoded_bytes().contains(&b',') { + // Emit current `-Wl` argument, if any has been built. + if combined_arg != OsStr::new("-Wl") { + cmd.arg(combined_arg); + // Begin next `-Wl` argument. + combined_arg = OsString::from("-Wl"); + } + + // Emit `-Xlinker` argument. + cmd.arg("-Xlinker"); + cmd.arg(arg); + } else { + // Append to `-Wl` argument. + combined_arg.push(","); + combined_arg.push(arg); + } + } + // Emit final `-Wl` argument. + if combined_arg != OsStr::new("-Wl") { + cmd.arg(combined_arg); + } +} /// Arguments for the underlying linker. /// Add options to pass them through cc wrapper if `Linker` is a cc wrapper. fn link_args( l: &mut L, args: impl IntoIterator, IntoIter: ExactSizeIterator>, ) -> &mut L { - let args = args.into_iter(); if !l.is_cc() { verbatim_args(l, args); - } else if args.len() != 0 { - // FIXME: Support arguments with commas, see `rpaths_to_flags` for the example. - let mut combined_arg = OsString::from("-Wl"); - for arg in args { - combined_arg.push(","); - combined_arg.push(arg); - } - l.cmd().arg(combined_arg); + } else { + convert_link_args_to_cc_args(l.cmd(), args); } l } diff --git a/compiler/rustc_codegen_ssa/src/back/linker/tests.rs b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs new file mode 100644 index 000000000000..293ed6634ae1 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs @@ -0,0 +1,25 @@ +use super::*; + +#[test] +fn test_xlinker() { + let mut cmd = Command::new("foo"); + convert_link_args_to_cc_args(&mut cmd, &[ + "arg1", + "arg2", + "arg3,with,comma", + "arg4,with,comma", + "arg5", + "arg6,with,comma", + ]); + + assert_eq!(cmd.get_args(), [ + OsStr::new("-Wl,arg1,arg2"), + OsStr::new("-Xlinker"), + OsStr::new("arg3,with,comma"), + OsStr::new("-Xlinker"), + OsStr::new("arg4,with,comma"), + OsStr::new("-Wl,arg5"), + OsStr::new("-Xlinker"), + OsStr::new("arg6,with,comma"), + ]); +} From cb6f8fa422ce14b82b60af79d0f0d0ad80936ecd Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 13 Nov 2024 00:27:14 +0100 Subject: [PATCH 094/330] Support rpath with -Clinker-flavor=ld Using `cc_args` panics when using `-Clinker-flavor=ld`, because the arguments are in a form tailored for `-Clinker-flavor=gcc`. So instead, we use `link_args` and let that wrap the arguments with the appropriate `-Wl` or `-Xlinker` when needed. --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +-- .../src/back/linker/tests.rs | 7 ++++ compiler/rustc_codegen_ssa/src/back/rpath.rs | 34 ++++++------------- .../rustc_codegen_ssa/src/back/rpath/tests.rs | 23 +------------ 4 files changed, 21 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 5149e3a12f23..ea184bb16aa9 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1384,7 +1384,7 @@ fn link_sanitizer_runtime( let filename = format!("rustc{channel}_rt.{name}"); let path = find_sanitizer_runtime(sess, &filename); let rpath = path.to_str().expect("non-utf8 component in path"); - linker.cc_args(&["-Wl,-rpath", "-Xlinker", rpath]); + linker.link_args(&["-rpath", rpath]); linker.link_dylib_by_name(&filename, false, true); } else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" { // MSVC provides the `/INFERASANLIBS` argument to automatically find the @@ -2208,7 +2208,7 @@ fn add_rpath_args( is_like_osx: sess.target.is_like_osx, linker_is_gnu: sess.target.linker_flavor.is_gnu(), }; - cmd.cc_args(&rpath::get_rpath_flags(&rpath_config)); + cmd.link_args(&rpath::get_rpath_linker_args(&rpath_config)); } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker/tests.rs b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs index 293ed6634ae1..bf3e8c902009 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker/tests.rs @@ -1,5 +1,12 @@ use super::*; +#[test] +fn test_rpaths_to_args() { + let mut cmd = Command::new("foo"); + convert_link_args_to_cc_args(&mut cmd, &["-rpath", "path1", "-rpath", "path2"]); + assert_eq!(cmd.get_args(), [OsStr::new("-Wl,-rpath,path1,-rpath,path2")]); +} + #[test] fn test_xlinker() { let mut cmd = Command::new("foo"); diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index 56a808df6b0b..d633cc98ac87 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -13,39 +13,27 @@ pub(super) struct RPathConfig<'a> { pub linker_is_gnu: bool, } -pub(super) fn get_rpath_flags(config: &RPathConfig<'_>) -> Vec { +pub(super) fn get_rpath_linker_args(config: &RPathConfig<'_>) -> Vec { debug!("preparing the RPATH!"); let rpaths = get_rpaths(config); - let mut flags = rpaths_to_flags(rpaths); + let mut args = Vec::with_capacity(rpaths.len() * 2); // the minimum needed capacity + + for rpath in rpaths { + args.push("-rpath".into()); + args.push(rpath); + } if config.linker_is_gnu { // Use DT_RUNPATH instead of DT_RPATH if available - flags.push("-Wl,--enable-new-dtags".into()); + args.push("--enable-new-dtags".into()); // Set DF_ORIGIN for substitute $ORIGIN - flags.push("-Wl,-z,origin".into()); + args.push("-z".into()); + args.push("origin".into()); } - flags -} - -fn rpaths_to_flags(rpaths: Vec) -> Vec { - let mut ret = Vec::with_capacity(rpaths.len()); // the minimum needed capacity - - for rpath in rpaths { - if rpath.to_string_lossy().contains(',') { - ret.push("-Wl,-rpath".into()); - ret.push("-Xlinker".into()); - ret.push(rpath); - } else { - let mut single_arg = OsString::from("-Wl,-rpath,"); - single_arg.push(rpath); - ret.push(single_arg); - } - } - - ret + args } fn get_rpaths(config: &RPathConfig<'_>) -> Vec { diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index 39034842d108..f1a30105c590 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -1,13 +1,4 @@ -use std::ffi::OsString; -use std::path::{Path, PathBuf}; - -use super::{RPathConfig, get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags}; - -#[test] -fn test_rpaths_to_flags() { - let flags = rpaths_to_flags(vec!["path1".into(), "path2".into()]); - assert_eq!(flags, ["-Wl,-rpath,path1", "-Wl,-rpath,path2"]); -} +use super::*; #[test] fn test_minimize1() { @@ -69,15 +60,3 @@ fn test_rpath_relative_issue_119571() { // Should not panic when lib only contains filename. let _ = get_rpath_relative_to_output(config, Path::new("libstd.so")); } - -#[test] -fn test_xlinker() { - let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]); - - assert_eq!(args, vec![ - OsString::from("-Wl,-rpath,a/normal/path"), - OsString::from("-Wl,-rpath"), - OsString::from("-Xlinker"), - OsString::from("a,comma,path") - ]); -} From 6bbf832cf266e48c1e8773e5d64a7e90bd866c7b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 24 Nov 2024 01:23:19 +0100 Subject: [PATCH 095/330] Remove unnecessary 0 link args optimization --- compiler/rustc_codegen_ssa/src/back/linker.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 162ea38dfd5c..05dfbd40a0ad 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -183,15 +183,7 @@ fn verbatim_args( } /// Add underlying linker arguments to C compiler command, by wrapping them in /// `-Wl` or `-Xlinker`. -fn convert_link_args_to_cc_args( - cmd: &mut Command, - args: impl IntoIterator, IntoIter: ExactSizeIterator>, -) { - let args = args.into_iter(); - if args.len() == 0 { - return; - } - +fn convert_link_args_to_cc_args(cmd: &mut Command, args: impl IntoIterator>) { let mut combined_arg = OsString::from("-Wl"); for arg in args { // If the argument itself contains a comma, we need to emit it @@ -220,10 +212,7 @@ fn convert_link_args_to_cc_args( } /// Arguments for the underlying linker. /// Add options to pass them through cc wrapper if `Linker` is a cc wrapper. -fn link_args( - l: &mut L, - args: impl IntoIterator, IntoIter: ExactSizeIterator>, -) -> &mut L { +fn link_args(l: &mut L, args: impl IntoIterator>) -> &mut L { if !l.is_cc() { verbatim_args(l, args); } else { @@ -257,7 +246,7 @@ macro_rules! generate_arg_methods { verbatim_args(self, iter::once(arg)) } #[allow(unused)] - pub(crate) fn link_args(&mut self, args: impl IntoIterator, IntoIter: ExactSizeIterator>) -> &mut Self { + pub(crate) fn link_args(&mut self, args: impl IntoIterator>) -> &mut Self { link_args(self, args) } #[allow(unused)] From 5eb65530033817f3007d016e34cea5077f4d723d Mon Sep 17 00:00:00 2001 From: "aaishwarymishra@gmail.com" Date: Sat, 16 Nov 2024 19:40:39 +0530 Subject: [PATCH 096/330] changes old intrinsic declaration to new declaration blesses tests/ui/intrinsics blesses tests/ui/intrinsics --- library/core/src/intrinsics/mod.rs | 1544 ++++++++++++-------- tests/ui/intrinsics/reify-intrinsic.stderr | 2 +- 2 files changed, 950 insertions(+), 596 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index e9859a58696d..ee4bf12d0df0 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2039,628 +2039,982 @@ pub fn ptr_mask(_ptr: *const T, _mask: usize) -> *const T { unreachable!() } -extern "rust-intrinsic" { - /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with - /// a size of `count` * `size_of::()` and an alignment of - /// `min_align_of::()` - /// - /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: usize); - /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with - /// a size of `count * size_of::()` and an alignment of - /// `min_align_of::()` - /// - /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); - /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a - /// size of `count * size_of::()` and an alignment of - /// `min_align_of::()`. - /// - /// The volatile parameter is set to `true`, so it will not be optimized out - /// unless size is equal to zero. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn volatile_set_memory(dst: *mut T, val: u8, count: usize); +/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with +/// a size of `count` * `size_of::()` and an alignment of +/// `min_align_of::()` +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_copy_nonoverlapping_memory(_dst: *mut T, _src: *const T, _count: usize) { + unreachable!() +} +/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with +/// a size of `count * size_of::()` and an alignment of +/// `min_align_of::()` +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_copy_memory(_dst: *mut T, _src: *const T, _count: usize) { + unreachable!() +} +/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a +/// size of `count * size_of::()` and an alignment of +/// `min_align_of::()`. +/// +/// The volatile parameter is set to `true`, so it will not be optimized out +/// unless size is equal to zero. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_set_memory(_dst: *mut T, _val: u8, _count: usize) { + unreachable!() +} - /// Performs a volatile load from the `src` pointer. - /// - /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. - #[rustc_nounwind] - pub fn volatile_load(src: *const T) -> T; - /// Performs a volatile store to the `dst` pointer. - /// - /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. - #[rustc_nounwind] - pub fn volatile_store(dst: *mut T, val: T); +/// Performs a volatile load from the `src` pointer. +/// +/// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_load(_src: *const T) -> T { + unreachable!() +} +/// Performs a volatile store to the `dst` pointer. +/// +/// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn volatile_store(_dst: *mut T, _val: T) { + unreachable!() +} - /// Performs a volatile load from the `src` pointer - /// The pointer is not required to be aligned. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] - pub fn unaligned_volatile_load(src: *const T) -> T; - /// Performs a volatile store to the `dst` pointer. - /// The pointer is not required to be aligned. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] - pub fn unaligned_volatile_store(dst: *mut T, val: T); +/// Performs a volatile load from the `src` pointer +/// The pointer is not required to be aligned. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"] +pub unsafe fn unaligned_volatile_load(_src: *const T) -> T { + unreachable!() +} +/// Performs a volatile store to the `dst` pointer. +/// The pointer is not required to be aligned. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"] +pub unsafe fn unaligned_volatile_store(_dst: *mut T, _val: T) { + unreachable!() +} - /// Returns the square root of an `f16` - /// - /// The stabilized version of this intrinsic is - /// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf16(x: f16) -> f16; - /// Returns the square root of an `f32` - /// - /// The stabilized version of this intrinsic is - /// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf32(x: f32) -> f32; - /// Returns the square root of an `f64` - /// - /// The stabilized version of this intrinsic is - /// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf64(x: f64) -> f64; - /// Returns the square root of an `f128` - /// - /// The stabilized version of this intrinsic is - /// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt) - #[rustc_nounwind] - pub fn sqrtf128(x: f128) -> f128; +/// Returns the square root of an `f16` +/// +/// The stabilized version of this intrinsic is +/// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the square root of an `f32` +/// +/// The stabilized version of this intrinsic is +/// [`f32::sqrt`](../../std/primitive.f32.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the square root of an `f64` +/// +/// The stabilized version of this intrinsic is +/// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the square root of an `f128` +/// +/// The stabilized version of this intrinsic is +/// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sqrtf128(_x: f128) -> f128 { + unreachable!() +} - /// Raises an `f16` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f16::powi`](../../std/primitive.f16.html#method.powi) - #[rustc_nounwind] - pub fn powif16(a: f16, x: i32) -> f16; - /// Raises an `f32` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f32::powi`](../../std/primitive.f32.html#method.powi) - #[rustc_nounwind] - pub fn powif32(a: f32, x: i32) -> f32; - /// Raises an `f64` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f64::powi`](../../std/primitive.f64.html#method.powi) - #[rustc_nounwind] - pub fn powif64(a: f64, x: i32) -> f64; - /// Raises an `f128` to an integer power. - /// - /// The stabilized version of this intrinsic is - /// [`f128::powi`](../../std/primitive.f128.html#method.powi) - #[rustc_nounwind] - pub fn powif128(a: f128, x: i32) -> f128; +/// Raises an `f16` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f16::powi`](../../std/primitive.f16.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif16(_a: f16, _x: i32) -> f16 { + unreachable!() +} +/// Raises an `f32` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f32::powi`](../../std/primitive.f32.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif32(_a: f32, _x: i32) -> f32 { + unreachable!() +} +/// Raises an `f64` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f64::powi`](../../std/primitive.f64.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif64(_a: f64, _x: i32) -> f64 { + unreachable!() +} +/// Raises an `f128` to an integer power. +/// +/// The stabilized version of this intrinsic is +/// [`f128::powi`](../../std/primitive.f128.html#method.powi) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powif128(_a: f128, _x: i32) -> f128 { + unreachable!() +} - /// Returns the sine of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::sin`](../../std/primitive.f16.html#method.sin) - #[rustc_nounwind] - pub fn sinf16(x: f16) -> f16; - /// Returns the sine of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::sin`](../../std/primitive.f32.html#method.sin) - #[rustc_nounwind] - pub fn sinf32(x: f32) -> f32; - /// Returns the sine of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::sin`](../../std/primitive.f64.html#method.sin) - #[rustc_nounwind] - pub fn sinf64(x: f64) -> f64; - /// Returns the sine of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::sin`](../../std/primitive.f128.html#method.sin) - #[rustc_nounwind] - pub fn sinf128(x: f128) -> f128; +/// Returns the sine of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::sin`](../../std/primitive.f16.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the sine of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::sin`](../../std/primitive.f32.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the sine of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::sin`](../../std/primitive.f64.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the sine of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::sin`](../../std/primitive.f128.html#method.sin) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn sinf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the cosine of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::cos`](../../std/primitive.f16.html#method.cos) - #[rustc_nounwind] - pub fn cosf16(x: f16) -> f16; - /// Returns the cosine of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::cos`](../../std/primitive.f32.html#method.cos) - #[rustc_nounwind] - pub fn cosf32(x: f32) -> f32; - /// Returns the cosine of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::cos`](../../std/primitive.f64.html#method.cos) - #[rustc_nounwind] - pub fn cosf64(x: f64) -> f64; - /// Returns the cosine of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::cos`](../../std/primitive.f128.html#method.cos) - #[rustc_nounwind] - pub fn cosf128(x: f128) -> f128; +/// Returns the cosine of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::cos`](../../std/primitive.f16.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the cosine of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::cos`](../../std/primitive.f32.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the cosine of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::cos`](../../std/primitive.f64.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the cosine of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::cos`](../../std/primitive.f128.html#method.cos) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn cosf128(_x: f128) -> f128 { + unreachable!() +} - /// Raises an `f16` to an `f16` power. - /// - /// The stabilized version of this intrinsic is - /// [`f16::powf`](../../std/primitive.f16.html#method.powf) - #[rustc_nounwind] - pub fn powf16(a: f16, x: f16) -> f16; - /// Raises an `f32` to an `f32` power. - /// - /// The stabilized version of this intrinsic is - /// [`f32::powf`](../../std/primitive.f32.html#method.powf) - #[rustc_nounwind] - pub fn powf32(a: f32, x: f32) -> f32; - /// Raises an `f64` to an `f64` power. - /// - /// The stabilized version of this intrinsic is - /// [`f64::powf`](../../std/primitive.f64.html#method.powf) - #[rustc_nounwind] - pub fn powf64(a: f64, x: f64) -> f64; - /// Raises an `f128` to an `f128` power. - /// - /// The stabilized version of this intrinsic is - /// [`f128::powf`](../../std/primitive.f128.html#method.powf) - #[rustc_nounwind] - pub fn powf128(a: f128, x: f128) -> f128; +/// Raises an `f16` to an `f16` power. +/// +/// The stabilized version of this intrinsic is +/// [`f16::powf`](../../std/primitive.f16.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf16(_a: f16, _x: f16) -> f16 { + unreachable!() +} +/// Raises an `f32` to an `f32` power. +/// +/// The stabilized version of this intrinsic is +/// [`f32::powf`](../../std/primitive.f32.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf32(_a: f32, _x: f32) -> f32 { + unreachable!() +} +/// Raises an `f64` to an `f64` power. +/// +/// The stabilized version of this intrinsic is +/// [`f64::powf`](../../std/primitive.f64.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf64(_a: f64, _x: f64) -> f64 { + unreachable!() +} +/// Raises an `f128` to an `f128` power. +/// +/// The stabilized version of this intrinsic is +/// [`f128::powf`](../../std/primitive.f128.html#method.powf) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn powf128(_a: f128, _x: f128) -> f128 { + unreachable!() +} - /// Returns the exponential of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::exp`](../../std/primitive.f16.html#method.exp) - #[rustc_nounwind] - pub fn expf16(x: f16) -> f16; - /// Returns the exponential of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::exp`](../../std/primitive.f32.html#method.exp) - #[rustc_nounwind] - pub fn expf32(x: f32) -> f32; - /// Returns the exponential of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::exp`](../../std/primitive.f64.html#method.exp) - #[rustc_nounwind] - pub fn expf64(x: f64) -> f64; - /// Returns the exponential of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::exp`](../../std/primitive.f128.html#method.exp) - #[rustc_nounwind] - pub fn expf128(x: f128) -> f128; +/// Returns the exponential of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::exp`](../../std/primitive.f16.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the exponential of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::exp`](../../std/primitive.f32.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the exponential of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::exp`](../../std/primitive.f64.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the exponential of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::exp`](../../std/primitive.f128.html#method.exp) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn expf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns 2 raised to the power of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f16(x: f16) -> f16; - /// Returns 2 raised to the power of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f32(x: f32) -> f32; - /// Returns 2 raised to the power of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f64(x: f64) -> f64; - /// Returns 2 raised to the power of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) - #[rustc_nounwind] - pub fn exp2f128(x: f128) -> f128; +/// Returns 2 raised to the power of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::exp2`](../../std/primitive.f16.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns 2 raised to the power of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::exp2`](../../std/primitive.f32.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns 2 raised to the power of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::exp2`](../../std/primitive.f64.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns 2 raised to the power of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::exp2`](../../std/primitive.f128.html#method.exp2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn exp2f128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the natural logarithm of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::ln`](../../std/primitive.f16.html#method.ln) - #[rustc_nounwind] - pub fn logf16(x: f16) -> f16; - /// Returns the natural logarithm of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::ln`](../../std/primitive.f32.html#method.ln) - #[rustc_nounwind] - pub fn logf32(x: f32) -> f32; - /// Returns the natural logarithm of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::ln`](../../std/primitive.f64.html#method.ln) - #[rustc_nounwind] - pub fn logf64(x: f64) -> f64; - /// Returns the natural logarithm of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::ln`](../../std/primitive.f128.html#method.ln) - #[rustc_nounwind] - pub fn logf128(x: f128) -> f128; +/// Returns the natural logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::ln`](../../std/primitive.f16.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the natural logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::ln`](../../std/primitive.f32.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the natural logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::ln`](../../std/primitive.f64.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the natural logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::ln`](../../std/primitive.f128.html#method.ln) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn logf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the base 10 logarithm of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::log10`](../../std/primitive.f16.html#method.log10) - #[rustc_nounwind] - pub fn log10f16(x: f16) -> f16; - /// Returns the base 10 logarithm of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::log10`](../../std/primitive.f32.html#method.log10) - #[rustc_nounwind] - pub fn log10f32(x: f32) -> f32; - /// Returns the base 10 logarithm of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::log10`](../../std/primitive.f64.html#method.log10) - #[rustc_nounwind] - pub fn log10f64(x: f64) -> f64; - /// Returns the base 10 logarithm of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::log10`](../../std/primitive.f128.html#method.log10) - #[rustc_nounwind] - pub fn log10f128(x: f128) -> f128; +/// Returns the base 10 logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::log10`](../../std/primitive.f16.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::log10`](../../std/primitive.f32.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::log10`](../../std/primitive.f64.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the base 10 logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::log10`](../../std/primitive.f128.html#method.log10) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log10f128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the base 2 logarithm of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::log2`](../../std/primitive.f16.html#method.log2) - #[rustc_nounwind] - pub fn log2f16(x: f16) -> f16; - /// Returns the base 2 logarithm of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::log2`](../../std/primitive.f32.html#method.log2) - #[rustc_nounwind] - pub fn log2f32(x: f32) -> f32; - /// Returns the base 2 logarithm of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::log2`](../../std/primitive.f64.html#method.log2) - #[rustc_nounwind] - pub fn log2f64(x: f64) -> f64; - /// Returns the base 2 logarithm of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::log2`](../../std/primitive.f128.html#method.log2) - #[rustc_nounwind] - pub fn log2f128(x: f128) -> f128; +/// Returns the base 2 logarithm of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::log2`](../../std/primitive.f16.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::log2`](../../std/primitive.f32.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::log2`](../../std/primitive.f64.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the base 2 logarithm of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::log2`](../../std/primitive.f128.html#method.log2) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn log2f128(_x: f128) -> f128 { + unreachable!() +} - /// Returns `a * b + c` for `f16` values. - /// - /// The stabilized version of this intrinsic is - /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf16(a: f16, b: f16, c: f16) -> f16; - /// Returns `a * b + c` for `f32` values. - /// - /// The stabilized version of this intrinsic is - /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; - /// Returns `a * b + c` for `f64` values. - /// - /// The stabilized version of this intrinsic is - /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; - /// Returns `a * b + c` for `f128` values. - /// - /// The stabilized version of this intrinsic is - /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) - #[rustc_nounwind] - pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; +/// Returns `a * b + c` for `f16` values. +/// +/// The stabilized version of this intrinsic is +/// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf16(_a: f16, _b: f16, _c: f16) -> f16 { + unreachable!() +} +/// Returns `a * b + c` for `f32` values. +/// +/// The stabilized version of this intrinsic is +/// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf32(_a: f32, _b: f32, _c: f32) -> f32 { + unreachable!() +} +/// Returns `a * b + c` for `f64` values. +/// +/// The stabilized version of this intrinsic is +/// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf64(_a: f64, _b: f64, _c: f64) -> f64 { + unreachable!() +} +/// Returns `a * b + c` for `f128` values. +/// +/// The stabilized version of this intrinsic is +/// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmaf128(_a: f128, _b: f128, _c: f128) -> f128 { + unreachable!() +} - /// Returns `a * b + c` for `f16` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; - /// Returns `a * b + c` for `f32` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; - /// Returns `a * b + c` for `f64` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; - /// Returns `a * b + c` for `f128` values, non-deterministically executing - /// either a fused multiply-add or two operations with rounding of the - /// intermediate result. - /// - /// The operation is fused if the code generator determines that target - /// instruction set has support for a fused operation, and that the fused - /// operation is more efficient than the equivalent, separate pair of mul - /// and add instructions. It is unspecified whether or not a fused operation - /// is selected, and that may depend on optimization level and context, for - /// example. - #[rustc_nounwind] - pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; +/// Returns `a * b + c` for `f16` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf16(_a: f16, _b: f16, _c: f16) -> f16 { + unreachable!() +} +/// Returns `a * b + c` for `f32` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf32(_a: f32, _b: f32, _c: f32) -> f32 { + unreachable!() +} +/// Returns `a * b + c` for `f64` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf64(_a: f64, _b: f64, _c: f64) -> f64 { + unreachable!() +} +/// Returns `a * b + c` for `f128` values, non-deterministically executing +/// either a fused multiply-add or two operations with rounding of the +/// intermediate result. +/// +/// The operation is fused if the code generator determines that target +/// instruction set has support for a fused operation, and that the fused +/// operation is more efficient than the equivalent, separate pair of mul +/// and add instructions. It is unspecified whether or not a fused operation +/// is selected, and that may depend on optimization level and context, for +/// example. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmuladdf128(_a: f128, _b: f128, _c: f128) -> f128 { + unreachable!() +} - /// Returns the largest integer less than or equal to an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::floor`](../../std/primitive.f16.html#method.floor) - #[rustc_nounwind] - pub fn floorf16(x: f16) -> f16; - /// Returns the largest integer less than or equal to an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::floor`](../../std/primitive.f32.html#method.floor) - #[rustc_nounwind] - pub fn floorf32(x: f32) -> f32; - /// Returns the largest integer less than or equal to an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::floor`](../../std/primitive.f64.html#method.floor) - #[rustc_nounwind] - pub fn floorf64(x: f64) -> f64; - /// Returns the largest integer less than or equal to an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::floor`](../../std/primitive.f128.html#method.floor) - #[rustc_nounwind] - pub fn floorf128(x: f128) -> f128; +/// Returns the largest integer less than or equal to an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::floor`](../../std/primitive.f16.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::floor`](../../std/primitive.f32.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::floor`](../../std/primitive.f64.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the largest integer less than or equal to an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::floor`](../../std/primitive.f128.html#method.floor) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn floorf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the smallest integer greater than or equal to an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf16(x: f16) -> f16; - /// Returns the smallest integer greater than or equal to an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf32(x: f32) -> f32; - /// Returns the smallest integer greater than or equal to an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf64(x: f64) -> f64; - /// Returns the smallest integer greater than or equal to an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil) - #[rustc_nounwind] - pub fn ceilf128(x: f128) -> f128; +/// Returns the smallest integer greater than or equal to an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the smallest integer greater than or equal to an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn ceilf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the integer part of an `f16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc) - #[rustc_nounwind] - pub fn truncf16(x: f16) -> f16; - /// Returns the integer part of an `f32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc) - #[rustc_nounwind] - pub fn truncf32(x: f32) -> f32; - /// Returns the integer part of an `f64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc) - #[rustc_nounwind] - pub fn truncf64(x: f64) -> f64; - /// Returns the integer part of an `f128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc) - #[rustc_nounwind] - pub fn truncf128(x: f128) -> f128; +/// Returns the integer part of an `f16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the integer part of an `f32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the integer part of an `f64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the integer part of an `f128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn truncf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`. - /// - /// The stabilized version of this intrinsic is - /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. - /// - /// The stabilized version of this intrinsic is - /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. - /// - /// The stabilized version of this intrinsic is - /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// May raise an inexact floating-point exception if the argument is not an integer. - /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions - /// cannot actually be utilized from Rust code. - /// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. - /// - /// The stabilized version of this intrinsic is - /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) - #[rustc_nounwind] - pub fn rintf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`. +/// +/// The stabilized version of this intrinsic is +/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. +/// +/// The stabilized version of this intrinsic is +/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. +/// +/// The stabilized version of this intrinsic is +/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// May raise an inexact floating-point exception if the argument is not an integer. +/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions +/// cannot actually be utilized from Rust code. +/// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. +/// +/// The stabilized version of this intrinsic is +/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn rintf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, - /// so this rounds half-way cases to the number with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn nearbyintf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, +/// so this rounds half-way cases to the number with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn nearbyintf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f16::round`](../../std/primitive.f16.html#method.round) - #[rustc_nounwind] - pub fn roundf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f32::round`](../../std/primitive.f32.html#method.round) - #[rustc_nounwind] - pub fn roundf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f64::round`](../../std/primitive.f64.html#method.round) - #[rustc_nounwind] - pub fn roundf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero. - /// - /// The stabilized version of this intrinsic is - /// [`f128::round`](../../std/primitive.f128.html#method.round) - #[rustc_nounwind] - pub fn roundf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f16::round`](../../std/primitive.f16.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f32::round`](../../std/primitive.f32.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f64::round`](../../std/primitive.f64.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero. +/// +/// The stabilized version of this intrinsic is +/// [`f128::round`](../../std/primitive.f128.html#method.round) +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundf128(_x: f128) -> f128 { + unreachable!() +} - /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf16(x: f16) -> f16; - /// Returns the nearest integer to an `f32`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf32(x: f32) -> f32; - /// Returns the nearest integer to an `f64`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf64(x: f64) -> f64; - /// Returns the nearest integer to an `f128`. Rounds half-way cases to the number - /// with an even least significant digit. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn roundevenf128(x: f128) -> f128; +/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf16(_x: f16) -> f16 { + unreachable!() +} +/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf32(_x: f32) -> f32 { + unreachable!() +} +/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf64(_x: f64) -> f64 { + unreachable!() +} +/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number +/// with an even least significant digit. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn roundevenf128(_x: f128) -> f128 { + unreachable!() +} - /// Float addition that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fadd_fast(a: T, b: T) -> T; +/// Float addition that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fadd_fast(_a: T, _b: T) -> T { + unreachable!() +} - /// Float subtraction that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fsub_fast(a: T, b: T) -> T; +/// Float subtraction that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fsub_fast(_a: T, _b: T) -> T { + unreachable!() +} - /// Float multiplication that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fmul_fast(a: T, b: T) -> T; +/// Float multiplication that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fmul_fast(_a: T, _b: T) -> T { + unreachable!() +} - /// Float division that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn fdiv_fast(a: T, b: T) -> T; +/// Float division that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn fdiv_fast(_a: T, _b: T) -> T { + unreachable!() +} - /// Float remainder that allows optimizations based on algebraic rules. - /// May assume inputs are finite. - /// - /// This intrinsic does not have a stable counterpart. - #[rustc_nounwind] - pub fn frem_fast(a: T, b: T) -> T; +/// Float remainder that allows optimizations based on algebraic rules. +/// May assume inputs are finite. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn frem_fast(_a: T, _b: T) -> T { + unreachable!() +} - /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range - /// () - /// - /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. - #[rustc_nounwind] - pub fn float_to_int_unchecked(value: Float) -> Int; +/// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range +/// () +/// +/// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn float_to_int_unchecked(_value: Float) -> Int { + unreachable!() } /// Float addition that allows optimizations based on algebraic rules. diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index a456e81e762f..aea6d263a727 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -22,7 +22,7 @@ LL | std::intrinsics::floorf32, | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _` - found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {floorf32}` + found fn item `unsafe fn(_) -> _ {floorf32}` error: aborting due to 3 previous errors From 736c397f41f9030e500199fc28b56a7fab703759 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 25 Nov 2024 00:36:22 +0900 Subject: [PATCH 097/330] Fix clobber_abi in RV32E and RV64E inline assembly --- compiler/rustc_ast_lowering/src/asm.rs | 7 ++- .../rustc_codegen_cranelift/src/inline_asm.rs | 11 +++-- compiler/rustc_target/src/asm/mod.rs | 33 +++++++++++++- compiler/rustc_target/src/asm/riscv.rs | 6 ++- tests/codegen/asm/riscv-clobbers.rs | 44 +++++++++++++++++++ 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 tests/codegen/asm/riscv-clobbers.rs diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 215e6d84d0f0..32559a10ac3b 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -80,7 +80,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut clobber_abis = FxIndexMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse( + asm_arch, + &self.tcx.sess.target, + &self.tcx.sess.unstable_target_features, + *abi_name, + ) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 70176754f337..73ee47b2c63a 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -472,9 +472,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { let mut new_slot = |x| new_slot_fn(&mut slot_size, x); // Allocate stack slots for saving clobbered registers - let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C) - .unwrap() - .clobbered_regs(); + let abi_clobber = InlineAsmClobberAbi::parse( + self.arch, + &self.tcx.sess.target, + &self.tcx.sess.unstable_target_features, + sym::C, + ) + .unwrap() + .clobbered_regs(); for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) { let mut need_save = true; // If the register overlaps with a register clobbered by function call, then diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 10778e9acf1f..2c5ad1aa8bf8 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -922,6 +922,7 @@ pub enum InlineAsmClobberAbi { AArch64NoX18, Arm64EC, RiscV, + RiscVE, LoongArch, PowerPC, S390x, @@ -934,6 +935,7 @@ impl InlineAsmClobberAbi { pub fn parse( arch: InlineAsmArch, target: &Target, + target_features: &FxIndexSet, name: Symbol, ) -> Result { let name = name.as_str(); @@ -968,7 +970,11 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV), + "C" | "system" | "efiapi" => Ok(if riscv::is_e(target_features) { + InlineAsmClobberAbi::RiscVE + } else { + InlineAsmClobberAbi::RiscV + }), _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::LoongArch64 => match name { @@ -1141,6 +1147,31 @@ impl InlineAsmClobberAbi { v24, v25, v26, v27, v28, v29, v30, v31, } }, + InlineAsmClobberAbi::RiscVE => clobbered_regs! { + RiscV RiscVInlineAsmReg { + // Refs: + // - ILP32E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#ilp32e-calling-convention + // - LP64E https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/299 + + // ra + x1, + // t0-t2 + x5, x6, x7, + // a0-a5 + x10, x11, x12, x13, x14, x15, + // ft0-ft7 + f0, f1, f2, f3, f4, f5, f6, f7, + // fa0-fa7 + f10, f11, f12, f13, f14, f15, f16, f17, + // ft8-ft11 + f28, f29, f30, f31, + + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + } + }, InlineAsmClobberAbi::LoongArch => clobbered_regs! { LoongArch LoongArchInlineAsmReg { // ra diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs index cfd573efbc1c..d6b305253798 100644 --- a/compiler/rustc_target/src/asm/riscv.rs +++ b/compiler/rustc_target/src/asm/riscv.rs @@ -54,6 +54,10 @@ impl RiscVInlineAsmRegClass { } } +pub(crate) fn is_e(target_features: &FxIndexSet) -> bool { + target_features.contains(&sym::e) +} + fn not_e( _arch: InlineAsmArch, _reloc_model: RelocModel, @@ -61,7 +65,7 @@ fn not_e( _target: &Target, _is_clobber: bool, ) -> Result<(), &'static str> { - if target_features.contains(&sym::e) { + if is_e(target_features) { Err("register can't be used with the `e` target feature") } else { Ok(()) diff --git a/tests/codegen/asm/riscv-clobbers.rs b/tests/codegen/asm/riscv-clobbers.rs new file mode 100644 index 000000000000..59b2705a4496 --- /dev/null +++ b/tests/codegen/asm/riscv-clobbers.rs @@ -0,0 +1,44 @@ +//@ assembly-output: emit-asm +//@ revisions: rv32i rv64i rv32e +//@[rv32i] compile-flags: --target riscv32i-unknown-none-elf +//@[rv32i] needs-llvm-components: riscv +//@[rv64i] compile-flags: --target riscv64imac-unknown-none-elf +//@[rv64i] needs-llvm-components: riscv +//@[rv32e] compile-flags: --target riscv32e-unknown-none-elf +//@[rv32e] needs-llvm-components: riscv +// ignore-tidy-linelength + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @flags_clobber +// CHECK: call void asm sideeffect "", "~{vtype},~{vl},~{vxsat},~{vxrm}"() +#[no_mangle] +pub unsafe fn flags_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// rv32i: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},={x16},={x17},={x28},={x29},={x30},={x31},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() +// rv64i: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},={x16},={x17},={x28},={x29},={x30},={x31},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() +// rv32e: asm sideeffect "", "={x1},={x5},={x6},={x7},={x10},={x11},={x12},={x13},={x14},={x15},~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f28},~{f29},~{f30},~{f31},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} From 63b82dd0415f8902d22d7db630d6c0fc04366946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 24 Nov 2024 18:26:26 +0200 Subject: [PATCH 098/330] Fix missing rust-src message --- .../rust-analyzer/crates/project-model/src/sysroot.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs index 19f4c35b5add..d47b4976aa27 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs @@ -444,13 +444,14 @@ fn discover_sysroot_src_dir_or_add_component( get_rust_src(sysroot_path) }) .ok_or_else(|| { - let error = "\ + tracing::error!(%sysroot_path, "can't load standard library, try installing `rust-src`"); + format_err!( + "\ can't load standard library from sysroot {sysroot_path} (discovered via `rustc --print sysroot`) -try installing the Rust source the same way you installed rustc"; - tracing::error!(error); - format_err!(error) +try installing `rust-src` the same way you installed `rustc`" + ) }) } From 418dfb2257c3a2c516b648695b92367dde2a9cd3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 24 Nov 2024 11:23:14 -0700 Subject: [PATCH 099/330] Add Known problems section --- clippy_lints/src/doc/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 993335e8248c..88ac871acf68 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -544,6 +544,8 @@ declare_clippy_lint! { /// Also, if any of these non-source code file is updated, it will trigger a /// recompilation. /// + /// ### Known problems + /// /// Excluding this will currently result in the file being left out if /// the item's docs are inlined from another crate. This may be fixed in a /// future version of rustdoc. From 15dff274d07621283b38e4ca0008f7e6145c2519 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Nov 2024 22:39:19 +0000 Subject: [PATCH 100/330] Actually use placeholder regions for trait method late bound regions in collect_return_position_impl_trait_in_trait_tys --- .../src/check/compare_impl_item.rs | 12 ++++---- .../in-trait/do-not-imply-from-trait-impl.rs | 30 +++++++++++++++++++ .../do-not-imply-from-trait-impl.stderr | 22 ++++++++++++++ .../method-signature-matches.lt.stderr | 8 ++--- ...rpitit-hidden-types-self-implied-wf.stderr | 4 +-- .../signature-mismatch.failure.stderr | 15 +++++----- .../impl-trait/in-trait/signature-mismatch.rs | 2 +- .../rpitit-impl-captures-too-much.stderr | 7 +++-- 8 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs create mode 100644 tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index f86ca95a954b..dd1062558901 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -523,8 +523,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_sig = ocx.normalize( &misc_cause, param_env, - tcx.liberate_late_bound_regions( - impl_m.def_id, + infcx.instantiate_binder_with_fresh_vars( + return_span, + infer::HigherRankedType, tcx.fn_sig(impl_m.def_id).instantiate_identity(), ), ); @@ -536,10 +537,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // them with inference variables. // We will use these inference variables to collect the hidden types of RPITITs. let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id); - let unnormalized_trait_sig = infcx - .instantiate_binder_with_fresh_vars( - return_span, - infer::HigherRankedType, + let unnormalized_trait_sig = tcx + .liberate_late_bound_regions( + impl_m.def_id, tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args), ) .fold_with(&mut collector); diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs new file mode 100644 index 000000000000..30ca3d271b81 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs @@ -0,0 +1,30 @@ +// Make sure that we don't accidentally collect an RPITIT hidden type that does not +// hold for all instantiations of the trait signature. + +trait MkStatic { + fn mk_static(self) -> &'static str; +} + +impl MkStatic for &'static str { + fn mk_static(self) -> &'static str { self } +} + +trait Foo { + fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic; +} + +impl Foo for str { + fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + //~^ ERROR method not compatible with trait + self + } +} + +fn call_foo(t: &T) -> &'static str { + t.foo().mk_static() +} + +fn main() { + let s = call_foo(String::from("hello, world").as_str()); + println!("> {s}"); +} diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr new file mode 100644 index 000000000000..95d8699e19ff --- /dev/null +++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr @@ -0,0 +1,22 @@ +error[E0308]: method not compatible with trait + --> $DIR/do-not-imply-from-trait-impl.rs:17:38 + | +LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&'late _) -> _` + found signature `fn(&'a _) -> _` +note: the lifetime `'late` as defined here... + --> $DIR/do-not-imply-from-trait-impl.rs:13:25 + | +LL | fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic; + | ^^^^^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/do-not-imply-from-trait-impl.rs:17:12 + | +LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static { + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 6f6b787b6fe1..a23879eb6c37 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -11,12 +11,12 @@ note: type in trait | LL | fn early<'early, T>(x: &'early T) -> impl Sized; | ^^^^^^^^^ - = note: expected signature `fn(&T)` - found signature `fn(&'late ())` + = note: expected signature `fn(&'early T)` + found signature `fn(&())` help: change the parameter type to match the trait | -LL | fn early<'late, T>(_: &T) {} - | ~~ +LL | fn early<'late, T>(_: &'early T) {} + | ~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr index 3430055dab17..4c10422f985f 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr @@ -6,9 +6,9 @@ LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { | = note: the pointer is valid for the static lifetime note: but the referenced data is only valid for the anonymous lifetime defined here - --> $DIR/rpitit-hidden-types-self-implied-wf.rs:6:18 + --> $DIR/rpitit-hidden-types-self-implied-wf.rs:2:18 | -LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) { +LL | fn extend(_: &str) -> (impl Sized + '_, &'static str); | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr index 56b83cbca77a..b27d7870955e 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr @@ -1,14 +1,15 @@ -error[E0623]: lifetime mismatch +error[E0477]: the type `impl Future>` does not fulfill the required lifetime --> $DIR/signature-mismatch.rs:77:10 | -LL | &'a self, - | -------- this parameter and the return type are declared with different lifetimes... -... LL | ) -> impl Future> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | ...but data from `buff` is returned here + | +note: type must outlive the lifetime `'a` as defined here as required by this binding + --> $DIR/signature-mismatch.rs:73:32 + | +LL | fn async_fn_reduce_outlive<'a, 'b, T>( + | ^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0623`. +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs index 55b9a0de5ff0..a9885c6a2986 100644 --- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs @@ -75,7 +75,7 @@ impl AsyncTrait for Struct { buff: &'b [u8], t: T, ) -> impl Future> { - //[failure]~^ ERROR lifetime mismatch + //[failure]~^ ERROR the type `impl Future>` does not fulfill the required lifetime async move { let _t = t; vec![] diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr index e1856b929106..360f0d7e7f37 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -1,10 +1,11 @@ error: return type captures more lifetimes than trait definition --> $DIR/rpitit-impl-captures-too-much.rs:10:39 | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; + | -- this lifetime was captured +... LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} - | -- ^^^^^^^^^^^^^^^^^^^^ - | | - | this lifetime was captured + | ^^^^^^^^^^^^^^^^^^^^ | note: hidden type must only reference lifetimes captured by this impl trait --> $DIR/rpitit-impl-captures-too-much.rs:6:39 From 671183a41f57f3a9932ce4d762c7fb30f4cbdd16 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sun, 24 Nov 2024 23:16:27 -0800 Subject: [PATCH 101/330] Bless --- book/src/lint_configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 670b5cbef823..275d125096e9 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -895,7 +895,7 @@ The order of associated items in traits. ## `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 +reference. **Default Value:** `target_pointer_width * 2` From 945ccbd0634b727f2b872f0ffd2872f8b9d7d173 Mon Sep 17 00:00:00 2001 From: Frank King Date: Mon, 25 Nov 2024 16:38:35 +0800 Subject: [PATCH 102/330] Refactor `where` predicates, and reserve for attributes support --- .../src/extra_unused_type_parameters.rs | 7 +++--- clippy_lints/src/implied_bounds_in_impls.rs | 4 ++-- clippy_lints/src/lifetimes.rs | 10 ++++----- clippy_lints/src/multiple_bound_locations.rs | 10 ++++----- clippy_lints/src/needless_maybe_sized.rs | 4 ++-- clippy_lints/src/trait_bounds.rs | 22 +++++++++---------- clippy_utils/src/ast_utils.rs | 4 ++-- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/extra_unused_type_parameters.rs b/clippy_lints/src/extra_unused_type_parameters.rs index 6ad879b9fe7a..81152da8c852 100644 --- a/clippy_lints/src/extra_unused_type_parameters.rs +++ b/clippy_lints/src/extra_unused_type_parameters.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty}; use rustc_hir::{ BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, - PredicateOrigin, Ty, WherePredicate, + PredicateOrigin, Ty, WherePredicate, WherePredicateKind }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; @@ -205,12 +205,13 @@ impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> { } fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) { - if let WherePredicate::BoundPredicate(predicate) = predicate { + let span = predicate.span; + if let WherePredicateKind::BoundPredicate(predicate) = predicate.kind { // Collect spans for any bounds on type parameters. if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param() { match predicate.origin { PredicateOrigin::GenericParam => { - self.inline_bounds.insert(def_id, predicate.span); + self.inline_bounds.insert(def_id, span); }, PredicateOrigin::WhereClause => { self.where_bounds.insert(def_id); diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 65fdc93e0ed9..4427edb752e0 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::def_id::DefId; use rustc_hir::{ AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind, - WherePredicate, + WherePredicateKind, }; use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; @@ -324,7 +324,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { 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 + if let WherePredicateKind::BoundPredicate(predicate) = predicate.kind // 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... diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index ce0e1a24a7b5..6ff1a1e5ec74 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{ use rustc_hir::{ BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, - PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items, + PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, WherePredicateKind, lang_items, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -442,9 +442,9 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> { /// reason about elision. fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_>) -> bool { for predicate in generics.predicates { - match *predicate { - WherePredicate::RegionPredicate(..) => return true, - WherePredicate::BoundPredicate(ref pred) => { + match *predicate.kind { + WherePredicateKind::RegionPredicate(..) => return true, + WherePredicateKind::BoundPredicate(ref pred) => { // a predicate like F: Trait or F: for<'a> Trait<'a> let mut visitor = RefVisitor::new(cx); // walk the type F, it may not contain LT refs @@ -467,7 +467,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ } } }, - WherePredicate::EqPredicate(ref pred) => { + WherePredicateKind::EqPredicate(ref pred) => { let mut visitor = RefVisitor::new(cx); walk_ty(&mut visitor, pred.lhs_ty); walk_ty(&mut visitor, pred.rhs_ty); diff --git a/clippy_lints/src/multiple_bound_locations.rs b/clippy_lints/src/multiple_bound_locations.rs index d276e29bacec..882ab2dda7aa 100644 --- a/clippy_lints/src/multiple_bound_locations.rs +++ b/clippy_lints/src/multiple_bound_locations.rs @@ -1,5 +1,5 @@ use rustc_ast::visit::FnKind; -use rustc_ast::{NodeId, WherePredicate}; +use rustc_ast::{NodeId, WherePredicateKind}; use rustc_data_structures::fx::FxHashMap; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; @@ -51,8 +51,8 @@ impl EarlyLintPass for MultipleBoundLocations { } } for clause in &generics.where_clause.predicates { - match clause { - WherePredicate::BoundPredicate(pred) => { + match &clause.kind { + WherePredicateKind::BoundPredicate(pred) => { if (!pred.bound_generic_params.is_empty() || !pred.bounds.is_empty()) && let Some(Some(bound_span)) = pred .bounded_ty @@ -62,14 +62,14 @@ impl EarlyLintPass for MultipleBoundLocations { emit_lint(cx, *bound_span, pred.bounded_ty.span); } }, - WherePredicate::RegionPredicate(pred) => { + WherePredicateKind::RegionPredicate(pred) => { if !pred.bounds.is_empty() && let Some(bound_span) = generic_params_with_bounds.get(&pred.lifetime.ident.name.as_str()) { emit_lint(cx, *bound_span, pred.lifetime.ident.span); } }, - WherePredicate::EqPredicate(_) => {}, + WherePredicateKind::EqPredicate(_) => {}, } } } diff --git a/clippy_lints/src/needless_maybe_sized.rs b/clippy_lints/src/needless_maybe_sized.rs index 852a0ce8c6d5..ad6313e391bd 100644 --- a/clippy_lints/src/needless_maybe_sized.rs +++ b/clippy_lints/src/needless_maybe_sized.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::def_id::{DefId, DefIdMap}; -use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicate}; +use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicateKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ClauseKind, PredicatePolarity}; use rustc_session::declare_lint_pass; @@ -52,7 +52,7 @@ fn type_param_bounds<'tcx>(generics: &'tcx Generics<'tcx>) -> impl Iterator LateLintPass<'tcx> for TraitBounds { let mut self_bounds_map = FxHashMap::default(); for predicate in item.generics.predicates { - if let WherePredicate::BoundPredicate(bound_predicate) = predicate + if let WherePredicateKind::BoundPredicate(bound_predicate) = predicate.kind && bound_predicate.origin != PredicateOrigin::ImplTrait - && !bound_predicate.span.from_expansion() + && !predicate.span.from_expansion() && let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind && let Some(PathSegment { res: Res::SelfTyParam { trait_: def_id }, @@ -268,10 +268,10 @@ impl TraitBounds { let mut map: UnhashMap, Vec<&GenericBound<'_>>> = UnhashMap::default(); let mut applicability = Applicability::MaybeIncorrect; for bound in generics.predicates { - if let WherePredicate::BoundPredicate(p) = bound + if let WherePredicateKind::BoundPredicate(p) = bound.kind && p.origin != PredicateOrigin::ImplTrait && p.bounds.len() as u64 <= self.max_trait_bounds - && !p.span.from_expansion() + && !bound.span.from_expansion() && let bounds = p .bounds .iter() @@ -295,7 +295,7 @@ impl TraitBounds { span_lint_and_help( cx, TYPE_REPETITION_IN_BOUNDS, - p.span, + bound.span, "this type has already been used as a bound predicate", None, hint_string, @@ -322,8 +322,8 @@ fn check_trait_bound_duplication<'tcx>(cx: &LateContext<'tcx>, generics: &'_ Gen .predicates .iter() .filter_map(|pred| { - if pred.in_where_clause() - && let WherePredicate::BoundPredicate(bound_predicate) = pred + if pred.kind.in_where_clause() + && let WherePredicateKind::BoundPredicate(bound_predicate) = pred.kind && let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind { return Some( @@ -347,10 +347,10 @@ fn check_trait_bound_duplication<'tcx>(cx: &LateContext<'tcx>, generics: &'_ Gen // | // compare trait bounds keyed by generic name and comparable trait to collected where // predicates eg. (T, Clone) - for predicate in generics.predicates.iter().filter(|pred| !pred.in_where_clause()) { - if let WherePredicate::BoundPredicate(bound_predicate) = predicate + for predicate in generics.predicates.iter().filter(|pred| !pred.kind.in_where_clause()) { + if let WherePredicateKind::BoundPredicate(bound_predicate) = predicate.kind && bound_predicate.origin != PredicateOrigin::ImplTrait - && !bound_predicate.span.from_expansion() + && !predicate.span.from_expansion() && let TyKind::Path(QPath::Resolved(_, path)) = bound_predicate.bounded_ty.kind { let traits = rollup_traits(cx, bound_predicate.bounds, "these bounds contain repeated elements"); diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 0be6dc15a8e1..c90f4a6ebfe6 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -661,8 +661,8 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool { } pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { - use WherePredicate::*; - match (l, r) { + use WherePredicateKind::*; + match (&l.kind, &r.kind) { (BoundPredicate(l), BoundPredicate(r)) => { over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { eq_generic_param(l, r) From 59f01cdbf48795ab8d6752b8a4bbe0e4540c30a5 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 25 Nov 2024 23:11:17 +0900 Subject: [PATCH 103/330] Support predicate registers (clobber-only) in Hexagon inline assembly --- compiler/rustc_codegen_gcc/src/asm.rs | 6 +++ compiler/rustc_codegen_llvm/src/asm.rs | 2 + compiler/rustc_target/src/asm/hexagon.rs | 6 +++ .../asm-experimental-arch.md | 2 + tests/codegen/asm/hexagon-clobbers.rs | 37 +++++++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 tests/codegen/asm/hexagon-clobbers.rs diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index ab4fdb78bb09..341d1b9c179b 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -634,6 +634,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", @@ -720,6 +723,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl cx.type_vector(cx.type_i64(), 2) } InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 6ee80c08d4ad..9aa01bd1b956 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -645,6 +645,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> | Arm(ArmInlineAsmRegClass::qreg_low4) => "x", Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w", Hexagon(HexagonInlineAsmRegClass::reg) => "r", + Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"), LoongArch(LoongArchInlineAsmRegClass::reg) => "r", LoongArch(LoongArchInlineAsmRegClass::freg) => "f", Mips(MipsInlineAsmRegClass::reg) => "r", @@ -813,6 +814,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' | Arm(ArmInlineAsmRegClass::qreg_low8) | Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2), Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"), LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs index f7e726c33768..aa14ca3f337b 100644 --- a/compiler/rustc_target/src/asm/hexagon.rs +++ b/compiler/rustc_target/src/asm/hexagon.rs @@ -7,6 +7,7 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; def_reg_class! { Hexagon HexagonInlineAsmRegClass { reg, + preg, } } @@ -37,6 +38,7 @@ impl HexagonInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg => types! { _: I8, I16, I32, F32; }, + Self::preg => &[], } } } @@ -71,6 +73,10 @@ def_regs! { r26: reg = ["r26"], r27: reg = ["r27"], r28: reg = ["r28"], + p0: preg = ["p0"], + p1: preg = ["p1"], + p2: preg = ["p2"], + p3: preg = ["p3"], #error = ["r19"] => "r19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r29", "sp"] => diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 01de12bb90e9..12a73f0508b2 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -30,6 +30,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg32` | None\* | `r` | | NVPTX | `reg64` | None\* | `l` | | Hexagon | `reg` | `r[0-28]` | `r` | +| Hexagon | `preg` | `p[0-3]` | Only clobbers | | PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` | | PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` | | PowerPC | `freg` | `f[0-31]` | `f` | @@ -70,6 +71,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | | NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| Hexagon | `preg` | N/A | Only clobbers | | PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `freg` | None | `f32`, `f64` | diff --git a/tests/codegen/asm/hexagon-clobbers.rs b/tests/codegen/asm/hexagon-clobbers.rs new file mode 100644 index 000000000000..6bb662ead994 --- /dev/null +++ b/tests/codegen/asm/hexagon-clobbers.rs @@ -0,0 +1,37 @@ +//@ revisions: hexagon +//@[hexagon] compile-flags: --target hexagon-unknown-linux-musl +//@[hexagon] needs-llvm-components: hexagon +//@ compile-flags: -Zmerge-functions=disabled + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @flags_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn flags_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @p0_clobber +// CHECK: call void asm sideeffect "", "~{p0}"() +#[no_mangle] +pub unsafe fn p0_clobber() { + asm!("", out("p0") _, options(nostack, nomem, preserves_flags)); +} From f5216ee5863f81d56a679166fa64d3b3ce907843 Mon Sep 17 00:00:00 2001 From: Aakarshit Uppal <26065812+aksh1618@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:37:30 +0000 Subject: [PATCH 104/330] Fix typos in pin.rs --- library/core/src/pin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index c14c49a0d92f..43cebf4881eb 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -373,9 +373,9 @@ //! exactly what we did with our `AddrTracker` example above. Without doing this, you *must not* //! rely on pinning-related guarantees to apply to your type! //! -//! If need to truly pin a value of a foreign or built-in type that implements [`Unpin`], you'll -//! need to create your own wrapper type around the [`Unpin`] type you want to pin and then -//! opts-out of [`Unpin`] using [`PhantomPinned`]. +//! If you really need to pin a value of a foreign or built-in type that implements [`Unpin`], +//! you'll need to create your own wrapper type around the [`Unpin`] type you want to pin and then +//! opt-out of [`Unpin`] using [`PhantomPinned`]. //! //! Exposing access to the inner field which you want to remain pinned must then be carefully //! considered as well! Remember, exposing a method that gives access to a From 687dc19cb60096d5feb789264f7d61d8b68de884 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Tue, 26 Nov 2024 03:10:22 +0900 Subject: [PATCH 105/330] Fix handling of x18 in AArch64 inline assembly on ohos/trusty or with -Zfixed-x18 --- compiler/rustc_ast_lowering/src/asm.rs | 7 ++- .../rustc_codegen_cranelift/src/inline_asm.rs | 11 ++-- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/asm/aarch64.rs | 18 +++++-- compiler/rustc_target/src/asm/mod.rs | 13 +++-- .../targets/aarch64_unknown_linux_ohos.rs | 1 - compiler/rustc_target/src/target_features.rs | 6 +++ tests/codegen/asm/aarch64-clobbers.rs | 51 +++++++++++++++++++ tests/codegen/asm/arm64ec-clobbers.rs | 36 ------------- tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 11 files changed, 95 insertions(+), 53 deletions(-) create mode 100644 tests/codegen/asm/aarch64-clobbers.rs delete mode 100644 tests/codegen/asm/arm64ec-clobbers.rs diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index ff803e509973..e85c69c97612 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -82,7 +82,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut clobber_abis = FxIndexMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse( + asm_arch, + &self.tcx.sess.target, + &self.tcx.sess.unstable_target_features, + *abi_name, + ) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 7bc500b18147..d74c366a87ff 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -476,9 +476,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { let mut new_slot = |x| new_slot_fn(&mut slot_size, x); // Allocate stack slots for saving clobbered registers - let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C) - .unwrap() - .clobbered_regs(); + let abi_clobber = InlineAsmClobberAbi::parse( + self.arch, + &self.tcx.sess.target, + &self.tcx.sess.unstable_target_features, + sym::C, + ) + .unwrap() + .clobbered_regs(); for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) { let mut need_save = true; // If the register overlaps with a register clobbered by function call, then diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 46e245fb71f1..1b08e3fadc4f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1611,6 +1611,7 @@ symbols! { repr_simd, repr_transparent, require, + reserve_x18: "reserve-x18", residual, result, result_ffi_guarantees, diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index b82d327a4091..cdccb3e5d728 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexSet; -use rustc_span::Symbol; +use rustc_span::{Symbol, sym}; use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; @@ -71,18 +71,26 @@ impl AArch64InlineAsmRegClass { } } -pub(crate) fn target_reserves_x18(target: &Target) -> bool { - target.os == "android" || target.os == "fuchsia" || target.is_like_osx || target.is_like_windows +pub(crate) fn target_reserves_x18(target: &Target, target_features: &FxIndexSet) -> bool { + // See isX18ReservedByDefault in LLVM for targets reserve x18 by default: + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/TargetParser/AArch64TargetParser.cpp#L102-L105 + // Note that +reserve-x18 is currently not set for the above targets. + target.os == "android" + || target.os == "fuchsia" + || target.env == "ohos" + || target.is_like_osx + || target.is_like_windows + || target_features.contains(&sym::reserve_x18) } fn reserved_x18( _arch: InlineAsmArch, _reloc_model: RelocModel, - _target_features: &FxIndexSet, + target_features: &FxIndexSet, target: &Target, _is_clobber: bool, ) -> Result<(), &'static str> { - if target_reserves_x18(target) { + if target_reserves_x18(target, target_features) { Err("x18 is a reserved register on this target") } else { Ok(()) diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index db8d23776e56..ae41a171ae76 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -941,6 +941,7 @@ impl InlineAsmClobberAbi { pub fn parse( arch: InlineAsmArch, target: &Target, + target_features: &FxIndexSet, name: Symbol, ) -> Result { let name = name.as_str(); @@ -963,11 +964,13 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system", "efiapi", "aapcs"]), }, InlineAsmArch::AArch64 => match name { - "C" | "system" | "efiapi" => Ok(if aarch64::target_reserves_x18(target) { - InlineAsmClobberAbi::AArch64NoX18 - } else { - InlineAsmClobberAbi::AArch64 - }), + "C" | "system" | "efiapi" => { + Ok(if aarch64::target_reserves_x18(target, target_features) { + InlineAsmClobberAbi::AArch64NoX18 + } else { + InlineAsmClobberAbi::AArch64 + }) + } _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::Arm64EC => match name { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index 22b3a5f88426..14a22988a091 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs @@ -16,7 +16,6 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { - features: "+reserve-x18".into(), mcount: "\u{1}_mcount".into(), stack_probes: StackProbeType::Inline, supported_sanitizers: SanitizerSet::ADDRESS diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 112eb8626635..67c047dddfcf 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -228,6 +228,12 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]), // FEAT_RDM ("rdm", Stable, &["neon"]), + // This is needed for inline assembly, but shouldn't be stabilized as-is + // since it should be enabled globally using -Zfixed-x18, not + // #[target_feature]. + // Note that cfg(target_feature = "reserve-x18") is currently not set for + // targets that reserve x18 by default. + ("reserve-x18", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_SB ("sb", Stable, &[]), // FEAT_SHA1 & FEAT_SHA256 diff --git a/tests/codegen/asm/aarch64-clobbers.rs b/tests/codegen/asm/aarch64-clobbers.rs new file mode 100644 index 000000000000..900e6629fd2c --- /dev/null +++ b/tests/codegen/asm/aarch64-clobbers.rs @@ -0,0 +1,51 @@ +//@ revisions: aarch64 aarch64_fixed_x18 aarch64_no_x18 aarch64_reserve_x18 arm64ec +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: aarch64 +//@[aarch64_fixed_x18] compile-flags: --target aarch64-unknown-linux-gnu -Zfixed-x18 +//@[aarch64_fixed_x18] needs-llvm-components: aarch64 +//@[aarch64_no_x18] compile-flags: --target aarch64-pc-windows-msvc +//@[aarch64_no_x18] needs-llvm-components: aarch64 +// aarch64-unknown-trusty uses aarch64-unknown-unknown-musl which doesn't +// reserve x18 by default as llvm_target, and pass +reserve-x18 in target-spec. +//@[aarch64_reserve_x18] compile-flags: --target aarch64-unknown-trusty +//@[aarch64_reserve_x18] needs-llvm-components: aarch64 +//@[arm64ec] compile-flags: --target arm64ec-pc-windows-msvc +//@[arm64ec] needs-llvm-components: aarch64 +// ignore-tidy-linelength + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @cc_clobber +// CHECK: call void asm sideeffect "", "~{cc}"() +#[no_mangle] +pub unsafe fn cc_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// aarch64: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w18},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// aarch64_fixed_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// aarch64_no_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// aarch64_reserve_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"() +// arm64ec: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} diff --git a/tests/codegen/asm/arm64ec-clobbers.rs b/tests/codegen/asm/arm64ec-clobbers.rs deleted file mode 100644 index 80059331642d..000000000000 --- a/tests/codegen/asm/arm64ec-clobbers.rs +++ /dev/null @@ -1,36 +0,0 @@ -//@ assembly-output: emit-asm -//@ compile-flags: --target arm64ec-pc-windows-msvc -//@ needs-llvm-components: aarch64 - -#![crate_type = "rlib"] -#![feature(no_core, rustc_attrs, lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[rustc_builtin_macro] -macro_rules! asm { - () => {}; -} - -// CHECK-LABEL: @cc_clobber -// CHECK: call void asm sideeffect "", "~{cc}"() -#[no_mangle] -pub unsafe fn cc_clobber() { - asm!("", options(nostack, nomem)); -} - -// CHECK-LABEL: @no_clobber -// CHECK: call void asm sideeffect "", ""() -#[no_mangle] -pub unsafe fn no_clobber() { - asm!("", options(nostack, nomem, preserves_flags)); -} - -// CHECK-LABEL: @clobber_abi -// CHECK: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"() -#[no_mangle] -pub unsafe fn clobber_abi() { - asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); -} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 0a993214f5a1..32eb01c7018b 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`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 251 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 252 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 ca6a173d6387..4d375d80e771 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -174,7 +174,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`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tail-call`, `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`, `v8.8a`, `v8.9a`, `v8plus`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `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`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `reserve-x18`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tail-call`, `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`, `v8.8a`, `v8.9a`, `v8plus`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `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 b4a23bb3fce5b661b6071deb0745a46f0b057868 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 25 Nov 2024 18:44:41 +0200 Subject: [PATCH 106/330] Fix a stack overflow when computing the sizedness of a struct that includes itself as the tail field --- .../crates/hir-ty/src/infer/unify.rs | 36 +++++++++++++------ .../crates/hir-ty/src/tests/traits.rs | 21 +++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index e4881d752013..54aa18ce2076 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -916,6 +916,32 @@ impl<'a> InferenceTable<'a> { /// Check if given type is `Sized` or not pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { + let mut ty = ty.clone(); + { + let mut structs = SmallVec::<[_; 8]>::new(); + // Must use a loop here and not recursion because otherwise users will conduct completely + // artificial examples of structs that have themselves as the tail field and complain r-a crashes. + while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { + let struct_data = self.db.struct_data(id); + if let Some((last_field, _)) = struct_data.variant_data.fields().iter().next_back() + { + let last_field_ty = self.db.field_types(id.into())[last_field] + .clone() + .substitute(Interner, subst); + if structs.contains(&ty) { + // A struct recursively contains itself as a tail field somewhere. + return true; // Don't overload the users with too many errors. + } + structs.push(ty); + // Structs can have DST as its last field and such cases are not handled + // as unsized by the chalk, so we do this manually. + ty = last_field_ty; + } else { + break; + }; + } + } + // Early return for some obvious types if matches!( ty.kind(Interner), @@ -930,16 +956,6 @@ impl<'a> InferenceTable<'a> { return true; } - if let Some((AdtId::StructId(id), subst)) = ty.as_adt() { - let struct_data = self.db.struct_data(id); - if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() { - let last_field_ty = - self.db.field_types(id.into())[last_field].clone().substitute(Interner, subst); - // Structs can have DST as its last field and such cases are not handled - // as unsized by the chalk, so we do this manually - return self.is_sized(&last_field_ty); - } - } let Some(sized) = self .db .lang_item(self.trait_env.krate, LangItem::Sized) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index 9b982a124e7b..624148cab20f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -4790,3 +4790,24 @@ fn allowed3(baz: impl Baz>) {} "#]], ) } + +#[test] +fn recursive_tail_sized() { + check_infer( + r#" +struct WeirdFoo(WeirdBar); +struct WeirdBar(WeirdFoo); + +fn bar(v: *const ()) { + let _ = v as *const WeirdFoo; +} + "#, + expect![[r#" + 62..63 'v': *const () + 76..113 '{ ...Foo; }': () + 86..87 '_': *const WeirdFoo + 90..91 'v': *const () + 90..110 'v as *...irdFoo': *const WeirdFoo + "#]], + ); +} From 2bf03f19e2722f5254555eaa8c96510de6d3ec66 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 23 Nov 2024 21:02:27 +0100 Subject: [PATCH 107/330] Handle repetition of associated constant constraint as well --- clippy_utils/src/hir_utils.rs | 11 ++++++++--- tests/ui/trait_duplication_in_bounds.fixed | 3 ++- tests/ui/trait_duplication_in_bounds.rs | 1 + tests/ui/trait_duplication_in_bounds.stderr | 8 +++++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 5c93a9948b82..5c5d84cb3818 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -545,7 +545,7 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool { if left.parenthesized == right.parenthesized { over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work - && over(left.constraints, right.constraints, |l, r| self.eq_assoc_type_binding(l, r)) + && over(left.constraints, right.constraints, |l, r| self.eq_assoc_eq_constraint(l, r)) } else { false } @@ -602,8 +602,13 @@ impl HirEqInterExpr<'_, '_, '_> { } } - fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool { - left.ident.name == right.ident.name && both_some_and(left.ty(), right.ty(), |l, r| self.eq_ty(l, r)) + /// Checks whether two constraints designate the same equality constraint (same name, and same + /// type or const). + fn eq_assoc_eq_constraint(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool { + // TODO: this could be extended to check for identical associated item bound constraints + left.ident.name == right.ident.name + && (both_some_and(left.ty(), right.ty(), |l, r| self.eq_ty(l, r)) + || both_some_and(left.ct(), right.ct(), |l, r| self.eq_const_arg(l, r))) } fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool { diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed index e57c79553c30..708512793d50 100644 --- a/tests/ui/trait_duplication_in_bounds.fixed +++ b/tests/ui/trait_duplication_in_bounds.fixed @@ -191,6 +191,7 @@ trait AssocConstTrait { } fn assoc_const_args() where - T: AssocConstTrait + AssocConstTrait, + T: AssocConstTrait, + //~^ trait_duplication_in_bounds { } diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index ee84d3c30118..12db6b65a7ae 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -192,5 +192,6 @@ trait AssocConstTrait { fn assoc_const_args() where T: AssocConstTrait + AssocConstTrait, + //~^ trait_duplication_in_bounds { } diff --git a/tests/ui/trait_duplication_in_bounds.stderr b/tests/ui/trait_duplication_in_bounds.stderr index 0dd508e47450..83c06eaccd4e 100644 --- a/tests/ui/trait_duplication_in_bounds.stderr +++ b/tests/ui/trait_duplication_in_bounds.stderr @@ -70,5 +70,11 @@ error: these where clauses contain repeated elements LL | T: IntoIterator + IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `IntoIterator` -error: aborting due to 11 previous errors +error: these where clauses contain repeated elements + --> tests/ui/trait_duplication_in_bounds.rs:194:8 + | +LL | T: AssocConstTrait + AssocConstTrait, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait` + +error: aborting due to 12 previous errors From 7fc4b963470de530a212f2b7eb87a0aeddba9a04 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Tue, 26 Nov 2024 06:25:56 +0100 Subject: [PATCH 108/330] tests: Add regression test for self referential struct with cow as last field --- ...lf-referential-struct-cow-as-last-field.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs diff --git a/tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs b/tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs new file mode 100644 index 000000000000..f953eb1c0f74 --- /dev/null +++ b/tests/ui/traits/solver-cycles/107481-self-referential-struct-cow-as-last-field.rs @@ -0,0 +1,19 @@ +// Regression test for #107481 + +//@ check-pass + +use std::{borrow::Cow, collections::HashMap}; + +#[derive(Clone)] +struct Foo<'a>(Cow<'a, [Self]>); + +#[derive(Clone)] +struct Bar<'a>(Cow<'a, HashMap>); + +#[derive(Clone)] +struct Baz<'a>(Cow<'a, Vec>); + +#[derive(Clone)] +struct Qux<'a>(Cow<'a, Box>); + +fn main() {} From 44f4f67f460a3b3c9bb34851d3d812fbdba81936 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Mon, 25 Nov 2024 21:50:26 -0700 Subject: [PATCH 109/330] fix confusing diagnostic for reserved `##` --- compiler/rustc_lint/messages.ftl | 3 ++ .../rustc_lint/src/context/diagnostics.rs | 8 +++- compiler/rustc_lint/src/lints.rs | 7 +++ compiler/rustc_lint_defs/src/lib.rs | 7 ++- compiler/rustc_parse/messages.ftl | 4 ++ compiler/rustc_parse/src/errors.rs | 9 ++++ compiler/rustc_parse/src/lexer/mod.rs | 16 ++++--- .../reserved-guarded-strings-lexing.rs | 24 +++++----- .../reserved-guarded-strings-lexing.stderr | 48 +++++++++---------- .../reserved-guarded-strings-migration.fixed | 20 ++++---- .../reserved-guarded-strings-migration.rs | 20 ++++---- .../reserved-guarded-strings-migration.stderr | 40 ++++++++-------- .../ui/rust-2024/reserved-guarded-strings.rs | 14 +++--- .../rust-2024/reserved-guarded-strings.stderr | 28 +++++------ 14 files changed, 141 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 69fd7f2d8b25..9df0c50868cb 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -733,6 +733,9 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` +lint_reserved_multihash = reserved token in Rust 2024 + .suggestion = insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 + lint_reserved_prefix = prefix `{$prefix}` is unknown .label = unknown prefix .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 565c3c042525..a3731e31c2bd 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -176,8 +176,12 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } .decorate_lint(diag); } - BuiltinLintDiag::ReservedString(suggestion) => { - lints::ReservedString { suggestion }.decorate_lint(diag); + BuiltinLintDiag::ReservedString { is_string, suggestion } => { + if is_string { + lints::ReservedString { suggestion }.decorate_lint(diag); + } else { + lints::ReservedMultihash { suggestion }.decorate_lint(diag); + } } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 352155729e51..9347aa508474 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3059,3 +3059,10 @@ pub(crate) struct ReservedString { #[suggestion(code = " ", applicability = "machine-applicable")] pub suggestion: Span, } + +#[derive(LintDiagnostic)] +#[diag(lint_reserved_multihash)] +pub(crate) struct ReservedMultihash { + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c74fceeedba8..eb761bd6475f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -663,8 +663,11 @@ pub enum BuiltinLintDiag { ReservedPrefix(Span, String), /// `'r#` in edition < 2021. RawPrefix(Span), - /// `##` or `#"` is edition < 2024. - ReservedString(Span), + /// `##` or `#"` in edition < 2024. + ReservedString { + is_string: bool, + suggestion: Span, + }, TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), UnicodeTextFlow(Span, String), diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 8c4f669c332b..b9a325eddd80 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -716,6 +716,10 @@ parse_require_colon_after_labeled_expression = labeled expression must be follow .label = the label .suggestion = add `:` after the label +parse_reserved_multihash = reserved multi-hash token is forbidden + .note = sequences of two or more # are reserved for future use since Rust 2024 + .suggestion_whitespace = consider inserting whitespace here + parse_reserved_string = invalid string literal .note = unprefixed guarded string literals are reserved for future use since Rust 2024 .suggestion_whitespace = consider inserting whitespace here diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 9bdb99dc0007..a48725de54b5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2151,6 +2151,15 @@ pub(crate) enum UnknownPrefixSugg { }, } +#[derive(Diagnostic)] +#[diag(parse_reserved_multihash)] +#[note] +pub(crate) struct ReservedMultihash { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: Option, +} #[derive(Diagnostic)] #[diag(parse_reserved_string)] #[note] diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 5023e83bd67c..787b298c8e42 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -803,7 +803,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let mut cursor = Cursor::new(str_before); - let (span, unterminated) = match cursor.guarded_double_quoted_string() { + let (is_string, span, unterminated) = match cursor.guarded_double_quoted_string() { Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => { let end = start + BytePos(token_len); let span = self.mk_sp(start, end); @@ -816,13 +816,13 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let unterminated = if terminated { None } else { Some(str_start) }; - (span, unterminated) + (true, span, unterminated) } - _ => { + None => { // We should only get here in the `##+` case. debug_assert_eq!(self.str_from_to(start, start + BytePos(2)), "##"); - (span, None) + (false, span, None) } }; if edition2024 { @@ -844,7 +844,11 @@ impl<'psess, 'src> StringReader<'psess, 'src> { }; // In Edition 2024 and later, emit a hard error. - let err = self.dcx().emit_err(errors::ReservedString { span, sugg }); + let err = if is_string { + self.dcx().emit_err(errors::ReservedString { span, sugg }) + } else { + self.dcx().emit_err(errors::ReservedMultihash { span, sugg }) + }; token::Literal(token::Lit { kind: token::Err(err), @@ -857,7 +861,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::ReservedString(space_span), + BuiltinLintDiag::ReservedString { is_string, suggestion: space_span }, ); // For backwards compatibility, roll back to after just the first `#` diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs index 83e0dcbb4beb..43413f7470e8 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs @@ -26,24 +26,24 @@ macro_rules! demo7 { fn main() { demo3!(## "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(### "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(## "foo"#); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo7!(### "foo"###); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo5!(###"foo"#); @@ -56,14 +56,14 @@ fn main() { demo5!(#"foo"###); //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!("foo"###); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 // Non-ascii identifiers diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr index e2e1ac42f05c..4d54a08617b5 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr @@ -28,7 +28,7 @@ error: identifiers cannot contain emoji: `🙃` LL | demo3!(🙃#""); | ^^ -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:28:12 | LL | demo3!(## "foo"); @@ -41,12 +41,12 @@ note: the lint level is defined here | LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo3!(# # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:31:12 | LL | demo4!(### "foo"); @@ -54,12 +54,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# ## "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:31:13 | LL | demo4!(### "foo"); @@ -67,12 +67,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(## # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:36:12 | LL | demo4!(## "foo"#); @@ -80,12 +80,12 @@ LL | demo4!(## "foo"#); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# # "foo"#); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:12 | LL | demo7!(### "foo"###); @@ -93,12 +93,12 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(# ## "foo"###); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:13 | LL | demo7!(### "foo"###); @@ -106,12 +106,12 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(## # "foo"###); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:21 | LL | demo7!(### "foo"###); @@ -119,12 +119,12 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(### "foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:39:22 | LL | demo7!(### "foo"###); @@ -132,7 +132,7 @@ LL | demo7!(### "foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo7!(### "foo"## #); | + @@ -189,7 +189,7 @@ help: insert whitespace here to avoid this being parsed as a guarded string in R LL | demo5!(# "foo"###); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:56:18 | LL | demo5!(#"foo"###); @@ -197,12 +197,12 @@ LL | demo5!(#"foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo5!(#"foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:56:19 | LL | demo5!(#"foo"###); @@ -210,12 +210,12 @@ LL | demo5!(#"foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo5!(#"foo"## #); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:63:17 | LL | demo4!("foo"###); @@ -223,12 +223,12 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-lexing.rs:63:18 | LL | demo4!("foo"###); @@ -236,7 +236,7 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"## #); | + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed index d92df7b5375a..ef00ed3f6107 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed @@ -38,28 +38,28 @@ fn main() { demo2!("foo"#); demo3!(# # "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(# # # "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(# # "foo"#); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo6!(# # # "foo"# #); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!("foo"# # #); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo2!(# ""); @@ -94,6 +94,6 @@ fn main() { //~| WARNING hard error in Rust 2024 //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 } diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.rs b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs index 5905f2abe323..cf2d8716ad2e 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-migration.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs @@ -38,28 +38,28 @@ fn main() { demo2!("foo"#); demo3!(## "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(### "foo"); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!(## "foo"#); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo6!(### "foo"##); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo4!("foo"###); - //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~^ WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 demo2!(#""); @@ -94,6 +94,6 @@ fn main() { //~| WARNING hard error in Rust 2024 //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 - //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING reserved token in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] //~| WARNING hard error in Rust 2024 } diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr index d7f8e5c9b4b2..b17ae941ef41 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr @@ -1,4 +1,4 @@ -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:40:12 | LL | demo3!(## "foo"); @@ -11,12 +11,12 @@ note: the lint level is defined here | LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo3!(# # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:43:12 | LL | demo4!(### "foo"); @@ -24,12 +24,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# ## "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:43:13 | LL | demo4!(### "foo"); @@ -37,12 +37,12 @@ LL | demo4!(### "foo"); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(## # "foo"); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:48:12 | LL | demo4!(## "foo"#); @@ -50,12 +50,12 @@ LL | demo4!(## "foo"#); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!(# # "foo"#); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:51:12 | LL | demo6!(### "foo"##); @@ -63,12 +63,12 @@ LL | demo6!(### "foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo6!(# ## "foo"##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:51:13 | LL | demo6!(### "foo"##); @@ -76,12 +76,12 @@ LL | demo6!(### "foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo6!(## # "foo"##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:51:21 | LL | demo6!(### "foo"##); @@ -89,12 +89,12 @@ LL | demo6!(### "foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo6!(### "foo"# #); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:59:17 | LL | demo4!("foo"###); @@ -102,12 +102,12 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"# ##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:59:18 | LL | demo4!("foo"###); @@ -115,7 +115,7 @@ LL | demo4!("foo"###); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo4!("foo"## #); | + @@ -276,7 +276,7 @@ help: insert whitespace here to avoid this being parsed as a guarded string in R LL | demo5!(## "foo"##); | + -warning: will be parsed as a guarded string in Rust 2024 +warning: reserved token in Rust 2024 --> $DIR/reserved-guarded-strings-migration.rs:92:19 | LL | demo5!(##"foo"##); @@ -284,7 +284,7 @@ LL | demo5!(##"foo"##); | = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see issue #123735 -help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 +help: insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 | LL | demo5!(##"foo"# #); | + diff --git a/tests/ui/rust-2024/reserved-guarded-strings.rs b/tests/ui/rust-2024/reserved-guarded-strings.rs index 878881c1d245..ae68d34cb86e 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings.rs @@ -46,13 +46,13 @@ fn main() { //~^ ERROR prefix `blah` is unknown //~| ERROR invalid string literal - demo2!(## "foo"); //~ ERROR invalid string literal - demo3!("foo"###); //~ ERROR invalid string literal - demo3!(### "foo"); //~ ERROR invalid string literal - demo3!(## "foo"#); //~ ERROR invalid string literal + demo2!(## "foo"); //~ reserved multi-hash token is forbidden + demo3!("foo"###); //~ reserved multi-hash token is forbidden + demo3!(### "foo"); //~ reserved multi-hash token is forbidden + demo3!(## "foo"#); //~ reserved multi-hash token is forbidden demo5!(### "foo"###); - //~^ ERROR invalid string literal - //~| ERROR invalid string literal + //~^ reserved multi-hash token is forbidden + //~| reserved multi-hash token is forbidden demo1!(#""); //~ ERROR invalid string literal demo1!(#""#); //~ ERROR invalid string literal @@ -65,7 +65,7 @@ fn main() { demo1!(###"foo"###); //~ ERROR invalid string literal demo2!(#"foo"###); //~^ ERROR invalid string literal - //~| ERROR invalid string literal + //~| ERROR reserved multi-hash token is forbidden // More than 255 hashes demon!(####################################################################################################################################################################################################################################################################"foo"); diff --git a/tests/ui/rust-2024/reserved-guarded-strings.stderr b/tests/ui/rust-2024/reserved-guarded-strings.stderr index c8f8557b0f4c..0f3b06147c4f 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings.stderr +++ b/tests/ui/rust-2024/reserved-guarded-strings.stderr @@ -34,73 +34,73 @@ help: consider inserting whitespace here LL | demo2!(blah# "xx"#); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:49:12 | LL | demo2!(## "foo"); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo2!(# # "foo"); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:50:17 | LL | demo3!("foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo3!("foo"# ##); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:51:12 | LL | demo3!(### "foo"); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo3!(# ## "foo"); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:52:12 | LL | demo3!(## "foo"#); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo3!(# # "foo"#); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:53:12 | LL | demo5!(### "foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo5!(# ## "foo"###); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:53:21 | LL | demo5!(### "foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo5!(### "foo"# ##); @@ -226,13 +226,13 @@ help: consider inserting whitespace here LL | demo2!(# "foo"###); | + -error: invalid string literal +error: reserved multi-hash token is forbidden --> $DIR/reserved-guarded-strings.rs:66:19 | LL | demo2!(#"foo"###); | ^^ | - = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: sequences of two or more # are reserved for future use since Rust 2024 help: consider inserting whitespace here | LL | demo2!(#"foo"## #); From 6dcac6e2bfbabc9f9552da40c7cc58996452dbe3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 26 Nov 2024 10:55:13 +0100 Subject: [PATCH 110/330] unnecessary_map_or: fix version for lint addition --- clippy_lints/src/methods/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2e9f6ea4731f..7d1d5d69c991 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4129,7 +4129,7 @@ declare_clippy_lint! { /// ) /// } /// ``` - #[clippy::version = "1.75.0"] + #[clippy::version = "1.84.0"] pub UNNECESSARY_MAP_OR, style, "reduce unnecessary calls to `.map_or(bool, …)`" From f0b7008648dbe2fea5d23bb2ad8ce622ddf4e133 Mon Sep 17 00:00:00 2001 From: Sebastian Urban Date: Tue, 26 Nov 2024 14:01:49 +0100 Subject: [PATCH 111/330] thread::available_parallelism for wasm32-wasip1-threads The target has limited POSIX support and provides the sysconf function which allows querying the number of available CPUs. --- library/std/src/sys/pal/wasi/thread.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index 4b83870fdea6..3b44f77631f5 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -2,7 +2,6 @@ use crate::ffi::CStr; use crate::num::NonZero; -use crate::sys::unsupported; use crate::time::Duration; use crate::{io, mem}; @@ -34,6 +33,8 @@ cfg_if::cfg_if! { #[allow(non_camel_case_types)] pub type pthread_t = *mut ffi::c_void; + pub const _SC_NPROCESSORS_ONLN: ffi::c_int = 84; + extern "C" { pub fn pthread_create( native: *mut pthread_t, @@ -121,7 +122,7 @@ impl Thread { } } else { pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { - unsupported() + crate::sys::unsupported() } } } @@ -187,5 +188,15 @@ impl Thread { } pub fn available_parallelism() -> io::Result> { - unsupported() + cfg_if::cfg_if! { + if #[cfg(target_feature = "atomics")] { + match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { + -1 => Err(io::Error::last_os_error()), + 0 => Err(io::Error::UNKNOWN_THREAD_COUNT), + cpus => Ok(unsafe { NonZero::new_unchecked(cpus as usize) }), + } + } else { + crate::sys::unsupported() + } + } } From d3ad00094313d6f777b4f44d707ccd457ce342ca Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 26 Nov 2024 15:25:46 +0100 Subject: [PATCH 112/330] Respect verify-llvm-ir option in the backend We are currently unconditionally verifying the LLVM IR in the backend (twice), ignoring the value of the verify-llvm-ir option. --- compiler/rustc_codegen_llvm/src/back/write.rs | 4 ++++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 6 +++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 00f7b479fa76..2744795d9981 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -61,6 +61,7 @@ fn write_output_file<'ll>( dwo_output: Option<&Path>, file_type: llvm::FileType, self_profiler_ref: &SelfProfilerRef, + verify_llvm_ir: bool, ) -> Result<(), FatalError> { debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output); unsafe { @@ -79,6 +80,7 @@ fn write_output_file<'ll>( output_c.as_ptr(), dwo_output_ptr, file_type, + verify_llvm_ir, ); // Record artifact sizes for self-profiling @@ -840,6 +842,7 @@ pub(crate) unsafe fn codegen( None, llvm::FileType::AssemblyFile, &cgcx.prof, + config.verify_llvm_ir, ) })?; } @@ -877,6 +880,7 @@ pub(crate) unsafe fn codegen( dwo_out, llvm::FileType::ObjectFile, &cgcx.prof, + config.verify_llvm_ir, ) })?; } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 17b0ec4b9360..b1ace0033ba3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2240,6 +2240,7 @@ unsafe extern "C" { Output: *const c_char, DwoOutput: *const c_char, FileType: FileType, + VerifyIR: bool, ) -> LLVMRustResult; pub fn LLVMRustOptimize<'a>( M: &'a Module, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 489c911d7eed..20859b167bc6 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -552,7 +552,7 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) { extern "C" LLVMRustResult LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, LLVMModuleRef M, const char *Path, const char *DwoPath, - LLVMRustFileType RustFileType) { + LLVMRustFileType RustFileType, bool VerifyIR) { llvm::legacy::PassManager *PM = unwrap(PMR); auto FileType = fromRust(RustFileType); @@ -577,10 +577,10 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Failure; } auto DBOS = buffer_ostream(DOS); - unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false); + unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, !VerifyIR); PM->run(*unwrap(M)); } else { - unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, false); + unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, !VerifyIR); PM->run(*unwrap(M)); } From 17fb5adf58bda51c03d9a8794ecd622b8b221cb5 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Tue, 26 Nov 2024 17:36:12 +0100 Subject: [PATCH 113/330] [] Fix FP on proc macros --- clippy_lints/src/operators/bit_mask.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/operators/bit_mask.rs b/clippy_lints/src/operators/bit_mask.rs index 4414056a467c..e87cfd103c30 100644 --- a/clippy_lints/src/operators/bit_mask.rs +++ b/clippy_lints/src/operators/bit_mask.rs @@ -1,5 +1,6 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_from_proc_macro; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::Span; @@ -35,9 +36,9 @@ fn invert_cmp(cmp: BinOpKind) -> BinOpKind { } } -fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp_value: u128, span: Span) { +fn check_compare<'a>(cx: &LateContext<'a>, bit_op: &Expr<'a>, cmp_op: BinOpKind, cmp_value: u128, span: Span) { if let ExprKind::Binary(op, left, right) = &bit_op.kind { - if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr { + if op.node != BinOpKind::BitAnd && op.node != BinOpKind::BitOr || is_from_proc_macro(cx, bit_op) { return; } if let Some(mask) = fetch_int_literal(cx, right).or_else(|| fetch_int_literal(cx, left)) { From 4b8ca28a1e334564fbf7561c6ed6e098e2b9b1a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Tue, 26 Nov 2024 21:49:28 +0100 Subject: [PATCH 114/330] Add '<[T]>::as_array', '<[T]>::as_mut_array', '<*const [T]>::as_array', and '<*mut [T]>::as_mut_array' conversion methods; --- library/core/src/array/mod.rs | 20 ++++------------ library/core/src/lib.rs | 1 + library/core/src/ptr/const_ptr.rs | 16 +++++++++++++ library/core/src/ptr/mut_ptr.rs | 16 +++++++++++++ library/core/src/slice/mod.rs | 38 +++++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 16 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 67fbda34bb93..95c1eb460cd9 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -214,8 +214,8 @@ impl BorrowMut<[T]> for [T; N] { } } -/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if -/// `slice.len() == N`. +/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. +/// Succeeds if `slice.len() == N`. /// /// ``` /// let bytes: [u8; 3] = [1, 0, 2]; @@ -282,13 +282,7 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { #[inline] fn try_from(slice: &'a [T]) -> Result<&'a [T; N], TryFromSliceError> { - if slice.len() == N { - let ptr = slice.as_ptr() as *const [T; N]; - // SAFETY: ok because we just checked that the length fits - unsafe { Ok(&*ptr) } - } else { - Err(TryFromSliceError(())) - } + slice.as_array().ok_or(TryFromSliceError(())) } } @@ -310,13 +304,7 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { #[inline] fn try_from(slice: &'a mut [T]) -> Result<&'a mut [T; N], TryFromSliceError> { - if slice.len() == N { - let ptr = slice.as_mut_ptr() as *mut [T; N]; - // SAFETY: ok because we just checked that the length fits - unsafe { Ok(&mut *ptr) } - } else { - Err(TryFromSliceError(())) - } + slice.as_mut_array().ok_or(TryFromSliceError(())) } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a178d1012547..1089d415eca9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -144,6 +144,7 @@ #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] +#![feature(slice_as_array)] #![feature(slice_as_chunks)] #![feature(slice_ptr_get)] #![feature(str_internals)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0dbe819acb1b..27516789f867 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1526,6 +1526,22 @@ impl *const [T] { self as *const T } + /// Gets a raw pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array(self) -> Option<*const [T; N]> { + if self.len() == N { + let me = self.as_ptr() as *const [T; N]; + Some(me) + } else { + None + } + } + /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index f0204bd0f773..e637edd74591 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1760,6 +1760,22 @@ impl *mut [T] { self.len() == 0 } + /// Gets a raw, mutable pointer to the underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array(self) -> Option<*mut [T; N]> { + if self.len() == N { + let me = self.as_mut_ptr() as *mut [T; N]; + Some(me) + } else { + None + } + } + /// Divides one mutable raw slice into two at an index. /// /// The first will contain all indices from `[0, mid)` (excluding diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c855f963771e..fb1c5a362d6c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -855,6 +855,44 @@ impl [T] { start..end } + /// Gets a reference to the underlying array. + /// + /// If `N` is not exactly equal to slice's the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_array(&self) -> Option<&[T; N]> { + if self.len() == N { + let ptr = self.as_ptr() as *const [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &*ptr }; + Some(me) + } else { + None + } + } + + /// Gets a mutable reference to the slice's underlying array. + /// + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. + #[unstable(feature = "slice_as_array", issue = "133508")] + #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] + #[inline] + #[must_use] + pub const fn as_mut_array(&mut self) -> Option<&mut [T; N]> { + if self.len() == N { + let ptr = self.as_mut_ptr() as *mut [T; N]; + + // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. + let me = unsafe { &mut *ptr }; + Some(me) + } else { + None + } + } + /// Swaps two elements in the slice. /// /// If `a` equals to `b`, it's guaranteed that elements won't change value. From 562a85579e279e7827eb9785055322e0942b6371 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 Nov 2024 18:44:03 +0100 Subject: [PATCH 115/330] ensure JSON-defined targets are consistent --- compiler/rustc_target/src/spec/mod.rs | 367 +++++++++++++++++- .../rustc_target/src/spec/tests/tests_impl.rs | 208 ---------- tests/ui/codegen/mismatched-data-layout.json | 2 +- .../ui/codegen/mismatched-data-layouts.stderr | 2 +- 4 files changed, 366 insertions(+), 213 deletions(-) delete mode 100644 compiler/rustc_target/src/spec/tests/tests_impl.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index fead20ec7d1f..1c7d473447ac 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -34,6 +34,8 @@ //! the target's settings, though `target-feature` and `link-args` will *add* //! to the list specified by the target, rather than replace. +// ignore-tidy-filelength + use std::borrow::Cow; use std::collections::BTreeMap; use std::hash::{Hash, Hasher}; @@ -42,6 +44,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fmt, io}; +use rustc_data_structures::fx::FxHashSet; use rustc_fs_util::try_canonicalize; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -1605,13 +1608,11 @@ macro_rules! supported_targets { #[cfg(test)] mod tests { - mod tests_impl; - // Cannot put this into a separate file without duplication, make an exception. $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(crate::spec::targets::$module::target()); + crate::spec::targets::$module::target().test_target() } )+ } @@ -1998,6 +1999,14 @@ impl TargetWarnings { } } +/// For the [`Target::check_consistency`] function, determines whether the given target is a builtin or a JSON +/// target. +#[derive(Copy, Clone, Debug, PartialEq)] +enum TargetKind { + Json, + Builtin, +} + /// Everything `rustc` knows about how to compile for a specific target. /// /// Every field here must be specified, and has no default value. @@ -2846,6 +2855,357 @@ impl Target { self.max_atomic_width.unwrap_or_else(|| self.pointer_width.into()) } + /// Check some basic consistency of the current target. For JSON targets we are less strict; + /// some of these checks are more guidelines than strict rules. + fn check_consistency(&self, kind: TargetKind) -> Result<(), String> { + macro_rules! check { + ($b:expr, $($msg:tt)*) => { + if !$b { + return Err(format!($($msg)*)); + } + } + } + macro_rules! check_eq { + ($left:expr, $right:expr, $($msg:tt)*) => { + if ($left) != ($right) { + return Err(format!($($msg)*)); + } + } + } + macro_rules! check_ne { + ($left:expr, $right:expr, $($msg:tt)*) => { + if ($left) == ($right) { + return Err(format!($($msg)*)); + } + } + } + macro_rules! check_matches { + ($left:expr, $right:pat, $($msg:tt)*) => { + if !matches!($left, $right) { + return Err(format!($($msg)*)); + } + } + } + + check_eq!( + self.is_like_osx, + self.vendor == "apple", + "`is_like_osx` must be set if and only if `vendor` is `apple`" + ); + check_eq!( + self.is_like_solaris, + self.os == "solaris" || self.os == "illumos", + "`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`" + ); + check_eq!( + self.is_like_windows, + self.os == "windows" || self.os == "uefi", + "`is_like_windows` must be set if and only if `os` is `windows` or `uefi`" + ); + check_eq!( + self.is_like_wasm, + self.arch == "wasm32" || self.arch == "wasm64", + "`is_like_wasm` must be set if and only if `arch` is `wasm32` or `wasm64`" + ); + if self.is_like_msvc { + check!(self.is_like_windows, "if `is_like_msvc` is set, `is_like_windows` must be set"); + } + if self.os == "emscripten" { + check!(self.is_like_wasm, "the `emcscripten` os only makes sense on wasm-like targets"); + } + + // Check that default linker flavor is compatible with some other key properties. + check_eq!( + self.is_like_osx, + matches!(self.linker_flavor, LinkerFlavor::Darwin(..)), + "`linker_flavor` must be `darwin` if and only if `is_like_osx` is set" + ); + check_eq!( + self.is_like_msvc, + matches!(self.linker_flavor, LinkerFlavor::Msvc(..)), + "`linker_flavor` must be `msvc` if and only if `is_like_msvc` is set" + ); + check_eq!( + self.is_like_wasm && self.os != "emscripten", + matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)), + "`linker_flavor` must be `wasm-lld` if and only if `is_like_wasm` is set and the `os` is not `emscripten`", + ); + check_eq!( + self.os == "emscripten", + matches!(self.linker_flavor, LinkerFlavor::EmCc), + "`linker_flavor` must be `em-cc` if and only if `os` is `emscripten`" + ); + check_eq!( + self.arch == "bpf", + matches!(self.linker_flavor, LinkerFlavor::Bpf), + "`linker_flavor` must be `bpf` if and only if `arch` is `bpf`" + ); + check_eq!( + self.arch == "nvptx64", + matches!(self.linker_flavor, LinkerFlavor::Ptx), + "`linker_flavor` must be `ptc` if and only if `arch` is `nvptx64`" + ); + + for args in [ + &self.pre_link_args, + &self.late_link_args, + &self.late_link_args_dynamic, + &self.late_link_args_static, + &self.post_link_args, + ] { + for (&flavor, flavor_args) in args { + check!(!flavor_args.is_empty(), "linker flavor args must not be empty"); + // Check that flavors mentioned in link args are compatible with the default flavor. + match self.linker_flavor { + LinkerFlavor::Gnu(..) => { + check_matches!( + flavor, + LinkerFlavor::Gnu(..), + "mixing GNU and non-GNU linker flavors" + ); + } + LinkerFlavor::Darwin(..) => { + check_matches!( + flavor, + LinkerFlavor::Darwin(..), + "mixing Darwin and non-Darwin linker flavors" + ) + } + LinkerFlavor::WasmLld(..) => { + check_matches!( + flavor, + LinkerFlavor::WasmLld(..), + "mixing wasm and non-wasm linker flavors" + ) + } + LinkerFlavor::Unix(..) => { + check_matches!( + flavor, + LinkerFlavor::Unix(..), + "mixing unix and non-unix linker flavors" + ); + } + LinkerFlavor::Msvc(..) => { + check_matches!( + flavor, + LinkerFlavor::Msvc(..), + "mixing MSVC and non-MSVC linker flavors" + ); + } + LinkerFlavor::EmCc + | LinkerFlavor::Bpf + | LinkerFlavor::Ptx + | LinkerFlavor::Llbc => { + check_eq!(flavor, self.linker_flavor, "mixing different linker flavors") + } + } + + // Check that link args for cc and non-cc versions of flavors are consistent. + let check_noncc = |noncc_flavor| -> Result<(), String> { + if let Some(noncc_args) = args.get(&noncc_flavor) { + for arg in flavor_args { + if let Some(suffix) = arg.strip_prefix("-Wl,") { + check!( + noncc_args.iter().any(|a| a == suffix), + " link args for cc and non-cc versions of flavors are not consistent" + ); + } + } + } + Ok(()) + }; + + match self.linker_flavor { + LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld))?, + LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No))?, + LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No))?, + _ => {} + } + } + + // Check that link args for lld and non-lld versions of flavors are consistent. + for cc in [Cc::No, Cc::Yes] { + check_eq!( + args.get(&LinkerFlavor::Gnu(cc, Lld::No)), + args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)), + "link args for lld and non-lld versions of flavors are not consistent", + ); + check_eq!( + args.get(&LinkerFlavor::Darwin(cc, Lld::No)), + args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)), + "link args for lld and non-lld versions of flavors are not consistent", + ); + } + check_eq!( + args.get(&LinkerFlavor::Msvc(Lld::No)), + args.get(&LinkerFlavor::Msvc(Lld::Yes)), + "link args for lld and non-lld versions of flavors are not consistent", + ); + } + + if self.link_self_contained.is_disabled() { + check!( + self.pre_link_objects_self_contained.is_empty() + && self.post_link_objects_self_contained.is_empty(), + "if `link_self_contained` is disabled, then `pre_link_objects_self_contained` and `post_link_objects_self_contained` must be empty", + ); + } + + // If your target really needs to deviate from the rules below, + // except it and document the reasons. + // Keep the default "unknown" vendor instead. + check_ne!(self.vendor, "", "`vendor` cannot be empty"); + check_ne!(self.os, "", "`os` cannot be empty"); + if !self.can_use_os_unknown() { + // Keep the default "none" for bare metal targets instead. + check_ne!( + self.os, + "unknown", + "`unknown` os can only be used on particular targets; use `none` for bare-metal targets" + ); + } + + // Check dynamic linking stuff. + // We skip this for JSON targets since otherwise, our default values would fail this test. + // These checks are not critical for correctness, but more like default guidelines. + // FIXME (https://github.com/rust-lang/rust/issues/133459): do we want to change the JSON + // target defaults so that they pass these checks? + if kind == TargetKind::Builtin { + // BPF: when targeting user space vms (like rbpf), those can load dynamic libraries. + // hexagon: when targeting QuRT, that OS can load dynamic libraries. + // wasm{32,64}: dynamic linking is inherent in the definition of the VM. + if self.os == "none" + && (self.arch != "bpf" + && self.arch != "hexagon" + && self.arch != "wasm32" + && self.arch != "wasm64") + { + check!( + !self.dynamic_linking, + "dynamic linking is not supported on this OS/architecture" + ); + } + if self.only_cdylib + || self.crt_static_allows_dylibs + || !self.late_link_args_dynamic.is_empty() + { + check!( + self.dynamic_linking, + "dynamic linking must be allowed when `only_cdylib` or `crt_static_allows_dylibs` or `late_link_args_dynamic` are set" + ); + } + // Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs + if self.dynamic_linking && !self.is_like_wasm { + check_eq!( + self.relocation_model, + RelocModel::Pic, + "targets that support dynamic linking must use the `pic` relocation model" + ); + } + if self.position_independent_executables { + check_eq!( + self.relocation_model, + RelocModel::Pic, + "targets that support position-independent executables must use the `pic` relocation model" + ); + } + // The UEFI targets do not support dynamic linking but still require PIC (#101377). + if self.relocation_model == RelocModel::Pic && (self.os != "uefi") { + check!( + self.dynamic_linking || self.position_independent_executables, + "when the relocation model is `pic`, the target must support dynamic linking or use position-independent executables. \ + Set the relocation model to `static` to avoid this requirement" + ); + } + if self.static_position_independent_executables { + check!( + self.position_independent_executables, + "if `static_position_independent_executables` is set, then `position_independent_executables` must be set" + ); + } + if self.position_independent_executables { + check!( + self.executables, + "if `position_independent_executables` is set then `executables` must be set" + ); + } + } + + // Check crt static stuff + if self.crt_static_default || self.crt_static_allows_dylibs { + check!( + self.crt_static_respected, + "static CRT can be enabled but `crt_static_respected` is not set" + ); + } + + // Check that RISC-V targets always specify which ABI they use. + match &*self.arch { + "riscv32" => { + check_matches!( + &*self.llvm_abiname, + "ilp32" | "ilp32f" | "ilp32d" | "ilp32e", + "invalid RISC-V ABI name" + ); + } + "riscv64" => { + // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI. + check_matches!( + &*self.llvm_abiname, + "lp64" | "lp64f" | "lp64d" | "lp64q" | "lp64e", + "invalid RISC-V ABI name" + ); + } + _ => {} + } + + // Check that the given target-features string makes some basic sense. + if !self.features.is_empty() { + let mut features_enabled = FxHashSet::default(); + let mut features_disabled = FxHashSet::default(); + for feat in self.features.split(',') { + if let Some(feat) = feat.strip_prefix("+") { + features_enabled.insert(feat); + if features_disabled.contains(feat) { + return Err(format!( + "target feature `{feat}` is both enabled and disabled" + )); + } + } else if let Some(feat) = feat.strip_prefix("-") { + features_disabled.insert(feat); + if features_enabled.contains(feat) { + return Err(format!( + "target feature `{feat}` is both enabled and disabled" + )); + } + } else { + return Err(format!( + "target feature `{feat}` is invalid, must start with `+` or `-`" + )); + } + } + } + + Ok(()) + } + + /// Test target self-consistency and JSON encoding/decoding roundtrip. + #[cfg(test)] + fn test_target(mut self) { + let recycled_target = Target::from_json(self.to_json()).map(|(j, _)| j); + self.update_to_cli(); + self.check_consistency(TargetKind::Builtin).unwrap(); + assert_eq!(recycled_target, Ok(self)); + } + + // Add your target to the whitelist if it has `std` library + // and you certainly want "unknown" for the OS name. + fn can_use_os_unknown(&self) -> bool { + self.llvm_target == "wasm32-unknown-unknown" + || self.llvm_target == "wasm64-unknown-unknown" + || (self.env == "sgx" && self.vendor == "fortanix") + } + /// Loads a target descriptor from a JSON object. pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> { // While ugly, this code must remain this way to retain @@ -3452,6 +3812,7 @@ impl Target { key!(supports_xray, bool); base.update_from_cli(); + base.check_consistency(TargetKind::Json)?; // Each field should have been read using `Json::remove` so any keys remaining are unused. let remaining_keys = obj.keys(); diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs deleted file mode 100644 index 3225cdc759d9..000000000000 --- a/compiler/rustc_target/src/spec/tests/tests_impl.rs +++ /dev/null @@ -1,208 +0,0 @@ -use std::assert_matches::assert_matches; - -use rustc_data_structures::fx::FxHashSet; - -use super::super::*; - -// Test target self-consistency and JSON encoding/decoding roundtrip. -pub(super) fn test_target(mut target: Target) { - let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j); - target.update_to_cli(); - target.check_consistency(); - assert_eq!(recycled_target, Ok(target)); -} - -impl Target { - fn check_consistency(&self) { - assert_eq!(self.is_like_osx, self.vendor == "apple"); - assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos"); - assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi"); - assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64"); - if self.is_like_msvc { - assert!(self.is_like_windows); - } - if self.os == "emscripten" { - assert!(self.is_like_wasm); - } - - // Check that default linker flavor is compatible with some other key properties. - assert_eq!(self.is_like_osx, matches!(self.linker_flavor, LinkerFlavor::Darwin(..))); - assert_eq!(self.is_like_msvc, matches!(self.linker_flavor, LinkerFlavor::Msvc(..))); - assert_eq!( - self.is_like_wasm && self.os != "emscripten", - matches!(self.linker_flavor, LinkerFlavor::WasmLld(..)) - ); - assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc)); - assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf)); - assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx)); - - for args in [ - &self.pre_link_args, - &self.late_link_args, - &self.late_link_args_dynamic, - &self.late_link_args_static, - &self.post_link_args, - ] { - for (&flavor, flavor_args) in args { - assert!(!flavor_args.is_empty()); - // Check that flavors mentioned in link args are compatible with the default flavor. - match self.linker_flavor { - LinkerFlavor::Gnu(..) => { - assert_matches!(flavor, LinkerFlavor::Gnu(..)); - } - LinkerFlavor::Darwin(..) => { - assert_matches!(flavor, LinkerFlavor::Darwin(..)) - } - LinkerFlavor::WasmLld(..) => { - assert_matches!(flavor, LinkerFlavor::WasmLld(..)) - } - LinkerFlavor::Unix(..) => { - assert_matches!(flavor, LinkerFlavor::Unix(..)); - } - LinkerFlavor::Msvc(..) => { - assert_matches!(flavor, LinkerFlavor::Msvc(..)) - } - LinkerFlavor::EmCc - | LinkerFlavor::Bpf - | LinkerFlavor::Ptx - | LinkerFlavor::Llbc => { - assert_eq!(flavor, self.linker_flavor) - } - } - - // Check that link args for cc and non-cc versions of flavors are consistent. - let check_noncc = |noncc_flavor| { - if let Some(noncc_args) = args.get(&noncc_flavor) { - for arg in flavor_args { - if let Some(suffix) = arg.strip_prefix("-Wl,") { - assert!(noncc_args.iter().any(|a| a == suffix)); - } - } - } - }; - - match self.linker_flavor { - LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld)), - LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No)), - LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No)), - _ => {} - } - } - - // Check that link args for lld and non-lld versions of flavors are consistent. - for cc in [Cc::No, Cc::Yes] { - assert_eq!( - args.get(&LinkerFlavor::Gnu(cc, Lld::No)), - args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)), - ); - assert_eq!( - args.get(&LinkerFlavor::Darwin(cc, Lld::No)), - args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)), - ); - } - assert_eq!( - args.get(&LinkerFlavor::Msvc(Lld::No)), - args.get(&LinkerFlavor::Msvc(Lld::Yes)), - ); - } - - if self.link_self_contained.is_disabled() { - assert!( - self.pre_link_objects_self_contained.is_empty() - && self.post_link_objects_self_contained.is_empty() - ); - } - - // If your target really needs to deviate from the rules below, - // except it and document the reasons. - // Keep the default "unknown" vendor instead. - assert_ne!(self.vendor, ""); - assert_ne!(self.os, ""); - if !self.can_use_os_unknown() { - // Keep the default "none" for bare metal targets instead. - assert_ne!(self.os, "unknown"); - } - - // Check dynamic linking stuff - // BPF: when targeting user space vms (like rbpf), those can load dynamic libraries. - // hexagon: when targeting QuRT, that OS can load dynamic libraries. - // wasm{32,64}: dynamic linking is inherent in the definition of the VM. - if self.os == "none" - && (self.arch != "bpf" - && self.arch != "hexagon" - && self.arch != "wasm32" - && self.arch != "wasm64") - { - assert!(!self.dynamic_linking); - } - if self.only_cdylib - || self.crt_static_allows_dylibs - || !self.late_link_args_dynamic.is_empty() - { - assert!(self.dynamic_linking); - } - // Apparently PIC was slow on wasm at some point, see comments in wasm_base.rs - if self.dynamic_linking && !self.is_like_wasm { - assert_eq!(self.relocation_model, RelocModel::Pic); - } - if self.position_independent_executables { - assert_eq!(self.relocation_model, RelocModel::Pic); - } - // The UEFI targets do not support dynamic linking but still require PIC (#101377). - if self.relocation_model == RelocModel::Pic && self.os != "uefi" { - assert!(self.dynamic_linking || self.position_independent_executables); - } - if self.static_position_independent_executables { - assert!(self.position_independent_executables); - } - if self.position_independent_executables { - assert!(self.executables); - } - - // Check crt static stuff - if self.crt_static_default || self.crt_static_allows_dylibs { - assert!(self.crt_static_respected); - } - - // Check that RISC-V targets always specify which ABI they use. - match &*self.arch { - "riscv32" => { - assert_matches!(&*self.llvm_abiname, "ilp32" | "ilp32f" | "ilp32d" | "ilp32e") - } - "riscv64" => { - // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI. - assert_matches!(&*self.llvm_abiname, "lp64" | "lp64f" | "lp64d" | "lp64q" | "lp64e") - } - _ => {} - } - - // Check that the given target-features string makes some basic sense. - if !self.features.is_empty() { - let mut features_enabled = FxHashSet::default(); - let mut features_disabled = FxHashSet::default(); - for feat in self.features.split(',') { - if let Some(feat) = feat.strip_prefix("+") { - features_enabled.insert(feat); - if features_disabled.contains(feat) { - panic!("target feature `{feat}` is both enabled and disabled"); - } - } else if let Some(feat) = feat.strip_prefix("-") { - features_disabled.insert(feat); - if features_enabled.contains(feat) { - panic!("target feature `{feat}` is both enabled and disabled"); - } - } else { - panic!("target feature `{feat}` is invalid, must start with `+` or `-`"); - } - } - } - } - - // Add your target to the whitelist if it has `std` library - // and you certainly want "unknown" for the OS name. - fn can_use_os_unknown(&self) -> bool { - self.llvm_target == "wasm32-unknown-unknown" - || self.llvm_target == "wasm64-unknown-unknown" - || (self.env == "sgx" && self.vendor == "fortanix") - } -} diff --git a/tests/ui/codegen/mismatched-data-layout.json b/tests/ui/codegen/mismatched-data-layout.json index 4cb0602dc75b..7adc88325247 100644 --- a/tests/ui/codegen/mismatched-data-layout.json +++ b/tests/ui/codegen/mismatched-data-layout.json @@ -5,7 +5,7 @@ "target-endian": "little", "target-pointer-width": "64", "target-c-int-width": "32", - "os": "unknown", + "os": "none", "linker-flavor": "ld.lld", "linker": "rust-lld", "executables": true diff --git a/tests/ui/codegen/mismatched-data-layouts.stderr b/tests/ui/codegen/mismatched-data-layouts.stderr index 1fe242266dff..b7d5d82bee08 100644 --- a/tests/ui/codegen/mismatched-data-layouts.stderr +++ b/tests/ui/codegen/mismatched-data-layouts.stderr @@ -1,4 +1,4 @@ -error: data-layout for target `mismatched-data-layout-7814813422914914169`, `normalized data layout`, differs from LLVM target's `x86_64-unknown-none-gnu` default layout, `normalized data layout` +error: data-layout for target `mismatched-data-layout-7193370089426056427`, `normalized data layout`, differs from LLVM target's `x86_64-unknown-none-gnu` default layout, `normalized data layout` error: aborting due to 1 previous error From 174ad448c7c5d71232bf50661f91b319b7e2a7e6 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 25 Nov 2024 11:46:46 +0000 Subject: [PATCH 116/330] replace placeholder version --- compiler/rustc_feature/src/accepted.rs | 6 +++--- compiler/rustc_feature/src/removed.rs | 2 +- compiler/rustc_feature/src/unstable.rs | 4 ++-- library/alloc/src/boxed/convert.rs | 4 ++-- library/alloc/src/ffi/c_str.rs | 6 +++--- library/alloc/src/rc.rs | 4 ++-- library/alloc/src/sync.rs | 4 ++-- library/core/src/cell.rs | 4 ++-- library/core/src/char/methods.rs | 8 ++++---- library/core/src/fmt/mod.rs | 2 +- library/core/src/intrinsics/mod.rs | 6 +++--- library/core/src/mem/maybe_uninit.rs | 2 +- library/core/src/net/ip_addr.rs | 8 ++++---- library/core/src/num/int_macros.rs | 8 ++++---- library/core/src/num/mod.rs | 4 ++-- library/core/src/num/nonzero.rs | 8 ++++---- library/core/src/num/uint_macros.rs | 4 ++-- library/core/src/option.rs | 8 ++++---- library/core/src/panic.rs | 2 +- library/core/src/panic/panic_info.rs | 2 +- library/core/src/pin.rs | 22 +++++++++++----------- library/core/src/ptr/const_ptr.rs | 12 ++++++------ library/core/src/ptr/mod.rs | 20 ++++++++++---------- library/core/src/ptr/mut_ptr.rs | 14 +++++++------- library/core/src/ptr/non_null.rs | 6 +++--- library/core/src/slice/ascii.rs | 4 ++-- library/core/src/str/mod.rs | 4 ++-- library/core/src/sync/atomic.rs | 6 +++--- library/std/src/ffi/os_str.rs | 6 +++--- library/std/src/os/darwin/mod.rs | 2 +- library/std/src/path.rs | 6 +++--- 31 files changed, 99 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e910415c3457..9cf59b02731d 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -225,7 +225,7 @@ declare_features! ( /// Allows the use of `if let` expressions. (accepted, if_let, "1.0.0", None), /// Rescoping temporaries in `if let` to align with Rust 2024. - (accepted, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), + (accepted, if_let_rescope, "1.84.0", Some(124085)), /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. (accepted, if_while_or_patterns, "1.33.0", Some(48215)), /// Allows lifetime elision in `impl` headers. For example: @@ -357,7 +357,7 @@ declare_features! ( (accepted, repr_transparent, "1.28.0", Some(43036)), /// Allows enums like Result to be used across FFI, if T's niche value can /// be used to describe E or vice-versa. - (accepted, result_ffi_guarantees, "CURRENT_RUSTC_VERSION", Some(110503)), + (accepted, result_ffi_guarantees, "1.84.0", Some(110503)), /// Allows return-position `impl Trait` in traits. (accepted, return_position_impl_trait_in_trait, "1.75.0", Some(91611)), /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). @@ -367,7 +367,7 @@ declare_features! ( /// Allows `Self` struct constructor (RFC 2302). (accepted, self_struct_ctor, "1.32.0", Some(51994)), /// Shortern the tail expression lifetime - (accepted, shorter_tail_lifetimes, "CURRENT_RUSTC_VERSION", Some(123739)), + (accepted, shorter_tail_lifetimes, "1.84.0", Some(123739)), /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254)), /// Allows use of `&foo[a..b]` as a slicing syntax. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 6ff70044eed4..69a14bd9f120 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -101,7 +101,7 @@ declare_features! ( /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None), /// Uses generic effect parameters for ~const bounds - (removed, effects, "CURRENT_RUSTC_VERSION", Some(102090), + (removed, effects, "1.84.0", Some(102090), Some("removed, redundant with `#![feature(const_trait_impl)]`")), /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index aa2e451ef394..e3b36fe45cbb 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -338,7 +338,7 @@ declare_features! ( (unstable, riscv_target_feature, "1.45.0", Some(44839)), (unstable, rtm_target_feature, "1.35.0", Some(44839)), (unstable, s390x_target_feature, "1.82.0", Some(44839)), - (unstable, sparc_target_feature, "CURRENT_RUSTC_VERSION", Some(132783)), + (unstable, sparc_target_feature, "1.84.0", Some(132783)), (unstable, sse4a_target_feature, "1.27.0", Some(44839)), (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), @@ -538,7 +538,7 @@ declare_features! ( /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), /// Enables the generic const args MVP (only bare paths, not arbitrary computation). - (incomplete, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980)), + (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs index 4430fff66775..255cefb1e78f 100644 --- a/library/alloc/src/boxed/convert.rs +++ b/library/alloc/src/boxed/convert.rs @@ -110,7 +110,7 @@ impl From<&[T]> for Box<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut [T]> for Box<[T]> { /// Converts a `&mut [T]` into a `Box<[T]>` /// @@ -171,7 +171,7 @@ impl From<&str> for Box { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut str> for Box { /// Converts a `&mut str` into a `Box` /// diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index d91682b796e4..c739832bc784 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -773,7 +773,7 @@ impl From<&CStr> for Box { } #[cfg(not(test))] -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Box { /// Converts a `&mut CStr` into a `Box`, /// by copying the contents into a newly allocated [`Box`]. @@ -921,7 +921,7 @@ impl From<&CStr> for Arc { } #[cfg(target_has_atomic = "ptr")] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Arc { /// Converts a `&mut CStr` into a `Arc`, /// by copying the contents into a newly allocated [`Arc`]. @@ -953,7 +953,7 @@ impl From<&CStr> for Rc { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut CStr> for Rc { /// Converts a `&mut CStr` into a `Rc`, /// by copying the contents into a newly allocated [`Rc`]. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3a9bd1b5bf11..48ffdcb77d31 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2659,7 +2659,7 @@ impl From<&[T]> for Rc<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut [T]> for Rc<[T]> { /// Allocates a reference-counted slice and fills it by cloning `v`'s items. /// @@ -2698,7 +2698,7 @@ impl From<&str> for Rc { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut str> for Rc { /// Allocates a reference-counted string slice and copies `v` into it. /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index da2d6bb3bce2..f7d1c9e4efb4 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3618,7 +3618,7 @@ impl From<&[T]> for Arc<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut [T]> for Arc<[T]> { /// Allocates a reference-counted slice and fills it by cloning `v`'s items. /// @@ -3657,7 +3657,7 @@ impl From<&str> for Arc { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut str> for Arc { /// Allocates a reference-counted `str` and copies `v` into it. /// diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index bfd2a71f97b2..d62cb28fc572 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2133,8 +2133,8 @@ impl UnsafeCell { /// assert_eq!(*uc.get_mut(), 41); /// ``` #[inline(always)] - #[stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] + #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(value: &mut T) -> &mut UnsafeCell { // SAFETY: `UnsafeCell` has the same memory layout as `T` due to #[repr(transparent)]. diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 974e7baccf7b..86822af31ca2 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -729,7 +729,7 @@ impl char { /// '𝕊'.encode_utf16(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0")] #[inline] pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { encode_utf16_raw(self as u32, dst) @@ -1299,7 +1299,7 @@ impl char { /// /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); @@ -1325,7 +1325,7 @@ impl char { /// /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); @@ -1838,7 +1838,7 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] #[cfg_attr( bootstrap, - rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION") + rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0") )] #[doc(hidden)] #[inline] diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 2b1692a195e5..9db6d27967ff 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -438,7 +438,7 @@ impl<'a> Arguments<'a> { /// assert_eq!(format_args!("{:?}", std::env::current_dir()).as_str(), None); /// ``` #[stable(feature = "fmt_as_str", since = "1.52.0")] - #[rustc_const_stable(feature = "const_arguments_as_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")] #[must_use] #[inline] pub const fn as_str(&self) -> Option<&'static str> { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 2f75bfae988f..8741e1b08075 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1494,7 +1494,7 @@ pub const fn cold_path() {} /// This intrinsic does not have a stable counterpart. #[cfg_attr( bootstrap, - rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") + rustc_const_stable(feature = "const_likely", since = "1.84.0") )] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] @@ -1526,7 +1526,7 @@ pub const fn likely(b: bool) -> bool { /// This intrinsic does not have a stable counterpart. #[cfg_attr( bootstrap, - rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") + rustc_const_stable(feature = "const_likely", since = "1.84.0") )] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] @@ -3629,7 +3629,7 @@ pub(crate) macro const_eval_select { /// ``` #[cfg_attr( bootstrap, - rustc_const_stable(feature = "const_is_val_statically_known", since = "CURRENT_RUSTC_VERSION") + rustc_const_stable(feature = "const_is_val_statically_known", since = "1.84.0") )] #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] #[rustc_nounwind] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 27273e4eedf3..476a8f823cb6 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -913,7 +913,7 @@ impl MaybeUninit { #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] #[rustc_const_stable( feature = "const_maybe_uninit_assume_init", - since = "CURRENT_RUSTC_VERSION" + since = "1.84.0" )] #[inline(always)] pub const unsafe fn assume_init_mut(&mut self) -> &mut T { diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 6746f0b2b316..82f11f0eaac3 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1601,8 +1601,8 @@ impl Ipv6Addr { /// ``` #[must_use] #[inline] - #[stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")] pub const fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 } @@ -1679,8 +1679,8 @@ impl Ipv6Addr { /// ``` #[must_use] #[inline] - #[stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")] + #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")] pub const fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 64dcb4c91e62..9e1474ecd1bb 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1613,8 +1613,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")] /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2860,8 +2860,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9d9897b9cf05..4278fec9f58c 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -677,7 +677,7 @@ impl u8 { /// /// [`to_ascii_uppercase`]: Self::to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); @@ -703,7 +703,7 @@ impl u8 { /// /// [`to_ascii_lowercase`]: Self::to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index b883a0c2ec7f..dba64d5dc8e3 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -139,9 +139,9 @@ impl_nonzero_fmt! { LowerHex #[stable(feature = "nonzero", since = "1.28.0")] UpperHex - #[stable(feature = "nonzero_fmt_exp", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_fmt_exp", since = "1.84.0")] LowerExp - #[stable(feature = "nonzero_fmt_exp", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_fmt_exp", since = "1.84.0")] UpperExp } @@ -1587,8 +1587,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Some(()) /// # } /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0383c13fa082..d398119624a0 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2838,8 +2838,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")] /// ``` - #[stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "isqrt", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "isqrt", since = "1.84.0")] + #[rustc_const_stable(feature = "isqrt", since = "1.84.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 29d1956af955..a12fb6a827e7 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -738,7 +738,7 @@ impl Option { #[inline] #[must_use] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { // FIXME(const-hack): use `map` once that is possible match Pin::get_ref(self).as_ref() { @@ -755,7 +755,7 @@ impl Option { #[inline] #[must_use] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_pin_mut(self: Pin<&mut Self>) -> Option> { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. @@ -802,7 +802,7 @@ impl Option { #[inline] #[must_use] #[stable(feature = "option_as_slice", since = "1.75.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_slice(&self) -> &[T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to @@ -857,7 +857,7 @@ impl Option { #[inline] #[must_use] #[stable(feature = "option_as_slice", since = "1.75.0")] - #[rustc_const_stable(feature = "const_option_ext", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option_ext", since = "1.84.0")] pub const fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: When the `Option` is `Some`, we're using the actual pointer // to the payload, with a length of 1, so this is equivalent to diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 179aadf0c286..1e61cfd804c2 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -208,7 +208,7 @@ pub macro const_panic { #[rustc_allow_const_fn_unstable(const_eval_select)] #[inline(always)] // inline the wrapper #[track_caller] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))] + #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "1.84.0"))] const fn do_panic($($arg: $ty),*) -> ! { $crate::intrinsics::const_eval_select!( @capture { $($arg: $ty = $arg),* } -> !: diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 230a9918dbf3..9d53567a26fd 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -165,7 +165,7 @@ impl<'a> PanicMessage<'a> { /// /// See [`fmt::Arguments::as_str`] for details. #[stable(feature = "panic_info_message", since = "1.81.0")] - #[rustc_const_stable(feature = "const_arguments_as_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_arguments_as_str", since = "1.84.0")] #[must_use] #[inline] pub const fn as_str(&self) -> Option<&'static str> { diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index c14c49a0d92f..ee8ec1ad41ed 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1186,7 +1186,7 @@ impl> Pin { /// let mut pinned: Pin<&mut u8> = Pin::new(&mut val); /// ``` #[inline(always)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn new(pointer: Ptr) -> Pin { // SAFETY: the value pointed to is `Unpin`, and so has no requirements @@ -1215,7 +1215,7 @@ impl> Pin { /// ``` #[inline(always)] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const fn into_inner(pin: Pin) -> Ptr { pin.__pointer @@ -1352,7 +1352,7 @@ impl Pin { /// [`pin` module docs]: self #[lang = "new_unchecked"] #[inline(always)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin { Pin { __pointer: pointer } @@ -1423,7 +1423,7 @@ impl Pin { /// move in the future, and this method does not enable the pointee to move. "Malicious" /// implementations of `Ptr::DerefMut` are likewise ruled out by the contract of /// `Pin::new_unchecked`. - #[stable(feature = "pin_deref_mut", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "pin_deref_mut", since = "1.84.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline(always)] pub fn as_deref_mut(self: Pin<&mut Pin>) -> Pin<&mut Ptr::Target> { @@ -1505,7 +1505,7 @@ impl Pin { /// instead. #[inline(always)] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { pin.__pointer @@ -1561,7 +1561,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// ["pinning projections"]: self#projections-and-structural-pinning #[inline(always)] #[must_use] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn get_ref(self) -> &'a T { self.__pointer @@ -1572,7 +1572,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn into_ref(self) -> Pin<&'a T> { Pin { __pointer: self.__pointer } @@ -1590,7 +1590,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const fn get_mut(self) -> &'a mut T where T: Unpin, @@ -1611,7 +1611,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[inline(always)] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "pin", since = "1.33.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { self.__pointer } @@ -1654,7 +1654,7 @@ impl Pin<&'static T> { /// This is safe because `T` is borrowed immutably for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const fn static_ref(r: &'static T) -> Pin<&'static T> { // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). @@ -1668,7 +1668,7 @@ impl Pin<&'static mut T> { /// This is safe because `T` is borrowed for the `'static` lifetime, which /// never ends. #[stable(feature = "pin_static_ref", since = "1.61.0")] - #[rustc_const_stable(feature = "const_pin", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> { // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 0dbe819acb1b..dfe905544af9 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -29,7 +29,7 @@ impl *const T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] @@ -159,7 +159,7 @@ impl *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline(always)] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn addr(self) -> usize { // A pointer-to-integer transmute currently has exactly the right semantics: it returns the // address without exposing the provenance. Note that this is *not* a stable guarantee about @@ -193,7 +193,7 @@ impl *const T { /// [`with_exposed_provenance`]: with_exposed_provenance #[must_use] #[inline(always)] - #[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "exposed_provenance", since = "1.84.0")] pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } @@ -211,7 +211,7 @@ impl *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn with_addr(self, addr: usize) -> Self { // This should probably be an intrinsic to avoid doing any sort of arithmetic, but // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's @@ -230,7 +230,7 @@ impl *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } @@ -282,7 +282,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 805edddfe631..6147e9f5e619 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -591,8 +591,8 @@ pub const fn null_mut() -> *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn without_provenance(addr: usize) -> *const T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute @@ -613,8 +613,8 @@ pub const fn without_provenance(addr: usize) -> *const T { /// some other means. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn dangling() -> *const T { without_provenance(mem::align_of::()) } @@ -634,8 +634,8 @@ pub const fn dangling() -> *const T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn without_provenance_mut(addr: usize) -> *mut T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute @@ -656,8 +656,8 @@ pub const fn without_provenance_mut(addr: usize) -> *mut T { /// some other means. #[inline(always)] #[must_use] -#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "strict_provenance", since = "1.84.0")] +#[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] pub const fn dangling_mut() -> *mut T { without_provenance_mut(mem::align_of::()) } @@ -695,7 +695,7 @@ pub const fn dangling_mut() -> *mut T { /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. #[must_use] #[inline(always)] -#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exposed_provenance", since = "1.84.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub fn with_exposed_provenance(addr: usize) -> *const T { @@ -735,7 +735,7 @@ pub fn with_exposed_provenance(addr: usize) -> *const T { /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API. #[must_use] #[inline(always)] -#[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exposed_provenance", since = "1.84.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub fn with_exposed_provenance_mut(addr: usize) -> *mut T { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index f0204bd0f773..5ed0b39f33b7 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -29,7 +29,7 @@ impl *mut T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { @@ -146,7 +146,7 @@ impl *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline(always)] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn addr(self) -> usize { // A pointer-to-integer transmute currently has exactly the right semantics: it returns the // address without exposing the provenance. Note that this is *not* a stable guarantee about @@ -179,7 +179,7 @@ impl *mut T { /// /// [`with_exposed_provenance_mut`]: with_exposed_provenance_mut #[inline(always)] - #[stable(feature = "exposed_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "exposed_provenance", since = "1.84.0")] pub fn expose_provenance(self) -> usize { self.cast::<()>() as usize } @@ -197,7 +197,7 @@ impl *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn with_addr(self, addr: usize) -> Self { // This should probably be an intrinsic to avoid doing any sort of arithmetic, but // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's @@ -216,7 +216,7 @@ impl *mut T { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self { self.with_addr(f(self.addr())) } @@ -271,7 +271,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a @@ -619,7 +619,7 @@ impl *mut T { /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index b69f8a4b9d3e..0fb5880fd1a0 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -278,7 +278,7 @@ impl NonNull { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn addr(self) -> NonZero { // SAFETY: The pointer is guaranteed by the type to be non-null, // meaning that the address will be non-zero. @@ -293,7 +293,7 @@ impl NonNull { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn with_addr(self, addr: NonZero) -> Self { // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) } @@ -307,7 +307,7 @@ impl NonNull { /// This is a [Strict Provenance][crate::ptr#strict-provenance] API. #[must_use] #[inline] - #[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance", since = "1.84.0")] pub fn map_addr(self, f: impl FnOnce(NonZero) -> NonZero) -> Self { self.with_addr(f(self.addr())) } diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 17ad4fd8f677..7cdb896586f1 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -88,7 +88,7 @@ impl [u8] { /// /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. @@ -110,7 +110,7 @@ impl [u8] { /// /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { // FIXME(const-hack): We would like to simply iterate using `for` loops but this isn't currently allowed in constant expressions. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 4629b770cb46..189ab39e976f 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2503,7 +2503,7 @@ impl str { /// assert_eq!("GRüßE, JüRGEN ❤", s); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_uppercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. @@ -2531,7 +2531,7 @@ impl str { /// assert_eq!("grÜße, jÜrgen ❤", s); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_make_ascii", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")] #[inline] pub const fn make_ascii_lowercase(&mut self) { // SAFETY: changing ASCII letters only does not invalidate UTF-8. diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 7f2a5424787f..487fffba881b 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -469,7 +469,7 @@ impl AtomicBool { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -1264,7 +1264,7 @@ impl AtomicPtr { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -2263,7 +2263,7 @@ macro_rules! atomic_int { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 328185d1f2b0..fff140f1564f 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1229,7 +1229,7 @@ impl From<&OsStr> for Box { } } -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut OsStr> for Box { /// Copies the string into a newly allocated [Box]<[OsStr]>. #[inline] @@ -1309,7 +1309,7 @@ impl From<&OsStr> for Arc { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut OsStr> for Arc { /// Copies the string into a newly allocated [Arc]<[OsStr]>. #[inline] @@ -1339,7 +1339,7 @@ impl From<&OsStr> for Rc { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut OsStr> for Rc { /// Copies the string into a newly allocated [Rc]<[OsStr]>. #[inline] diff --git a/library/std/src/os/darwin/mod.rs b/library/std/src/os/darwin/mod.rs index 7a057ddb861b..3b1bd974fa31 100644 --- a/library/std/src/os/darwin/mod.rs +++ b/library/std/src/os/darwin/mod.rs @@ -13,7 +13,7 @@ //! `aarch64-apple-darwin` target names, which are mostly named that way for //! legacy reasons. -#![stable(feature = "os_darwin", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "os_darwin", since = "1.84.0")] #![doc(cfg(target_vendor = "apple"))] pub mod fs; diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 33a3e4332f37..635c7bca0e01 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1762,7 +1762,7 @@ impl From<&Path> for Box { } } -#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "box_from_mut_slice", since = "1.84.0")] impl From<&mut Path> for Box { /// Creates a boxed [`Path`] from a reference. /// @@ -2000,7 +2000,7 @@ impl From<&Path> for Arc { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut Path> for Arc { /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer. #[inline] @@ -2030,7 +2030,7 @@ impl From<&Path> for Rc { } } -#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "shared_from_mut_slice", since = "1.84.0")] impl From<&mut Path> for Rc { /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer. #[inline] From be78dabe186f72279c119fe73a7754b2f16650e1 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 27 Nov 2024 12:12:23 +0000 Subject: [PATCH 117/330] bump stage0 --- src/stage0 | 900 ++++++++++++++++++++++++++--------------------------- 1 file changed, 450 insertions(+), 450 deletions(-) diff --git a/src/stage0 b/src/stage0 index 57a01edb6fdc..23ee3304b422 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,456 +14,456 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2024-10-16 +compiler_date=2024-11-27 compiler_version=beta -rustfmt_date=2024-10-16 +rustfmt_date=2024-11-27 rustfmt_version=nightly -dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.gz=24719797bf50fb494c61cf4711d6bb238ea9e789a1b10d957abb23f9849a06cd -dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.xz=5eed456f0034e2b31ed4f6089163dd5e86ecb04630371e408aca741c32d845c5 -dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f337d992f4a730d39ae571d602f15d2c66ed0b6abf1b2c63112b570e855ac409 -dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d22b4f26ba8b82e32114311c1f0386d0126eecffa2accab8ca9ecd6a7aa38400 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=047735b5c90fca9f26e5eca2a1d24dcac6fdddfddcb89c9d1e2f6d0af0199946 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c70bce1fa2a6e98577683d94473ca7046e8add65b85792e9887fee4edb8bdcb7 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.gz=4c75417b640557b35172ea384fa34a3e8da1960efdf4a40cf8d1fdbdd50ee997 -dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.xz=f7f5e67b831af5fdb28266fadd7cfd9f092c066f7e7322b058d6fb2bc7f6ff77 -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=5d94f4e51767b02ddcdafdcaba3404a3133d308fe98c7bf5145a41bde8146319 -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=49166b4eb2e18e009ebde1e4c133adcacc3d5257fbd63b07418642d5c841957a -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=9e51ecc782cf9738adafd70c055ed793ab895c9616619c525cb52d7412cdf884 -dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=d60502f25273c2552997de281727b0f5914a2a97f32310f921ea714c5a1080d7 -dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=5796a33eda8d7b47c8982d3a2e425728cf681043151a291fea107b3aca9ff1a7 -dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=71fb2132822aa284cae878a76f9996092316942f84dc5a674fb8be17eb391cb0 -dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.gz=d089cdb87961d00e7dc51c767993342a2fa704756a94c421be7f195dfa6c5293 -dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.xz=42865105f308f7e0cf9af250b54086eaa20da8ef13e9cbf82380340a9db4ce90 -dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.gz=5753e00d74de3ceb1af0dc533496d7db6295d673eb05aea779734a519b5f789f -dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.xz=dff93d0c39e8653f01248f0db05123018c63c92a1d3861935b12ad1818b00864 -dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.gz=4e2e06e503be7d15211dad18911ce951491d2596cef466ae8282af840184427c -dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.xz=77d0d69f3e0c2b32bd1ccb73f12b5b770a1a720e7928859d454f42e611f77d67 -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=5faa3516ecfe77f8fb21ba80e78c21a1b039f5fffae508cceffd04c8c329f152 -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=8f086e53b3abffd7c947f5b0784f9977ed4559e654805bc3877ada99072d38e4 -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=2147f76d151c513aaef63cb2365bb2c9a8d0eb21a6b1c7c2ff535dab0882c46a -dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=db2c17f1f3e0af9ad56982e1396a031df07939aa04c73795f541b16161fc3bdf -dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e5d3fabc7902695ccf85171dd16cfe772a480dce203004da0853170450e57b1c -dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=db2f03a41470e60a0070b4d96590ae049c23d2c0f8c07a5778023a4ecf3e52eb -dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=49610d2df0b6ece6b2afc583db707eed0a6a12ef99a8ba0a82f9acb7c1e15fca -dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=801a92eebf0c068c88a48129b054c4ecea143f38468ff5d53e28fd00a0fad6de -dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=db8a9c4bc9313627d5ad2ed2ebe91b6129958254a32862aec67edee10cdf9bca -dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=fb2f2f2acb7516d98a6abf17e84e8b36beb7179c69776d69465f1c981466321d -dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=87effe21c4b4333769fa7b4b0fc4bd43edaabc1c8ba33e75480cb4da0d59dae9 -dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=71701db843d0974b4fc09afb65e3872faaaf66bfda258c9627576efe8f998f96 -dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.gz=6485ed4c99deffdde4eee34e46b8be2eeb65a3f8f4b4eb032a4ccd9c6f4e29e7 -dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.xz=e8ee8b61386d490c8e59e0c2ccb30fb7758ea0ff0b1448d5f946d9fc58496a11 -dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.gz=23e36a4892e948a6dc231d15913562f1f95f798a62a38315a6b19244aaf78385 -dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.xz=2db43b3b599eab832a13c784d3a1bc60c3222f5bfce8e112688e1478837b8c25 -dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.gz=099c529cc84219ae3ed9a33dbc5265c46a01c8cffb8989e66e367078bc981eec -dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.xz=efef4dd4a40d4f96d151293031783688c84b088a5f2cdde84d931bd44aee923a -dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28633202a502121e9369e93a8cc66bcb52b2cc959d7598f9bbb8e4c840381baa -dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.xz=c7b879d2e7d7c21eafc7b8e9f18f009d2d38f91a2eafa51d25d38e3b51e17ef3 -dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.gz=69bdb56ac4f47fa614fa9e8be5218a492d31a423454c192ed5850f49357687e5 -dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.xz=36c995c1dd55ab4501f250a77f27cce34330daa2a3e74129ce389aa23b4e3a05 -dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.gz=84bb641a5576ef0e93c7b5bae7417eae344f32271a0ebc31bb987d15316815a3 -dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.xz=a7311a345dddc9f8cf1eab6b3e82658fadb485bd755a115d4d6ffdfb42a5625e -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=9def7618829111d1014e21fb0bc10abc26459e59ce61fdac5fb3b63583f472c6 -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=97d124a65a7d7e5610901521b565ff031313685cc37a1caf89de58d952065c3c -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.gz=101a440c383011cb4621825481582a81bfbad0ac03439542bd8d05ccb5aaf2c4 -dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.xz=4148b4311ce8e1cc5dae86d5f27e207496b85e5c23a53c7bc5b05ba18918f717 -dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.gz=25c5c35f2acd37a7c72eb8dc546cb6e9f62b3e76e1569d188bbe2aa9b31ea3e1 -dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.xz=9b84ce176d4015ed8f6946ef2d42f2f601cf419d1a6477f44bd6b7c7d27c95fc -dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.gz=ebdf49b8d4fab00c7fb4d396c54caf5cb234389b7353856734b960f908c3cff9 -dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.xz=4d0d5fbc235d8cc78e9997302c45916008e203ba7f02edcd061290fb9639ee8f -dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.gz=6693f5a06df0ea5929df18b633ad6373d098db4454d0e1d35e4c19b6dd7fa4ed -dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.xz=351a1a2a13316161edcf97238d868cf4b1b5216bdf28ca0aff5a1dba2a1258f4 -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=f0e13e1700a1cbc1489c0a5728ce6c0f5ba1432a75ca2c0c0573b9fcf130ae9b -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=825550e3a2afbe15130dcf7b702ea62b3b90f8a1e0b850cd6e9a5b5dd180e72d -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.gz=f77a6c24301c5c7165de3bf51b5b6d45e7d37a82d00446d1abbe5a5c591ca616 -dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.xz=5a9507e0c06b252196203b01319355e4d246eddead60993262bd680b6a1d2315 -dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.gz=eca36ae4253e5f1b51c065631a650135b71797b452a7fbf6dfa17c49a01f71d9 -dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.xz=1da17cca8397bedda8b5403ddcc9f7686d7ad207daa7389a6cf80f922bac8140 -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a4eea434371a7d95b473410a42d8409995119c85954f94a75b8b0a69aa3095b -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=cea3d7d9568d2ed86ab11d28f5a02cf36210971b798c4d61e133357c24108f6f -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=355fa0988a68a1a331a2794a573cd065e6fbbe8b312e187dfff59f4f4245cc5f -dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=c93347602b0133e0da072243ba9419c95179f9f548b6284612967d7b80a42144 -dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c4305667ed2a77764c729fe236491b239cea7c2605039c2bc28a926d21f343cc -dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=02b6b621a1b3b91e25482400680cd38be806d7de541cf364d0ed181a92fdcbf5 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=830e1b90ea156eee05b0c5fab514d82558e2473eb5f6bddfeafa51e7417315c2 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c5910437177f607439a6b18bd05b93c3965f915a0d372fb540deecf044b21880 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=7a0f343b5fa50168a3edd0770dee148c82e43e7b2b82e2149ca22badeade3218 -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=dc4d7b3cb830451044726e72b848e529e92ec0330e610f06b07f8ed37415c3cd -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=8a9e341e6f208d5036e4c774f68b75802c64c53c4a9381ffd5a62e9b3c486cdd -dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fd24b56cc9891d9a1246e62eb33f6de8385acb265ca875af79f2593ff4bd323d -dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.gz=51a58a9f663de787ca58da8e4ed705a1099bfeca945eaab3bbce01edd45aff4b -dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.xz=47fcf0fcdabaddde929e4828c1de1db3986af1d32a752c057ec69aee9c8f6162 -dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=207281137a1b6ec8c1df21c581c23a6db7bfdd11c550749203bbe24b9ae80019 -dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=217625e68479d09d8e63f931983e030ea9f0829cdd559ba88bf657e711c96aa6 -dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.gz=4c5fa8fc4e18723c4522a1e93e9e343e35f02e74fc82e6fc44951bf7e1849371 -dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.xz=f4440f97ebab6a79d50683169994cef569a427cb1811b85ee196432d4e2d0b38 -dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.gz=ab7dfa2b8aff6bb7514798d11970e4c09c8a4844d7408e295c547f1a87c23ea0 -dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.xz=fb9ce70893a8c89bc3e66dd6ded2e0c4813c96bd0781b6c3b420a278c53ba4cd -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4650f832189a221337fc172c2ffa113ff209774949ae12e7ef159117a02e984e -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=f6bb5528b914311802fdb9816260e8a57531fedc5f68bef2dc6ba83d59d5ce4c -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2fff203abd959498321680582bb969de89c9de4718b38e06cc91a789d7fd415e -dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=df5cadfd5895ee1552bbcfebc40b34826481932bdde309ecb2c13f55541ca2c0 -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e29900d97e62c7568395191e1230fa6f98f971c1593303810f05d4db5c68592e -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=4455ff5a1de11281aca0df4f3f6d33d245314ce4276bda9d161bf850eda24ad6 -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=26fcafd19aee4fcba45875d0f35aeceed7cb0a0fa070e6a2447b3d9b86170c8a -dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=cc43780fa58e7fa1d23a3b5e2695dfd3f4ac3c02398756516c395f4546e2042d -dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a67a25cdaa3fabdd2b619434e3b98f05acc13f25cc7ebf8f936e7f3d1761e272 -dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=e8ee762127e02a73614e636b77d34d927f34e967cadd79158ca6ea27687c679a -dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.gz=7343489518ad6d354f9bfcbbc884d1c0e4fc88c4650cc68d9b9b84ee12b750b2 -dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.xz=eef35d9c016fdb67b9825104558ca0fc1aec3af8a738636a0f24797ad270b8e6 -dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.gz=ed36702bbf1d45c263b8b52a06f2b4a9783c6ec78db28e00d317acd09a549977 -dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.xz=e4fbf4007af9858e1bebffef6bdb4c66f419b035c8fb385dc70d46ce2e312e2e -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=1eebca6a4ed9b04a1cd3fc57f8f75bda14cc03c8909385586c8a084e46aa96fd -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=0bf68ccaa22a4782f23a34b8a52ca250b183e265f12bffde7cda9ddac515040c -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=6f7b932bb0176fefbcc1de700a36da7c60dac609ec91e6bf351e4c42ea6fb119 -dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a0d9397caf812fa479da6b389b653fcff451f8d54fa0545e5c908e73391b6dee -dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.gz=5be2ca5bd0340fa2e7ffe435081d1848ab883e46a9c0f07eee69f7dd9d08e0f6 -dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.xz=ed563b78d4201ce29ba79cf6ebf5a3b7d8020611309e39b8790c59edcdd05b29 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=53f7928406a1a14dfc6774fb2704bfa9c68091b135b750c5e46e3610e00e8c72 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d71cf98a8b6dfa2cc1682819d1bc5bbfe0eae819f63bb91d64e4f52bbee4158f -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f65eccc2a47e34d96faa94954c738813d9b5acae351936b07df6ee2ee8592296 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=4f44230338a6b6bc17a8a2a80125ba18a9dedb6f9347c6e93b7f7b88c87e4468 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=80eae216bc5c3f77817d244f0d81cc13704894c1c7bde30c89b4f58b6049767f -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=b8036aee8615786593f83c3e7808eac2a59ad44ae9f5959b9719fd475b3197b0 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=95ca16bf6931261a62f4a3637495c02450d34fd0a0ee8abe350881b9aa0bc773 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=df92b9f5ec3ea09c2cc48e4c91d41ecb1fa82db87180458b1e051bbceeb4efc2 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=26a4426464874411bf51cf0148569c9a110681632d228dc9c9d57fbe24292e93 -dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=70ee4948185aec3b556c963ba030abbb6424e09190e31afb11d063bc2ba21664 -dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.gz=50c5b3d721cb5d83ab5f277c24eecbdbde32bdbc208bc0597830329fd19bf786 -dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.xz=9add40fc1a971f135796a8020e3ecbc6ccfa657714cee2535866f2af38fcde97 -dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.gz=d9e4695576a9f34e67804a636de6164fa7d381ac2193095cd2daa74fe148b748 -dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.xz=6592a61388b53c3d3040245b8634715026f1e2a020a118edaf43f98839537aa3 -dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.gz=da24db2c8642e8273ef7d0e74fd32a1045ec99f5201b35d0116ba1818ab330d3 -dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.xz=75574d203e5e15973ce1e6e12a43d6b26825844382ef76b05c4dd568912fd16b -dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.gz=2e4bab4042bac836ac40e07c36c6057273d6bffaf97b1b22a64cd0876d48895d -dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.xz=f335988ba2ae2853c4c8928562fa6ed81a2bbd2bd5d09dbcebd7e64cbc7d458e -dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e96921c51d49ae28871286147d589bb59eec596826d1e0eeddd928f57ed4499f -dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.xz=c17d7cbbc6bb30899a1a94f74f380bb54878b927ebe58b31592f7adb64d7b5fb -dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.gz=f9030f5b2ae0411349f1f4fabd00efa3e1117ca5dc5ba60fe87f33f94e51787b -dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.xz=d45b9c7c6f8de53f99b550a6d673bf8ff29e507c60ef63271d7d5ac73c765e07 -dist/2024-10-16/rust-std-beta-i686-linux-android.tar.gz=2a6b9c893d2d8bbdb5900c4105fe54a988101c7d69f504e4d2983ba7aaadbbd4 -dist/2024-10-16/rust-std-beta-i686-linux-android.tar.xz=94c884a0cd03fe092bdfb6fe718fd335921a82c9c2887e0e68a13fe6a183a877 -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.gz=2d4a8b299987ab046536db276f3c4ea97413be5915189b9af085e4a4ba7b28ab -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.xz=eb60bf4d73fa45fe61730427287585939ff1a14efa8910877546818167b343cc -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=ec0f11f5cce47e6ad288393dafaa69b27fc5207194e886f0a00b4e6c3a006164 -dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=10a5c127538bc9b951c62692ca4d626cd669919d5bb2236ef6112da28db028a5 -dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.gz=7c9afcae592f5494ffd2baa95947b4fa5483c795e516852b463170e4797984cc -dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.xz=ad9381999c1846c188d7264992c79faf413d675fdd70f22f25afcf84ed6e3b22 -dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.gz=9b4ea3de244aaf14b6759807444bb983ec5732b119faad1c9437eb2c02d407ed -dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.xz=88f975eff5146af6ae548e2d7be8d402ca3d6f470b6760b75e27dedcac9f70fb -dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.gz=8a8a255695d36a86ab32abe9f37f9f6f3e9b75eee75953486d82f186d8342180 -dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.xz=00a55b220767f3b692286bea728208bf665ea9a54869f82b31805b40ff56f763 -dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.gz=96e838064bfdace0fcd5596c50714585a221a5116e2825aba448cc1f188d0edf -dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.xz=78c5be28afda04d536a634a049c175b38d46309eb4b02126ba2cda3102b92d45 -dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.gz=41a11092091b1f3b508f606978c0ac026e94614fe4b2207522b4f5f3d6c3262b -dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.xz=a2250a5bb179549426ead55edaf3eba7626ee57a5e2c578057c3166348a47523 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=782998317c6c9cca107e84538ee166a37490b287efb437e5da9bf799178084b1 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=75b15b6d6db6f801a74419aa294b9537aa6e92b4d9d4c482e66aa6e319accee5 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=003a9949067435194f6a9bc6ea742876d5894ade67b5831c111826aa8ba5c2d5 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=5f1a4b6acfc1c82049c13ee2553ac20df016062feb368a54e44aead601105987 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.gz=f5e851d27f7017832de64c134727b7cd045495ed93fece21101c1e32b4c4c5e2 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.xz=289a56a0ee6087fbebed28a8d2110961c08889724d1a776a41094d5589cd112d -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=86cc3aa69dd4b18fc8435b6f6c1c73a24dc0b031cd79f942f6bc20a11f093f67 -dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e29c510424862fbd96cf61e89b6f9d64cef3c0274dea125f4af2c2a84816f5d -dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=7506febb3ffaf1e763084d06a8dc9da096155c6a609a5c4c26feb993688f45f4 -dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=9c7e50509abfe5f0faa41eb526effa915e0799f59e5404e5a667c5f674a1ed18 -dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=6070daa8b4fc8bfb6c392767ac669a80067520c0fa85c923cb435c03a5ba6b9b -dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=32e4064ed11bc521f26e222897ca651704e41bd42df214eb618b6fffcb909b56 -dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=51a092e812baf52f5eb7100e433fc1d5ac7cd984f8062b7d960711b9b88f1431 -dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=444bcbf145d1aff19d8e2474191ee4ff0be738c7c3b1ded12e1a9bb35d700c2f -dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=9a4968669cb034ebdd0623f57f86a674df513abf6c01cbffce0d104447f0aacf -dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=11e478ed0cf115eaed256e9f0f64ab9f879ea0fb26b2f520a6388d3efe705422 -dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0476e97436699b50ce459b3c38b55425b81864162639997bc14bce33fd7ea429 -dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=f76163c6963a7f1e29cc6a348b68e3c0659b739383273029eefac4d292280a3f -dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f922ff15e927c047bed29d64534218d392bb584e12abdba09d9d9243613de3b4 -dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=0131845949fe27479123189bca11f2ff13aa14e0349c0901407cf65723271fad -dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=a7898b83bf49203172e6191cc720b6b184aca6cdbe44386278fab0e6c8ca4bca -dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d5a4a03dfa52f732af211ae3ed3220fd76c5a2a6babada0bf94de3817e71cca9 -dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=c074043d065a85860d2f99b657035b87a1ee7fdcea53c557035a8da6fbba96ad -dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9a02c6c4c5cf7c57942a89da30869d7bbe2b0f5bf7374b7dec868bb5f84e00f6 -dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=1c016db6ffad0ecc552025777b2d2df5a54d6ec3a215eb2b4af0f1ccc6e45f14 -dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=399d56e3525aeb354a0c9250f070a43a7426e185960db6d8b57484f47ad11a4d -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=64f01a83583f4d025c95b3b2c09b86c4bae123c72a66a6a0995994d4226d34fa -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=794cb971242dedc2926a6b56badeffd1b4aa4f1753a22a1228eda8f336c2a5c5 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=1eaa20562af0921066ae04c8e1d9191ecfc4f9816a721ad2797c47b58a343084 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=423b35248c797ea494e6462b4a9c16e49649f0105b06b16c6137799a82f0a401 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=38a31b095b74cb4b678ecd797ed768f4f9f967a201b79f21b059ef8a39fbd4f9 -dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=d7a53419a2f604102bda0d0b8ee9aba790082ccb0d63c31ff28be15f37ee87d6 -dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=0cbccec64f57ca0951fe678299cf17a7aec8bb2a8d71aa7fea1a26cd720b38ca -dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=aed7bcbb60aa5444ed8a8e1ccc7b74cc978b7e1646eb618a1899ebe61adf2c34 -dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0cd68dad85a5cc084d8a0cddc275cd5e932e50cea18d3d622d03ecca068008e4 -dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=0873ae093594ae2d93f19003ded34d1d6d4884757e0a5a790d4766be4bd7622a -dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=ae70c9e9edd7d83776cdd0013e081d3b16dadb2a2504037b245acc82f104112f -dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=810c1346632064535769e8fb15ac207de45f06700e8cc9875b3971c44725a3df -dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.gz=0538ccf4739439c52d6c7d99b573e7d8163a834a6163720829816d291e067217 -dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.xz=8064bfdddb99ba6ff202ab92e3492bd2191ea11387b930a35fcde5ac7e341c29 -dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.gz=a988938091594f39015783e78a334d72d41f5a3646a3da09fe7a7a0db7ec2662 -dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.xz=0dbf287df801225c52d4dcbfd7afdfd5c1bb8410d9342885c092a4982a0d038b -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.gz=d5b46640810193ee163ef6cf3bb8d506b6844104c3d00c033d436d79ee790dcf -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.xz=f4e7ee83d5392e2496b9d3fc1e42b45d73be3b67e723a2e62f931c11a61480af -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.gz=0fa0ba0ca7c4e73f8b9ff2800919484cad7d902cc5e704e5aa3adb742cf6a6a0 -dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.xz=ce3f3f3bc51cf79449df550b8c3fbcac588444b3234f379b93076034be6a40e7 -dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b2aee46d16f38cf43cdd3f3fab78df181bab6438cb012c2caa56fa097ad1402 -dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.xz=3ee398b8497b7920f5d3cb18be2334ce440ec61b11e80c3ffb9eb1d898be45cc -dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=26a67116e52dc1fcf179dd226fc28e3e21f2d2b482330d254b5882502573ee6b -dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d051ae1bc98060db4a2ca7fa3c3dfc6c3107632631edac41d553e4b192ccc2d3 -dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=dc34a8335b1a9dc077e38b4e4a8222d84340de604a6af547fa17bb142cd0c4da -dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=2d5c375d09bcaad6f983d4c4e0762532feb1d3706beacbf3a8d2e4fd75bf0c71 -dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=30c73a59d9138a542337fbb2be848a152172be272a25a1ad9a28f37510e35e94 -dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=467775974be97da92015790d49cb4f89d967ed1fd7846456b4b30e20f9585501 -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=06db2989a00b1913822cec211225b0d37143dfe1e62d394c18c04954f7396ac0 -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=65de9bf3cfc8ac6910953b2d3b2e9de532220f692519875e7da50a6493500fe5 -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=26a6aec0f92b238c4d75c9eda3ecbb8bf0f1628ea5bdf52941e7b5ca398ec03a -dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=7a4b72ba1d507f418b30d7a110eb5e9025872e2398f0aa68abbef150f4c49ef1 -dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.gz=cf04dc8f1df723dbca4fa3a1155dc3bced6b3c96588bf41f6bcc196b74ae19cf -dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4fd17a62d10d27c13818cc3dbe1c62aa85d9c7123b88310d12cc40939010ec97 -dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.gz=64ddae5e3e08ede16960f50595c4205de9962e0f5b8de9de5df1e9a8946bf66a -dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.xz=0d6449807c02e1ef817fa2d378e77d9becd3a1560192bc9fdfad84cdee5cc8b3 -dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.gz=c4ba753891162f604effac480ded4c536f294e39768f41d7b4fea1ab28c71be3 -dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.xz=46a6f680f19ee2ddeb41e7aa13bb91a893ae27ae89ec41c36094f6e4db4a3e0d -dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.gz=3f89ca539044a79abd2b25f12d08ae954a7fcdcdf0288239c57d241b225776f9 -dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.xz=18a922eb41f5c907bfb624d18ca882dfd569f6775105dcdc29e7c7eb49187859 -dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.gz=6dec5910a96e7a8e0713c109c993df44094e03fc8ac90b1a99f72dfdf84798f7 -dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.xz=00e21ba70b0ee2760dcd51bf68f6be74c5cf38fc301476f406bf1f1d21ae7503 -dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.gz=c0b620ffb0debcd0f20155b1be250627450f14b4f62b32d9d9e4ee4c4e57cca7 -dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.xz=4d14c5de2f92b67c99e6fd2342d4ee968805d9eb68d4f9d1f549bb27e866f3b0 -dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.gz=b3ffba3cdef26174462e65847414458eba1c6aea63a78f6087497a04b427295b -dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.xz=1923ee9008ca30677642d1e66463555ba6fcee88dc0ed947e0ece7e4ce4efdd4 -dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.gz=e8f1cd196c5e3b10a58f640cc8bdf3d015e1b23d49724112aaa7e4019cf01107 -dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.xz=5fec3b22adc67fc6e4ef2cb873d446cb1520cfcee2ef4248e3dcc2816ada683e -dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=852e5067d47ac896c18e424cedcb984b0b4724b7fcd05e550151de2781603737 -dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=2333f02b870c6e7b673f5e8e166bf9166c3f6d1586daafa4eeb626d8de5b305e -dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=5c2bfde266aefa83ef9e65448900f4aa73e1d91de3719ada2512230a69090e2c -dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=218f4a4861812e38992bf261e390e95fbe67402f89827e6ac1b68fa42c705166 -dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.gz=5cd9859a22f77dffae58fb6573a8f5e23dc75bf030f54c152714777e5a01eef3 -dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.xz=be754bee393794ac427718b687f5e4aaf61aa1544795ed0da0b9d20e77e45803 -dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.gz=556f48c0ee8276bc847f3519dc0dfb72bd11cf27add709815da47f5cbb48716d -dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.xz=aa185610d66b606913d1102f62b62c5bbf9c5baf2e091d14d37c30b1526fb583 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=1a7dd15c91fb1597593b27dc0b72bc0b1a6e758935efae3c9db714cd624d7639 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=be18c0a1f2d0a1852c81ac1619a01d04d0c8c22472655710f643d86cb559508d -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=e18f210cfe890af8285da5f99cc476770daa78cddb7f8213f7f26f66111e17ef -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=b207877400dbfad09b6a3c2917516b63faa159f922ad03911736634ff46898d1 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6f277d2e2e9a9057e2a2c8045c3949ab36ee8ed58b64829b10470e0c6b111671 -dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=51a102726ddf492dbc530437047fcb4d5e542dc4ace0e64da21c7ec79ebc001c -dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.gz=eeb6a46dd78fe3b477454c256ba8486b906e7a7ed044e686bd4f8c868265bd90 -dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.xz=67e103b9742ebf2798fe8e2647a6755a1d253301fea13a5193ced5bc394b9a0c -dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b42fcd18458cff0ffa0902a0797e9b42cdf9475f5e84279972e4010608a14ba3 -dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=878e3950e0aefbd5c5c155f1ba2a4e8abebab10e3e77311403fc2c475e6da9df -dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.gz=d72be5ca5fde3ac33da483058b8132707c93647652245864c988158e6dd70ca1 -dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.xz=270959bb47366b7276717b677c5303ba0d579c9fd1f98fcf3774ce033caf0015 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=33370d376f3ecd80ddb5f614eef222c601e2df5dd18ae98ec034922790f56218 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=061a262fe98e6e1b41df6f9f60367259d44215f528938574098ede8698985c94 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=70328a15c8e29be07f248bb073336f06eba613c377ea4e98a1e0a4abe5e2eb6e -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=ac389ebe5ca69cb382fd104161c9068bd8aa4d28960d578f2d925faafffb61da -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=22d350bc0718b999d88e715cba73ef1860e1b1b8efac026f46d9050952d739b3 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=0761b9cb94210ee40fd0dbde38cd049a9e727a73da4ebc2cf10e5db92e6860de -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=35f975847adac17d19abba5385b951ce2015dd8b62ce4b0a716ac612808cc9d7 -dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=5a9679805c1bdfa835aee94ed0d3ed4d2b4d0b6a8e2ec4471fcbcefd331cb200 -dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.gz=e4269be360d9823bccf6f7d71e4f51feeb8e955c7851d5bb6527055d709b68b7 -dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.xz=58880cc63fb93bbbb78fa4268eb69b37464b429de2f007abf05f5fd7c53aec8a -dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.gz=42c77c14c433f43a092bef5ea0cfa60aea747301a9499c66bdd81d7998a74143 -dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.xz=0cdfb3cf58d8f6db3bd65f4848aec8a431ffb4e1a5f79e56ceafe09849a96ac3 -dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.gz=35ba471138c115ac3e1ac3560fe8590038cb6002d22a45dd92f09a868270d223 -dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.xz=f250b60b52e2f84864406a0ef7e2f8896e1373f4f14f555a47a2019fd370f553 -dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.gz=7332cbab92c48611604eb13ac025b845fd0dc0bfe838a4edb02f8266a5245aeb -dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.xz=7cbef4955ee702d845116c59742194b1019d67f564145cf809ecec67245ca8af -dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.gz=59321dd2f962c7b14514fdf1ec96907c16735a03a799479055f40f17883b8b6e -dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.xz=336c7dff9f3a1d9de819a32f62eb518dd94d45ee591afb01d329127a2146c3fb -dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.gz=00c53e3a327909882282a32850c82e4aa18508a5e355532951d380e985b75c79 -dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.xz=39d09b49740b0512a84fd5351d473c5802de30721f621cf99ccd0178d8eebd60 -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=dcb522627c49811d2e6eb133725e301089a4942da1347721ea28f2cdd670685a -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b9ce402bb130d35e482ee360f8f142726ff51bac3954aeed14800eef0bd96f6d -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.gz=670c0b78cd5c985e6bacb2bb2cc3a5a2478c2623992c4cc35d0d4c624e1b4b16 -dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.xz=8a936c0c457a1d5c659611e7a69fe9934313d9ceea04c0a0eb393e28544ce7b1 -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=10150caa2130a73443942f1dde7c849172b57b7b9e07e8939cd6c126c701d7d7 -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4dc0ffb898e66661a1b9844b965a0b0ca115bd6d9bb25fd5c5df022fdbeb56bf -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6db24d0a3eb7de6e3d40dceccf6a92ed86e170e0c4dd2ebc9702652655ad664b -dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=c5699a6a4ad49c34a77c94a4982b1a0ea7f6dea84d2771c24fdc05dfe9d4cdb4 -dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=f5621b39e7608e8461b559f3c3e57969e7eadce82798b395ba41e6302b2e0283 -dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=d7f62c0ac375f56d9ebbd0edbfaee4684d7d47ed8ad38bf7d25fb75a5770bdb1 -dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.gz=b895fa9240c3a6c089cde6b08a21408b5a6f38818c4a9cf25394b17e9610da96 -dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.xz=e26de92566339b932cdf4a4ee90464f1f3863d89534c03a3c9f9a632a278993d -dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.gz=ba64512c0732f5821ac4d1eb7fb53c0f340847c0cbc7dd5f88f67e03bc3f58ee -dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.xz=cf9872ad8ce5621faf517c2796620f24c1a99bccff7f328b7e7650e89e604b22 -dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.gz=23496080baad6b976f8680b7f6c856461a410a4dce5c66a41cfa220d9479cd95 -dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.xz=9799594bddbe1e04e1d625a6ead04efdd4749d4f0773585d21ba2be6636f0bee -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=5a1b95969f002c25717751337951aed39e6f6256ee58acce150d5ffaf0046300 -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=36bab05ec8b39c7e230ed78f64b2680ea21fa9f7997c980c22edde61c0799b5a -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=19bfbd70b98c0bbbf29a0a796572d1661b8902132087173ca0e6aaadb4d51d09 -dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=629e42e188447a392bfc7cef5fe04c31380ee30523dc0bc33b0f3c02bd2fd82c -dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=5d8b1daa253ebe0750e6f073b8367b053de09b4f209327d4114bfa60b2bb5602 -dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=545d7ad3b7b0b5d2ec0b4bb70b7e31dd823048d6087d6c3fa2139f307ea35fbb -dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2111cbc7586a1e58dc7e6e54a63157f9606f5586c7bb72ffa15f1a94284d4c97 -dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=0d6702d3ec5a6aa9dfb06d565e4e16b27cd3d445871bf2344c876d7ffe2f8a32 -dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0f750831b518b452a2ac17c9bab3a02f30f58bba6ffcd962eed06012102c7b31 -dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6d476e16109e9bc5dd055c537a9382ce154d2837a32bc2c165a1aec76ba1ba43 -dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=850bbca95670afa1262b5d46bb02f0bb367c83f851bc2a9817f8bf2eda9bd2ef -dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f42b3b5cb506886bcfc92c0a7f3dd3d0668bdda0f2db657b98becb4c0e99bfd1 -dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f3a8541b3e6c12f350fcfbf43a8efb2a8bb48a62e055d9dc522d568b94476f43 -dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.xz=12c5411791c715562c99dd211095c9924142053d510e17e6ec50b7b8b927eda1 -dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.gz=95885bfcf5fc1de80d0f9b5415dd261136d5577b7d61716c184a6c6379acca21 -dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.xz=881c9d88bf2a848f5b5cd61d18068e2dda3542a65e93ab373e3a047cc30369d2 -dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.gz=c04ca1768c5925d5c7e19d5f232adbda355469974b19a2a130a6967db94b56c3 -dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc02593e98f5393ce2032fb605ec2bc053a1a19311a5a80d27c3a552ec8b968b -dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8ffb930c33ad454806f2f61a10949a3fa5b92b9313454927dbd76928955ed7f2 -dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.xz=ef0bbe8512b3dc9bdc9f3a47abf2834bcde1fd7f59e319f7c7040b7100ba1f8a -dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.gz=eb21f7739dbd7c120dc9552360e8aa6e1e0eee14d80ea16e3dcecb9e94efe7c0 -dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.xz=9e287f3d0c7e402dbc121cd737fd2360dfcd97fa886770aae93c07474494bb77 -dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.gz=1cb86b6953ec99e95d92d61ead263021d16921cfe6152b6331efb838c46be85c -dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.xz=c356e671ca97dcb4d945567e33f06911d5269fdebc19fe83a9313f574d446576 -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=7613e679837e2769b9e8df5b8785fdb7e51665379e64547bae9d6015eb8e45c0 -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=39ae7207f84ee3da16ee11271070e8b82d2991cde29771d5154bb2957d9beccc -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4dfaa69f4377bb724eb7d1990aea7ac219a960b690601769f8e06b72f59f86b4 -dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.xz=4cf72f3f0048e8cfb2b05566cbc1d76e9730cf1f71f9d0f3a71bd9379f30b08c -dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.gz=e1d3ff748dcf1777bc2d999ec82f0b8a67295f91a9cb07a9c1123cd5424928c3 -dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.xz=7e21e89e218118d536d489d16e77e667df7ba7c809135ba179e7097a2243df5d -dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.gz=244ed83cac923e00647cdd3aab9d0479cf420991e9e06eee5ffd8acc9e5a199e -dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.xz=6dd93a671fca0efb2d3b8cc461aba66483624327a382fd714a526832034c8438 -dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.gz=56710fa9c7d46fb881903e08e407c258e3ffc75ce3de0226dcdc3709dc59180e -dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.xz=6ee782709786c310fb1e887cc576e7e61b0a4b120f6a46c7dea1e2f2bf7dad1d -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=06f0ee2195349921d1ae791fa1628fceaa7adb377968fa09dbe17aa77c762a47 -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=6e792e91db8b54e0cfb9eaed8187b5202ac5d5735ed0f73080a6a73bf15ce683 -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.gz=bde52962b121472cd1b755c506b9362ff88ec582cb3fe9d307948c51f4d96f1c -dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.xz=70a06d5b8175d078bd246adf45f3058d362f0b128f1dc11d3797840b28692bf5 -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=ab8b54d8436dbc6af279a048d2b75eea9eabfa369f23c51fc1c47388f642a755 -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a2715009144defc9aea3ff0d6a15485d8feedd37b333658470d479600fe87ffd -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=a1863b47208051a231f9571bdac3628d8afdfca7eac3b1cb7a04a843c176ae80 -dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=a5926e8e3e2867a8fa87db77dc26bd18734f84a4a685374dda07d50d21068f62 -dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=f70eabd386aac93c676485bd42845e62b34c034b8710bf0db24a440c03b15bce -dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=cfde41ebe7398d0858bf507b9322c5f4959becd5a3a4624027b4bf3321730a29 -dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.gz=3d988126d6a0ed9133b73b8aea3b16d6355db8ad83254a7499f7dc3b414d62f8 -dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.xz=6efe88aab2daa0c7df17bbb449c2b815e085ca7e859b17bb578978d18ca2ea04 -dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.gz=2c2eb32ebe3ec89a985c07ce87cc1dbc627f5f8588aeac72fd381c6e19034095 -dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.xz=fe2d2ae70e0ce102794450d4259b706d3bda2c5b05bd21a863b2ecd8ed54274b -dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.gz=0d633381b174f04523f13cc574e79af5041a231aa61b0befc406c7e3ccb0ebf3 -dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.xz=029558aecdd4862dc74ce9726a462f1d34a7e2a6eda5bf791995dfd6933096e7 -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=2bdaa7f730f30db62ed0661f135227c54249786a78a8022428ead03766c9e29b -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=2a4f5982eac9cb5e8372d35c13a7832d532a31e5c38d13b0643d16832e1e341e -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a9a1fc5b74e19a567c45ce1789c7bfd50b28774bca8320886108e4a18a1d7765 -dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9e957652f80b2de14c5a8f5faaa5662d0ebd26e18b2bc5d248587d72413e483b -dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=a9fa9caea0f784ed096b3ff204a8261126102e05456c52d544c7036f9ee30c41 -dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=0e3d3472e3e73b02aca8797ecaa2471e472d361b0c44126e4bfc2d25a8fad96c -dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=211c52eed69942aed1e6b1fb4799232ea4fd3f898a44a4bb6343336e89dfec74 -dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=8c07b34223e465e17094b7e20efdbf8ec6ef5aa042485d3cfbc6ef58dbca0be9 -dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=b3fc3cc6e81ef118eada3c01fc3535dfc622b92377d8e735f80d7661b4b847fb -dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e885c534589fac79046bb31b92aefe7674dee13c8df1a456e91ca63e9d92c6d5 -dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=fcfbf29d105ade4a6d7537dc44d01c6de2de70d066afd8ac3af58bf3bcb6f7d0 -dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a5425df8cd724fd992de26434090e157e9d148d063161bfb43789d6b4234ad02 -dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ab96fc1c538a9a526124bc2cf3e97edd655f29f8d6d310b3b5f017cfbe6311e3 -dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.xz=096de4e9f80f40a294dfd1ba32e9de038c3449b2760189a5c9e46cf8e36dc0d6 -dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.gz=5614651ef2acd5ce1d43cc2504d353e471d9c8c425c16e3649f81e1cef44b86f -dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.xz=26e39442af2251c52bcd275c7ae25a88211ec2f582bbe7a29724f816768c9781 -dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.gz=b2626513cbcd9b1456dce8543c2b11458eb052434f9ca84a6e926a77e5be2362 -dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.xz=87403c11e1b92bbbc2651183b2b480c41d9c7e0fa6f08551702c6ab308fbbf5e -dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.gz=929029e67d34bc813061c524490b8f0030d31097fc1fd439acd4d8c3545589a1 -dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1584df60f086c6af01f06023236f612bf59be9d5b991bd09ed66f4c505737533 -dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.gz=d5ee8cfefbf164d33529f1a777437f49216e93173a2ac04b605e74fea89fc6a3 -dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.xz=9469aead14fc03ebe984e51bbee0db6d1cd8e877b67ca361c44939e2464a95fe -dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.gz=79bd918b2a391cbeb885b7075b1e0534054c81784c332a2aa8539d0e1cd15f69 -dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.xz=16b808026a4fdfaa85a4ac01b01b4fc79c4824a651bd4e412e4ee9b0011eca4c -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=62224af7a1831140fc3f06e7e918191e9443751549ec5c96afdcb3ffb5b18e06 -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=78bab115fa696fc95d911655575032fc9af324c8b6df136044f11681239e5c41 -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.gz=1a76ea2b1596acd396585d78d01be5d3b795641d7b20f84379cd2c344e7536e9 -dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.xz=63ac980b41b0a3b744d94727af6ee1679b8bc4c50db4ef68402d0253b1852ffb -dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.gz=eba61354aecfea64815a68b569122e029501d85876d37f5ea4119f36f932e146 -dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.xz=37f9395e78a2bf2977b38929b9511e9668f26e23705d025609f028b282aeaee2 -dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.gz=05cc308cd0c35063b43a45dab3e84001e2d580b10431c74899a86cd8971e5b36 -dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.xz=aede50889786bc1e902162b9347cf59ee67b15e902b0ed78d7187d3c24a7c4a0 -dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=1c25ee283dbc720b471d435ed952e6d794ecacafd4c889a2ad8d43725cba8ded -dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=67602978481a53b0b4681523d94bf79ad731a369cc088c3b0adf8e7d54b1fbce -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ed7c9c38071f9d1e632104ff1d9a9407efec99d74eabd127db795c56e84b9d73 -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=65ee60bfefa1334cece9f5da72789d90b4b5918e7afea2b47aa4d1450d9a1237 -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=e92d5ddf80c94bdc34697bec4d7a1b1ea677e5fc6c68c41059a7829e53e95505 -dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2f1737178817318d1543deabd865aa83a1f395a36cc83e3717157b4dad827f22 -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=a4be0eb92a011ed940db67973d5fb62c4b5d3fdd52a08981223c5fa5278826b5 -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=a47b2dab4f20f53e6c29fbce06383144a67ece61a63f33c3fb86beaabfe4bce5 -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=7bfef0a8b7cb4a905ad145311c320a8ccb2048e806ef68688a1423009770b35a -dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=d944161b92bdd74f3ba533b94b67a3a361a01b82fa5c156710608f00c46913ec -dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=46a46ad32e2829550e301a84212f057faf21bf67ff6862f77f11cb0e13f80453 -dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d917336a949ad5a5f0fcfe1ef261d87d4dcbde22b467258543c50715a9041d64 -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=38a9cd401774ff1d832e536ed0aca9a3f0d5593814bd6db9ba4f8341a5545fd3 -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=fa2194663d11d517bbd67c157fc40cf67149246c391e9b8adf0a46c2eb96c860 -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c5271c244d8055401d3d3a97873064b93915dbcc52108cb9b61381af1ebe99ad -dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=56c6a0cedf3ec4667d65a209477cfe0d395e534654b49e28efbd3836e8a0dae7 -dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c4325b80bfc63dc58c4632ede188efdc94aa4cad49abfa4e57d81faad673a35c -dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=35b4fba91cad3bf9e627d59baf1f1864e30d002b05696c61498e73fd0e0f299f -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=b2f856cc81be2c6f2c4250ec88cbab0a51c3d59e73fefd66cae9b1a91a32b0bb -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=1b1a40377a8a13b74f62f5bb382cb8056930c543b97261d32613c53826c758da -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=98b1f0fc4f45eae47a6cae7e7d4d9734979d8f860c7c96da281fa1d9ed3ca39f -dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=bae7dbd1342d5aa89c335f1dcdac0d93f5cd8198ce9f869ef4c32dba8bc6c0d7 -dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=cb5dc166002aba8a95f7e10d2d9e93a66d51483540c7e733b528bfccdbc74d9f -dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=c070a48d0aad7ce42cfe5eba9477a0f54a9e04c9ec5c770e91bd2db55d0d764a -dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=424c0d9a047ac228cfed286d0a2936b857e1c575ddebd931ca634e0501c125da -dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=b067b3d095a5b53191ff148d0e89baed0b53c2099142d885961220548b904c52 -dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=01acab58a327ee34d100e67a4a40a9efb66a64d478d6bcaaf94ce35874296c42 -dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c1a715f7502ef54a236d4ebe15488ec4c1c5cc5b1c50eea416a5b9c57de66f53 -dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=cb014573a52f2d6776e47f3f728ae1e8b05feac2274c5916b1545675e658fc15 -dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=5abf6bf36bcb57c0492e9bb4953ef78a61acf347d20ab788b4b31da44ae3bd39 -dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=0bee2c4ea3f8ba07c189f7e2e0df1b2627b7bb638823fde2839d46a353e0480a -dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=df352612d69dff13b59da185581a48062e54ee07161b1fe205b92d0687a4e896 -dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b7b44f5fb37fac58a83c2220a68c251513fcca96c51a71b189152a78cf095cf9 -dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.xz=f5876f1d8181880e4ecb71eaa2477b0431dd0bbb45e6a4da8f20bc31426cb43d -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=cae33e30d7b2e5589a6fe681345f6edbf406aa803d0d521ea182a575ee32dca2 -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=21324d7c6949bd12c841db8904d9485dd709f8c324e7aea31f2a9eb2a32844c0 -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=cfccffb90721492cc79212ba49dd88361c6d38eab24ca4fbfd8110c2eefea001 -dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=05c528e683c40467ed3911ec5f852914e117fd71e8a0826f17d91295d4f1b047 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=97cd5e773bfebd3e1d78dc3d486a75b969e30f1dd0311d07c337440d275d0443 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=19989c6e9ce4d67e068d449b92dfedd8e07bd1a287cee0410f43aa43432346f9 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=c3d8ed4650b4f7902a8643bfee849926892aea2e664400b858f61000966042cd -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=6b0dce2bb77036d154d15ffb2495480ed8c8cc441dc8979b4fd767af80e0736d -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=de7b427a783d588a778a2301a1bf8e4fec076ede2006e275f45d82a87e965feb -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=43fdb72c7e74c86eedbb01631ec357c2cf469512c0c591d15f35f747bcfbbd30 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=3fccaaf7106f47302eb3c489dd722a91727e25351278a17f81d06fbb4cd4041d -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=988d6c342a4561790d1024455be643e17525ae07e02fe5238fc61d00c91d3cd6 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=71c10377a84b3bd612a83cd2822bc6c0eb4a540c681114d63be368da84ef3766 -dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=1e6a3c7080334663ef6fe246eae3482a05446b83c8a0c659084ca8186b9cab01 -dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.gz=e68c96b5d6fc204944cd1bfd80e2c6a8332dedede98a968e170fa657e012ec1f -dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.xz=9f7138fecf991a17483e0359c7a5a0b4292cffeafdd4b52b7c1021cbf993ec5c -dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0f31c36e6b6b765e9814dd193861e2ae2a176160f22aaff6211a6da3efbc1fd0 -dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ab4cbc70a6002bdba2955fbbdd99f03d3e54d14d32bd2f7250be6a323f39dfd9 -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=e088594f42b88494401df68cc60b8d94a4c1199e3549aa6dffd513b0c5f7508a -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=a204d11814dfb6a3283ed84abf8b88492283eb6cfbec018a0f249d496e2db5f1 -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=802ae62e1023c460739670a12b8a331637cec02aec14769bf0bbdbad44217555 -dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=9ab24e33a80a442a540720377855710c2b33617531daa625dff537d1251bb9b4 -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=08a139d7e1ad8559d3add81416581984d24eb997f5d03f2ea85a76eac62df57e -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=dc9dface28b81a1b241a6ad034cd910221866cff7188d94929bd80e3d2dc1598 -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=ecfb3225d805cb7faeb185e43471b35decc735c1330bcb45d54cbb93fac0db4f -dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=60437f2b7cd51cebff36687bc904c7493ef834e39033c08e35883b3de03ed15f -dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=aab495b49ad218fbaf6f36e0dc82ae76dd867ca77411568f15039e494154d890 -dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=51648f6d14e8684c3f258ede3e97371c1530be584b5bc47a92b7bce84d70b397 -dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.gz=6bf818c20105a30461336053b40b9b298388b341766536137a3fd6039e7885ad -dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.xz=60346687b8359a3df7bc4d7beb5532be716bb699fe8aec76664b5b5b4d7cacfc -dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.gz=48b542959792f1cb4c316ee417fec68ccab0ee76a68accbe667fc56ca9d5a367 -dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.xz=b83ebe192f8e2d82fdb0765952e69e4234f11fd6a0a4a69d089b2df42a3c637f -dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.gz=03b36beaf28462424b3b70e6a944d24a22a551c4fd9c245cfd5eef464047ec30 -dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.xz=e00e81bfca624087f97ae2ff675adf08a72519240e31cfaf0f4da238d7be8050 -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f71e27157be06043624ebb769cffc92593d4db6d2a9edabec6815d0f9be64b9f -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=5bd77608b891be20b38739d2b1cd4319feeb13f92214e550a01c599349fd6ce2 -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=0cda1b3a287843431991468cf8dea7a34221d42153e9421ed89a8f58d048e01b -dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=57f3a4d73a40ffe0dad530334f2e584c1279ce3b81458023f034bf8c35dc6641 -dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=5d7c5164b12ad921f1d8461d0edeb17566bf4d5861d6b0f18f66ac1a91b7306d -dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=8ba849b777182977ad9b87c002bff49ff9ad2007932abab98509e96274b9c7d9 -dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=03c12e5d01a6f0b66dfd728610fc0df2f3bef8d5cf418a4d5a385b11f35ecd81 -dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=db0b2d5a9a12c9c8aa0d5d3a320ef8f815ea2ac84718e1bbe94514e7480db6b5 -dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2e3a85da6e7a74b079a5bbbbcd433e0271b89b873aec22c19537669bd908a98c -dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=2b19af7ec21a9e442975b073455e4b3a2711832f6f4a521335034f47dd7725e3 -dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=c293489afe56e4ab984bab7c0ea8db292464b1b0a83b3efac3d38079f71303b2 -dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=fad8d9fce164461c81c5fca56c3557e76635f70ad755cfdb1a448faf161a6b02 -dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1a4d7fb7e5d74649270e79fcdd5b7686bf3db6985d3a781ebb1f069404639884 -dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb1ca19ca8a99b68a1665937c2bfde2a275ff2746cd8b50e097202352a0f7cba -dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.gz=32d6c59ee1bb8d1449393b37ae9399d24ecbfcaa6dc5831ad2bdfb3a586c8ab9 -dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.xz=5a9237c1b359da2c6aac0d6c9202f527d5982310477c414c3c03c6eee50feaf3 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=9b03ad10b3e5de01a813fd9be676135de072de0d3fe6db63e82ff881b9d81c51 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=1e7b91da95fa7fba74c4f8937fc9e02b592c4a66260aab1a4feca24e136501e3 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=59efe9285d460cf8080d3aaed31742cc7ae5dffebb9bdd3410be22a061fa8dc0 -dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=e64edab835454e2024081b9c447798075cc2df3703a8b627d9661c32233c8540 -dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c1ceabe8ad4f89b401a72a6a02843a5f31267cb9762d1a8c30dbcb51c1967488 -dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.xz=456708749343846153490593eebc55d78ae347d0a1096d0fdbea19c99aa24d9e -dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.gz=e01be583da5371501755ca0f6d44cd2abef40543d7d97448933e27ba0de78c8e -dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.xz=42dca4d9e7d76109a3c963b5783554d6ce0171001d744f3fa6b5001bc6ad66a1 -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4464cc28f6a15d5a2a1de098f28224848d0b91779bb70ace3106f3a6208d25dd -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=5f9b9cf42730255c27bef5187241736693b5e39de9fde935da25c9f33deb4325 -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=d6c2b41d4fff28d12b254d3cdab480ac4a81054e50794b6cfb7ed30065cad5a1 -dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1acfe2f78ff7aa747e5b307b40ff5a8be5e8076897b78b2fb5828d1bb1d74cf1 -dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.gz=9d5bfab5bfb9e6d627a5acd1f54fb164538e84c449aa3ea15841636257ec7ab4 -dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.xz=dddd1663a821d99ea19864435e1c7daed6bcb4fd914e6b79c94d644836bc8d1a \ No newline at end of file +dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.gz=58e2ba5f6a388a5bc9ecfa1c7ec4ba3efd9662e1875ea5fba484c75c5f930227 +dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.xz=95f3ed14a6e3093cdee83f80227c7966783fffcc0ff0be6ef095df0dc744b9f8 +dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz=687b58e25baa685be9357048cc1e0c469c25dc6530db55e0179234615ff4d289 +dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz=694e2405efb25c53575599ad6573d8c4646a168e5d4bde922ef5e7d43f3e530c +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=4b42d00e701f90c1fff9a692f1bc1da957fcadbd1813c3066dc1f1990bceadcc +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=4f83a8cced878c03aea2d6cec7e1d588c2b6590850664f28f3b49a3be3a8b827 +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz=bae97ca3778fbaa40f6db4da4f6da0b2bb870e9880165fc3126363f55a1fb23a +dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3e617e866a8c03fef243dede8c086d085a6564aeeb5570bada62db5a16e95f2a +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=96d2f23814db8286de9ffce7bab033aa4dc656f83aa39418c8f877a5befbb100 +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0433a866c4d8a434990746216232759345d3ef556b0b92358b231fc1e727962e +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=6a776c6eb2b7b4992eed6a127d11b8845695cdc5d23938ced2267f88f8d97033 +dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=2649e0f522755dcd511a6459258c3c3a24808fc49d3513f3d9098b17bd0f2c79 +dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=02a65e970ee930b46c2d10e1eb3d2e6f2420e08bbef039f10a8311baf57f274f +dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=3843610c7ecf98948a5f78a364c223d520a084bc8c49ec0c3c8ec48bad6c0bf8 +dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.gz=75288ca1e65157b8902195ec2fff31015017c90d3b8f51890f2f851529b200cb +dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.xz=5c694e50b41cd6f2c7b59b891eda3e728a1a2c56617b96c9da001b35885637b4 +dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.gz=6d1a66c090322ccf272a425c779f9165398e6bd9e0c7e5d0a5f262086d43ed88 +dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.xz=e826fe8be287f8969d11f620da9d01ea0d913eba145fb79ae86bc78674f1b919 +dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.gz=31e0d9a1ff97d92c391cc913fd865a0c8afd614279654350d469bdf881a1b1a3 +dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.xz=3b11a6be4863cb6ad420b66558b7745431834d1fac5dbda899a384dc30b526cf +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=59d96cd092a56d12ea796b65225479803edadbdcb483effdfa36e191f73483f1 +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=0714a469cbd7d96118e9260f80fedf34b21234776904e9c8ec5b71c9493dd36a +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=25113ca9719a036ae581f68df4dda74f1446b49ababe7bb194510fbd1b296e7a +dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=25bd910ea722fe2d4a1e66089352c92f97759ec7212af2b9a04431b469ed8e12 +dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=7a83c9f63d88849c4d691ad1d7fbe7ab5924b5a7d76378ddff5024269be95310 +dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=fbbb11b4c986186d94b0e00ebc70400d0071efc2ba3b802abdd877d86b8cacdd +dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=6223dff24490e3e8506dfbe2b12620155d7c05fce92191cb01f3b28e269bf1be +dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=6fb1edea73bcb76d9cb6061d1aba15ee4655a212c1bf96328a225c7c05df3462 +dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=0b7bc9ec0c40a6203fb62eb71fb6eeab43a4f64a2f7d0d51a1e0d041a216adb1 +dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=d77a49acbf26b8c9a2a5f79fdc640feb1c81b9fa38f442b81f69127f49c7cde7 +dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=bdf45a37fad10df4822690ea73840b38ee3e1048878982e625efbad3b2054f28 +dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=ad6a2f03b2e27711e1ec4eb75502782c4bc0200cfaca2b5246e0bd5b86bf29ad +dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz=b0cc3024a717d33775dbea63e83f317f8826e564ceb4ecb7a6cf23676f66ccdc +dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz=9d5b44a82803d5de5355ffced6ec1dcb9860950910bba6dc54878ad4da7ff444 +dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.gz=c7174c35b530453182f5f0b15c6684c030a2ff2770f4cc1a4a4ba75695e53b99 +dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.xz=c68c26159a3fb4d4380fb25488aa78223989893d7786b8ec947d82ce0cc905bc +dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz=c97caf7877097d78fe2191e715e3a45d827d28c27b4dabf0747f8ca522ee43f5 +dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz=b7794ecabc42698cb77c1c90d66676a8b1b3632108ab95954ee496ee7d6e5708 +dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28068a6e050abe21933920dba3ead2261f7d0c09687d5a86a5db51cca6e72ea9 +dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz=3860d7ec8564019c79551727a3a54c66453a7d654fbb89b8feeae75d9021fa77 +dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.gz=6c2a918f8d40ba01e648565c98ea120d32562dd93820e8f2e33abb2aef08e1da +dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.xz=5d1edcc6c4be49849c3c2d1c3c173d4a127db3cfb615093e5ee396e0d0c77366 +dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.gz=a64c30d82dca58d09bfa38e72bbe1457b48b101157193a3ee33dd85922bbfe9d +dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.xz=87d14b146386fe1f9e24fedc25e1bf9682913bbd7537047b0baef0d74cad5473 +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=3f186913535ac59446e249f4d3e35e3d93a3f8207b31ee31b3f70af8344856bc +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=0c17a60ebac74a9cdfc2ec69fd71a21e370ff178f4c83be6020642b55b6d78ab +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz=327973698dd0ffe9b2d56b3b5929f82ec552f2002b4113fc9a738e27b0005ac0 +dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz=d7e2f768922ae36a9eb302667398ee308c13f829c03235682529fce90253813d +dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.gz=13f327974170a0423ea6e7241cd3a454ab8c39b657a707c08f2e306a7a657b45 +dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.xz=5c75388802c0ddcfa51336883f4039b6f7963e0efbe47c209bb455c12951990b +dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.gz=84c4c02fdecc669c5d26c49120fdece5899133c098f5ef791ea19aba33936dea +dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.xz=7ea047840073e6ad3123a61ca799bc56c951edbb71cb8495ecbc2029759a0190 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.gz=dfb8207b4b3bc13a9704fd1d212d92a22a0e7a57293f24f28bcaa846ad4c08b6 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.xz=96940a84d95b4cfdde84a501758c9dd83f5d6cb5afce9142917d5cb3dd75c040 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=4ed66daf59e9a8b61d66caef4b2248be72049282518d7526be771301bee2b905 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=013d59e32097917b269c45a837bff380a41c4f6401b0c145264cca5a1bbd91c3 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz=270a0322dd3c2342745faa8797f4f64da8c0028b322385d209ff65cf04965a47 +dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz=9d54f7f51c99f17ba9cfe7cbe005ddbfe598f8af6df1dfccc9ef37029cc08b41 +dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.gz=9ae4c1d6044b2c3586791f127108e308e0a381e8e14ecc20b3830ae5258a03c2 +dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.xz=689225ea098a88a88e8e2269ef53f964405a6c31b3ee2bda0fef98da4ed9178e +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=f1d9c996cbe468ca93b15c76b84c544930d7452f1eff2968a298c885203f14cb +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=f3f8c088d74c81b2457ddff57008cb908cc86e16d0fac60d10969e45210d88d6 +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=fb4e5d66911a47bd63429686885cd5c7f0a6310b25622f36bb43a754300526be +dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ab6c7d346bfd72f06fbbc198743bda35fcb7fd1e131c05c54935b6ceff282f17 +dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=32b2e0d5161f7d8354d846c91e5cb25530e78351dfcff4ebf0a6fba669e2c483 +dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=656fc4a8af570b28b3f83cd59d4e5226f15d11b5d8c26b58ca2c1b2a4e18c4df +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=13c98efcde78c1e187f728509f2950a0a407ba32e730877cb9ca4cbb4ba01469 +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=6372891715046375fd0a04e80c95bf79080db2d136e187b02ea96647e9281407 +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=db156e0d5db6f04621e625e92323a04091c049a8b5e2b4f7e0fb2e50b81ab2ec +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=b610214bb59b8f58be96b84b0f13e5f50473e21039f6e827fa16c446d0e9ccba +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=99f96b0bda31bf21853c96b3618408587f275f46ea9bd7d1fc741e58343a5625 +dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=dfa1f209f546b457aa6ef742a645f00f55c70fde86522c737f7a560494170157 +dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.gz=4735b29991a2337a7e2016c5a827635e17ac149372efafc0442a86b0dc0759fb +dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.xz=fead0635c572aa4f5e5564e497f1b7e892217ebe52fea54aedacbefb32f6343d +dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=bbb9b6fedb874a61d99d22b4cdb2d20d8b9e6c69924922312692aa526851b960 +dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=9e0d48236676dc9947565daf0c2605316c5b4abc06bdb1c343559c46b9c4e304 +dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.gz=e230ffa3d46dbe5330416cdf8b7235b8dc2cf119ef8990b422eeebd017ebd17f +dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.xz=38a5560575740f92cb8664d204924cf7a2972e0f2f396852d8a22befd2cdd848 +dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.gz=0b0a9f95d10484207c52fcd8ab1bd56903b53f18ce46fe263d5b7bb085044246 +dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.xz=91f7655ab2bce397a0821edc0f523dbf2bac0af39a50ead106eb1de637ec5c44 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=e8210f03bc18661954f147dedd0b4af721d005866c0c4fea1e91594cd6c9bc2b +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=56a623817e6a600e802727d59d4cd653e84cb628695e39ecb23ae99065113115 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=310a408bde58335d8011af480d4f8c38745865772d71631596cef1a79f9f4fc2 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=fd6766ea9e828adc2e43ff1654a459785eed05ad00c7f6804c742ff8ae8f6b8a +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e663e30526d85d89f41456a3d5bcd411397cb69e7cb9508aa1472b015963fd18 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0361504ada464a7d21e7ac66fdf9e1e820695f3a8ca4854695e78a748c5c7a18 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=c375be97e626900d809390c61bf6f2d689c9fca8e58c85e4e02b694bed4c5ce0 +dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=c33e3b4f9098860f75fcc9a8f86c7e7173692ad4c19cbb2c0de068961f87c192 +dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=3f50d9afd9df4db85958e4575429dd4c80b6702a8d91c3f1d9327345aaadefe0 +dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=0016d3a6ec8351ee9fac2eeae358a0854a3c2b360822bb3ba670255e8f27f57e +dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.gz=f23117b972ccd21c0a6f4db4b544401045c9f157595a297fb56d7e864cf190fe +dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.xz=ab9be4bb25b1575af276cbec7fb1a1f8c683741b0f137bca7b4b61ab13575645 +dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.gz=673561456e26bc992cb6a888c34c0b6b13e1bd0d3e0764360a785a6c3369f0d0 +dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.xz=29c6f01c636bcd901b88e92c60874c454369efd41f690d74b1fa2adf3450166a +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=c214d4439676a19c057324dc736d63aa0328ac74c0eb9ced8d782d8bc89757ae +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=4baf85ac632750c35d007bcae8f23720208c5197f4a1d49b0a85b2b0e137f603 +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=a7e81c0e80f2508c81ba9d8e658dabeb19af2de6f7365f6e377d39e99d8449e7 +dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3f37f746aaa03107573a3a2b201c15bf86777ec405dc03640e7d3f24f718f67f +dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.gz=fe7c7ecb8a8e612caf0e7ecf04d18ccaed31d8b93911ded6b3cba0c78fcbbddc +dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.xz=d571b714821de4b7d2accad221b5e043e7f9aead8dbc06586f4f7ff3f3f3e38e +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=663396f0e4c45bfc041b1a502b64627620f499ca6343664633761c3fb1c2229e +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4d8c47d74958e3b1058ab721e9c6635774afad0252f251b0c9fe4f0895d0c81e +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=3cba82809bc1204b6e8f62877c5e9f9a08f111da7d439032cc30d55be0e88fd7 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=d525a4dde496e72fd18c6f2a525756d652ced436007f513267e9201d8b1c0a40 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=ec0311a0722f205b117160817b2137e9a73f0f4e540930d61c831ceba1265f0d +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=c63c4a28225dfca26baab129f06d8537fae5710083046f203a2fb73c50b48671 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=52eae1bdf37366bf406cff95e5e7979d0651979ae5ad4c036e8badddc8ec8b82 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=542791fb5cd80fe5515ab0812c9fd8671f083151d4262fc76d26f7723ba961e1 +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=91697f75c762bdb51f19348953768a45bc37c389c2e904a56f4f092604ed2d1c +dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=a79a7a5974b365f70598c413da3db8262d14414e3b4d48dde45f529bca4c6ef8 +dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.gz=6eec497ec2aaf6c5beb8e6dfbeaf32190b6f7206aebffb7499b5fdd7e5e7643a +dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.xz=234924a6746fed2efa112b0b805d0ca56252b6cde82e6422774871e9c009fed6 +dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.gz=1b0cd107412fae22266267bd8eccd2b39a36afa8936da3888d0bd0d2f4cfdb1c +dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.xz=0d0d1ee48f9032df88ea7b3f73f06300686f4d5b9fc16f1d4554caf8356cfd74 +dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.gz=72f0549de44925bd08286e092261164dac47826124123e3fe707411a3dfa756c +dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.xz=eb45acd55dd70be3670de83c8cbef5b6ef05827b3f97b7c71679a19c88f8f3e6 +dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.gz=edd8dadbba618f2a786dfcc68e4a5c7f2b7cf1528d1c16ca6ddbc52622df95c6 +dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.xz=ae59c5d77b31aeac30c22104abc0abda6b7f725419e9f86db6cae634ededf262 +dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz=8996c94269e4c60270d253ea75bddb9482facc441ee2314a387888924bea1d92 +dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz=f6b59e3d6e7f0e458c048ad4aad9a2da23f3b54aeac20a905d2e00379da1bd6a +dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.gz=85f22b148be72691214dee620eac582405dc3b8937d2ef7c480c9070b963af3a +dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.xz=4b48538541dd20fad8569cb3f0994d5ce6aceaacdd8b319d00b0234cefc5c267 +dist/2024-11-27/rust-std-beta-i686-linux-android.tar.gz=6e5ce19fc4cd8cf4dbaca8b31f4032b08ee413ce20f354186e4945efd4e8b6af +dist/2024-11-27/rust-std-beta-i686-linux-android.tar.xz=5e78b98abdf2b7348381863052c109beec025a5f68285ce72e6f6e9245c22ce3 +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.gz=50057f990d1127e7d693b1c5b9539b19262a478130bed51dbc2837d61d2db6da +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.xz=ea524b276e42a1cb918625df12b8d3397ada5ecd43bb9ad5c676747e1f916c8b +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=c7c9093e277187590b86ea02fcd940071c8bce93a894396d73953276ec58eb1d +dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a67879ff0dcc591d30a155fd972149953eaac3b139bec9aca3a383dc277ddbc6 +dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.gz=a086c8272f9c7c0db3d5de37b027478dfc22fc577c613254a821700c645df3c9 +dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.xz=8ac4b938e0b643e47d6d0ba6e5283887fcc73cb1a825fc065c35879b085d9c28 +dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.gz=3614b95b54ca24c598e3ed6e14aaa86f7048c2a5be2b3e9f97d9ca00f3d890ce +dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.xz=6d36127f5c113b01300fa0d54062bc1137b51d2514346c8d84bafb9f2c56a972 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz=a6d33a96eeb667f3f4649ea6ccdd6212a183bce85f095ff7db5036c3a50d35a6 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz=bab1dada484d61bb96e2834da5fc6ed5d4d788e6636849e9802f9fb6bff45d55 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.gz=0ac331a1c9e384430a5f316809bffdf01bae3ae9cc1f807f07142ffde7388602 +dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.xz=136341bbf4c820dfc98e96cee41fa0e9fcbc7d81d2772407efaf1d4be6d10f7f +dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.gz=32f06ca3b2752a8687e2f282a59823671fcec672bffc0775a9fb27da50b6bb11 +dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.xz=b2f376089b39a34f3308833ce9bf65200f9665e5c55bbda3e5b7e9c5096b7e67 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=a2ca950893c93be71c7db707230b98674a29c013546e27d95bdf8c3c6eebf9a7 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c70b58f4583578347e9f0fa20d17bd5fc51d88717095e05d73091209f2a363be +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ed284c40b6253c022e39718dc2af2e4100ca7e805d35d86aca04937586f26ece +dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=3efcabf46e0d02505ebf0926c6c14e0c70838f9b510f2328ccd98dd0fa977794 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.gz=9b9f8418fdf64fef652f15b28a1a1f2f8c63c18da8b323994f10f921010721ab +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.xz=fdc673e4b250424c6dafc18a165ffb592aecd7b897e483af8ca54aa145a0e6a9 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=802d22c1c364a58402f9313c6ba2f58b79f3cf3163842a608b78680fa2b3d476 +dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=dc4932d91d8a2887d309dbd6317d6c41afd083043f44742138ca7c97f60b931c +dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=636b19ca036fc7ddcf358062c98f6bcf31e8c2cd035cbb9dc0a6b96c81217f7c +dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=31f80fc50be95bf665d21fe52b714532ff34ebfcdc0c975bb68f7d2f2cebd0e0 +dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=f2c83275df652bc5b387525e77a1aa30bac31fb301b304ddd7e6bf402e140c34 +dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=41358bdb20fe3a97a95fd7b656b1ed03d5b8012354d8cfad2437bc9ef6c7aeb6 +dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=49b8f286b4abb3b34bd38c92ea3e15efbd1f623d5efa7bcff10711b595363579 +dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=283f065701c77fa47a2d5413d20fa40989fbbcc75bc938889de6c4f9b6b9e53e +dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=d0ee5ba5dd6f94dc6ca981be0d55f2e3f51c2af25877131a7a74e0ab9848dc3d +dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=79c78bb31022ec8e7a3fad9823c5d22ac553d389104844110473d1877d8c8302 +dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b953686e3034f2b51033a2630328c8eb5f59fdf8ef4e26189bddb8efb4c482cf +dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=fb25ac2e68594d379f915f0555b3ded2b1a7b5a67144e12eb62949f540b0d957 +dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=fbf5a16a57de3a7e846389aebe18bc7871f43e67eff39fc9b4744b5a445b2639 +dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=55a92aa5770924a21b706724c15f58d66ef2ca5b630f7025f6ba1416152ef350 +dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=b880b7209ea604761ad2a46832925d32fc547737b879645fd3cf99ec235e7b39 +dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=c48cc6a6fda06fab014c0b8fef49006dd32fb71f8e981ba44a0c25d47fbfe034 +dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=7d133b6c8d0e8b8ec8b65a74ed8d64a22e2fa5e4f6d4a1e36f9e0ebb8826f40e +dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=1c507e003c38115bfffe8701df1ff7aed6ad16ef5ac4b383f84bd2d6aa0216bd +dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=111a909b3d1a04b328ca1c1f247ee4eaaa84349eeaa8df77f7901bbc0efc94c1 +dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d29f92ed071c60259feaa8005eb5392da549f8e2069fecb1b77e112f89cf1bbc +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=241b1ec9ef6a89277944c9d8021f521284dc28822c5f80513b6cd94d2bdd1d64 +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=9f5b02be846fa2084becc5616f024094d47beca102442ac7a0e3588e0f12ee7e +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=7272eae1625415c0f57bf541dd62c14e02b9946ca1de04615827a1f5218c2181 +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=d4bcd0068d3c9e7351565fec57ca68d36c9ddbfe59249a6bd2c56930ebad2257 +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=758ccc47004398add2e3cfef52e4839e14dc4d132a215658e576e590401a28ca +dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=6902fee1027b0136f8dc5179e69e24ed9e34366e9409129b9ba223043ddadea1 +dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=3024570f3e382a57fce0e832c52d080a83d42206d8412b724361bd1f0087ec4d +dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=20eaa72b6fa32b9884b43030a0bee554bafa9de3f3b51c5768ba0ff47ec492c1 +dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=a3eae70be3fa5b0a56cc88cc6433cdb7c42b3b974caf0d879d21a5219f4f826e +dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1da88d1882d4dd1f15ca97e016f392a01b56951882ae75929023e83fa557d796 +dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=387cc8ccaeed6f9c6a8c9d21004e45ac97a9739643a63448eb893e13ed4df22d +dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=1b9afe3631fb7847b2a8a8f483fc00ca203ccc18ae298339801dab1c7b06b3b3 +dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.gz=f9a4d2115d6fce06e0da7a9f579b197d383034c218573e145b3c7dae0aad21d4 +dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.xz=c352bc631e538d4e68eaaccdfb9dca1c9dc8ff0ef4a75d8ee91016aada39d717 +dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.gz=d97851ca9193d98192a55aeaf695973ac706e6ba3e198643c200cf410817b424 +dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.xz=89a6524a3743e5a769a583b4a6bf8a76ef5b45c67b7e39da7ae24b687bed4943 +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.gz=6fe614db166618a8f2ccb5807e02884daa8bd8dfded2164f88d79fc688047020 +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.xz=91c5e4f4575ab004119797988679077e5057881ad9a7f6790b673dd062a8b7ee +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d0e05467fb1562ed7d6687a50b7fafa14ba0c2aad328f0e7c19eaca1ee366475 +dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz=0473372df5fece49e58efcd3b2a702bb93e47ec149b38fd5244ad667804e7c63 +dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.gz=e6b6130a1a571325cc1bda8ddba6b2672104c2feeed5c93c6022bfcc8ba4b247 +dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.xz=d4c739c42104e04aba55b96a3ad434e11b013ba44649dd3a648cfbb15de83eb9 +dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=e427d5d6a53abfb53b436df96457d58eedc648198fce6b1d976b50de18cbc31a +dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=11142018c11849c21adaa7096abf50d0c923f3b8f07d67eb96d6860d428e9b27 +dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=46596d8f2271dd5a6f0f84387ac19d0e81976adfc6050b6aab6cc554102fe469 +dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=f3d0c9db1c50a018540278433fed2e0ae4bc798aa0dac87cf0f55ad1808618a1 +dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=c46fc4bf174fc54f5565fa04e80efff4e853642e3e5f0bf5b696a2bd6e7ae817 +dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=706c10ef22cc16b3d4cab8fc09d8783384313b9f774229470b8ae1dd292850b2 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=b9cec80ed374f7b5f22f1446e3f2e0dacfaa0e2d4d6c631ad66cc42a23e156f7 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=41c67ee95e72a3d10bdf739c4841bd937c4e0b19c33451724c1f603b4bd2a318 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=5ad8603f98cff0d5d015c72f3a55730d75d59680a867c067928bf4586c00d805 +dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=61a75701f7e000f86f318a04dc6746f029fb933e0ea94944d76c7eefca1f24b2 +dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz=89bfbfea23974ed75a53ff134386992e9c257d3e51a55eb49847aec9c5ba6b13 +dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz=e34d1586bc6767b4b244f98754badda706645fdec7168ddc0a409b9f95f2b18d +dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.gz=8a88bb923e138d0015c8f46bc1c3d5f2f5f75f40dddfca72a49eed42c080d1db +dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.xz=79a980f2b999c3e3b04d7e327bd2b548007039b45da705847c6da2bfec3ffc04 +dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.gz=454e2c4b46b4684e591c6e4c0f1ce8e3c44623a29d561be3a481ae008072dbd5 +dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.xz=4dcf652ab51fe03c4691de46365218dc483cf1f7c2f5a552a38509685a0ca873 +dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.gz=c2c34d9b3998633cfa145dc2a5568a99d1fe26b91c5be55a08870a1d27db4af7 +dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.xz=4d5b25e4b5fb71d879f15f320f7513eec1ad078d3ca6f525ebf56b9620bdb5ad +dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.gz=e1385a340d3d9a4003cc456156bfbb1435a5255b2bdae3a40b6d7339768bdc81 +dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.xz=245e7914174d213ddbb550b09fff200f419bcd632de98548a470013891666410 +dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.gz=d5d924ea001f914bf87df8765b013db6e838a930a4865e95f8d35bfaa86bc81e +dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.xz=bb98d0d55f38f2308bf99d4e5f11842683452571075eefa5b4e1f18f2bd553bf +dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.gz=edd5e7ea230a13be750dd74c5f7a7dee20db8683f7978aeb352307a0ce110b9d +dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.xz=c6cec9a501d9873e3c7abdefd5b9418f7250c8cb915be8b816cb48dedf1f201e +dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.gz=e970c2a4ebfb69219dc66e4c7541cf22c52da5f94983c7c914df1f93beda3d31 +dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.xz=594ae9bf5f1501322d986dc91249a48a61c22371513b872fd63e134097ac55ca +dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=d57bf579b4629417dbe1c02506db4a4ba4428871a2684141d21303e6c99551f5 +dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=714db83e7563a5f286fb37bc629b64834a9ed981bb9a05931122072f95e39bf8 +dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=feafcba9c46ba3e5fa0bd9b5bedc05ef3423c9962dc4d25a7b2367e3e1caa679 +dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=78fbc8f45df64dca21da7223b5d081111922f2268fcc4f1f83595d159d310bce +dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.gz=74fb57da7f2907afbaa2a7a73847273ef81e2d6902a326f1ae87767677a864d3 +dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.xz=3216eb73d9c9effcd2a2de7f63d78055c3d7e50fb8141e2910a45a36ce744ffb +dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.gz=3df431c8941ac28906c3a6568d3debe478d9349d868ea8bd3ad79e65792c20e8 +dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.xz=548c2a6104148bf0da21bf5e009b80522fd15539077a62021a64f16282815a5e +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=235228431d67feb4c8e6aad44e20bf68574f335e8f948808b597ae98d827171d +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=5a2d4ed70aed26f902cf45e1dcabc5f25884cf6e9aaff775405ba9c1f0a5cacd +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=818131158e8be6af4b762750f7927c4a799346c94059a6073230da79b4408720 +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=fc08b39833e2c9319dcb55cef5c6d1f0110aea794c9a6f163ca39749a22a94b9 +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6164c3ade38c03113193301b815c52df0ee84a4ca1c8ef21e1a56d386e28df00 +dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=0846126e6c4cf2b5184979b6025fbb7bddb5c22905bc7ba31fff69f6b1459280 +dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz=ae308e29be13a176b26c142347a81facf8c11ef1a28e67d5898f4f2a0d3344ca +dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz=e80bcba8b011a4dd3f7b2a2cea69b5a95ae2cde9b2d9078ac8fdd492ac162139 +dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b25f0d605b7f4a2a93adb746e32f59bfc26af569a4169e9fb203cb33751d1575 +dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=010f35236062a651b1b54d7c928068efca8dc486856b84b04e98f4f97583bf32 +dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.gz=db3d258c2caea73b469feb9c11fbd3bcc29d22c3969c406321d11f05c24974ed +dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.xz=a952b0c2bbed9085525c041c957f00b6b1020e031149dba70c09a1a0d40db3ad +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=817d3d3a931eba2255bd5721435cba7604fe37a72c18a179c1fd5f06dc3b97a1 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=170a54aa50f161576d4b0d103f2ab6dcbbb81ee57a5a47f7fbd181128f6c17ff +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=ea991dce55415ed7462abbeb1ac1c70795cb628b0460e14230e8cecd41117fca +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=a8f620c3a641f8f4c29d88e4cc54d7637aeb18cf8eaed8571ce558835f742601 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=875e2e3309b1deccc1a4476e4847a2849df32e0e2a394e4ddf3b4abd1feca534 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=23f21ac664b3341771109ac69d094518a512391b86219ffec50725dc68a08504 +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=680f5b2c63f58643bd34f9921e2c1699a549410ab06bfd04ce991907e8fd7d8f +dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=dd10f6f3ce39489b6e3f3f638573e850c36518e3b2e8ffad0c50c3143e3a8124 +dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz=fd31ba490f0bfc53530e34e6e5ab35a52eebee616efc8ed18d473065ea885230 +dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz=daffc01050f5cf0b5ece91717d7a4c42cd4a148c4c11f641b494d9c375df5177 +dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.gz=376d571641a9f1f75fadf951da91bb73ba94a5495d7d33389f5f914ccbec57bb +dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.xz=ffd9e826537dc94c6d8e767ef5a61d1fcf0385b8ccbe508ff9177de0fe772939 +dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.gz=447e434b5e40f7882d7adb6d0346629e0e3e92d0f339c7781e5a437898a84b4a +dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.xz=bc21caabcb492ca648e19a8f3b9dc1a1bf7792135a202831deb554ec3ea11077 +dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.gz=40ca7d9ebcf6610c26f2921c0560729e708f5661bf6167266e9d8cb3987ad0b3 +dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.xz=06966d5901f5d9accadb47c4d1e561f3f95bd050f3f8e78f30000389f39e9b6c +dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.gz=e1a24f081ddd93b483c0f1c196bae676163db50fef0a994bc47c2a7c98c9dfa7 +dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.xz=d51a5f0669906eceeee4e09b079828e2ebf3404aaedf1fb20745339205270ee0 +dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz=e135a5f0f83432b58d9e093c6d560b021a133707e39e1ded90a28a9967105e0f +dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz=1fbe65015cb8c7ab0b863ffc6f7aa72d3bf52f7830957ede8915c61a22e5b993 +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=9d4e830e9ba582302865fcefe31883cef4a471e77d46e70838e549ca11a0fbce +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=233f6347a36e806dcf27ecad4906c90bb3353051f440a819989efcf091cb78b8 +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz=6cd719a7255a0eb1f11592b9a92d0aa4986363f624ee0d6077fcc253acab66a8 +dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz=b874ca8285ad1936adc70a9323cf80f06322b1e6d5925f54b58500129830f0ca +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=ec7200319224ccabe814cb051e51d147f1ae8c763413002fd03c9263a02c2320 +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=86e96c80a91862e59123272c80f1cfabdca56bfddcd66af4a5e840af7421c4e1 +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=3f7cfdcb28fe8c3f0dde58c24a0c424652b40d00a24fc50891351fa5bff5c15e +dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=2d5a184b0103ac943ec4f6756fbc7126773e739e0d120acea7b3244c7cd19b1b +dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=9a77540943f28584d90b4bcae4e234cc9d833eb732f65d7fbd680a0f4e915da4 +dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=7696a065951b7d7179b30ff2fd16a05675b6bd4250f293666b98ec05299113a5 +dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.gz=eaff75076ad71a4291af5465dedf0fb0998dc171e35ab8f707ac63b43e89c38a +dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.xz=205d3d19726a1a87a1533d94f77b73ed9de8181906acb48088dca22835aa7a83 +dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.gz=58da319889533ff7be5c9142c2abdd1ade79de10eb83d7ef82ebd93b75607f8b +dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.xz=5ae699d0f6b9e210a988af5b8f2f0c4d62fb1695ed6fa55718fdf05298039b9c +dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.gz=362f6338ea929ceb632307031e049dee1b3ed998f5cf160654c327c5e0e7ed39 +dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.xz=88f14ca7b5c8af006f3c54749b61747485f7e93fde4c65b5969e73503d12c5c2 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=9ee8f29e3e715cd7c85e679fd01ca724a27503a50edb0e6f8912f289630bc7a5 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=4c643f0d18ba101c2b248e1df32ec3ddba82efc0d5f9b47945d484fd3d462794 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=f70952c63e2eebd05acc326cfa667595535fc36db34bc0262fda4ba100ff2145 +dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=0546a908cc12884801c35b461f98db01e87a7f92d276ca6cb6b89eb76c596e2c +dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=3534e839b34603e4e2b32fb8ecc76163ea3b9cd9907c1a22fde4165860d1fb56 +dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=b402a2e73debd81dc5cbc866f00c2ca82f676e2f923193674969af0ab34ad311 +dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=fa69011557fdde5af1f78f33f9ba75a1d6f4488b9d8edd2958582593dba347fe +dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=679be0bf62c7371b92f1824c8718662672ac3ef2d79e8af5c752fe34effbe333 +dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=ecc2ba0da5c1057136eb105ec0727e55396e414d75efe0c2b96bef0477961574 +dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=a89ad44842df861c69c6633ba79bf4ecefc38419d5669b6f22a265dd7be836f2 +dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=051437ff7d177bdeb7a5a0eb947d27b8cf352c8e809b9311a1cc21b785a5a8b5 +dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=1a4f50972104a95c404e778279a4acd42176cae45f58d316d601e7f38dc7bbc0 +dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz=bbe9812fe890b900e71aa4714dabd2f3e67bdc610fe0bbd5aea645ee807dd0ff +dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eebac7e8555f44ea9094750b61bd11d758197a72d4d436e1713e4bca42fa8080 +dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.gz=6773b94f012a3d3589e2bca28f35dd23208fb245f107e4a17b8b3e7f893c038a +dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.xz=d3a20dbd60545b0162dc06499317e342bea077cff369e053eb89e85e2b640188 +dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz=39e16c97c0b22533dfa674d6e8f5bf5df256e2b426d02dca5ed33e246f18d05b +dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz=ffd939f901c64a17c3f24fc69744cd2af1c176a45d8e5fa8209067ada403db7d +dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8addc12e74a983f3166b89d1d53ce87c92f38c7c3a62ec7c66580aa424d20516 +dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz=8e5622917395ff50e53b237e7322f1faf2b64f0446c41ccaa0096e57a3e7de69 +dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.gz=2734d099aa1ada79346213aec8cc7ebe40312df1dfb40a32d09ccd3b6622e025 +dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.xz=642edcaf16dd74c0935d28ce9b37cf1c5ecb9c03bec30f6ff0e7476760ae7ca2 +dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.gz=4f28de38005de48db7126dcb698b748063341de41dc71175605301837a3f7336 +dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.xz=ce18692f99780ec09d01816277ee4e71785bdfbd7abb4375ba8d87c1b6905ffa +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=f1d692c3a1c280f34de167ef26af3c13a6d0a3b5ae4fb86b0a9f2178c3287a94 +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=21f477af2b49ec8809bf8bc7b4c4919c7d2ac57782b829f5a0d9ef1967c5d71a +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4bed61be221c1347b1649f54222b27e2a3577b84816ce1099c9f0f461c6e9e5a +dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz=33f463209d50ca6b04a8953c87d2177a84d1729d635de9a7c9b1a711ccb5d751 +dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.gz=ce46b5b2d767cc0d790d8fd21052ecfb787dffb4218a238a339fe5f1afd26d6f +dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.xz=0afd0489cb4231edc5bc1ef24a43c3f1918f681f08c1207d184fefdb46416509 +dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.gz=6e5f1a85dad2b899567369aceac0102943ab807dad7e218c273b7b4d6393dba7 +dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.xz=f784ac4a6ab180675396adf8256ac2bf2d1e823bef106d1c6c59911a8360692c +dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.gz=22f1e9299a24aebaf9a32471ddc6cdbf856b455d059ca077170aecf5989f8772 +dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.xz=7f3fd047ed5aa85ea6ca2b0d6103f7530d7d070c93b0f212c9d1a6491f160cbc +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=f383ecb5cd654268f00be1f577572993c38e7386a1e1d18b864338e87c7b2b42 +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=b2043facf587f98a8f10a92ae129b7f608297709f4ac61d683b7c813cc65e41e +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.gz=6678d45195bd2a7b27ed2d4bad3790e6b63e376da71d112b9333760ea375c40f +dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.xz=f6c77e80c9ea4e312fc2715a9f66ea9a2e6344e3f04ab96cc572e4c0e8c915db +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=be8c0dfde3f09bf476d6600b530aa498b01415015665429bebed8814c7568b73 +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=4315f7623dcf0a278cccb6c8b397a29f83f70ecb9b03588f61e383e5ebaa697d +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=c31ff694c68f28e0f462133e783a5d732cf9c539737fc8dbbfd01a53e9a456c3 +dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=2553ae5596b8273d8a61ec66d2e20d0c9733c9f791ca5c56217c60884f0ccf9a +dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=1842cf2c26ab474df47e74720c56997e270b37609f840ac50ab0b05064cb38fb +dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=e882b1cc2814e3c97c33991fa0a80de62556ce8f4f88307f6338a90be32b045b +dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.gz=7c6e08b841f21e3b8953e51a6a9fd9df0c719e8defd7b1ab0660d8920fe72185 +dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.xz=137aec194877446fec994a233427db419bb4f2910151c456c3ec80d9329628e7 +dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.gz=52ba38277ac3f80d124fdc8dd1709b8c1115cecfc53fae4731da8615a63f78cb +dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.xz=548d3eb599334ab98791b8ba27decff8b0de98dfcffadc994ad38aad6255cff5 +dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.gz=448071394d5e647e8da8f64cfbf85e8305d85ff9357dd24737523c95eb339ab3 +dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.xz=e25daa6264cf5e0a7cbcfd827e27a8e276c29c88c86cc15977c1a1650d0303f9 +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=9f080cc937e7209ad83fdb8bf4b2cd7b080af83dbd9061229f154785e273bfec +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7d537f66195c581ff51ce8f53c4687a762daf225c7f0ce76393953ab04b804e1 +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=2bd38261a9ef33ad687b3edcd33f283c32a493a80b56dbefc822c1116edb1f2f +dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=7e63dff1d8abe517aefeb4b1976932d23a9a7ed5e4db2398d8ba2659301f639c +dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=1495b2a49cfce014da72beb691e6c477d189ef34080acb1761b588d11b75d27a +dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=75da94f1ade2ef48674b77ded595c69ee715f62f9d9dd96e72039e27807b7314 +dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=2d6b826fb4d3d9b61ecd3aaffdd1334f766dd5a5fb0d8279e0de26d381c5cbdc +dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=f5ceaca2651d6002f232f71809458ad912bb5f00030790e907ff7b0e12c9e0c1 +dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=1a62f307197c6fd08fbeabef89f58842cfd59c6d62f530850592fe55852d61f7 +dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=4c65fd6a5d74527391fbc7c242a2313e5290209f5a15763d74eeaa6cba0a0ed0 +dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=8ab9f735a98de1949e65d51c3050b29ceba3ddc28167ba0180353253dc726392 +dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=0367eb23a9349ebd829d59fe0a2638557c8e57205e48f66a701b238461385bf2 +dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ffe9100ec6b81b081d5f9d840bdf01c658790d7e6bc0674e5ebb6b28f79c2f7f +dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.xz=b19b1b28bb7ddf8cf977f102acb623f65d5117c44ab8b62cf197f2d3d33c15de +dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.gz=d986de5c01bde3469693dea7cb4248155ee9791550aa179d601066d27e45afb1 +dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.xz=8000e46ccc2598fdb770c69c68aeb18d94db9b2847d0509f7a9c51ef28714ba7 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.gz=c701581f28d885889ae5c845a7b34beebb04a4631c2740e9333b69390cfaf499 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.xz=fc285792e6f626e133edede613a9a9a90ee12191765e2f0beac642a3b3c9ca12 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.gz=91afdb71bdd54e5c04fc7c933dac06d5e769627e886e20eb712524e852a01966 +dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.xz=2ef7018c7319e3a299c5eddf36748d9d293ae43eaf54662d9855fd211eb4658c +dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.gz=02234d4c47478112e01d51bc7dd48cd467293e1eeba55bd383d08bc7376c471d +dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.xz=a3e6a0c7f31278866d97816c5ed434b1987e0bc5a89b24283e836402803c1388 +dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.gz=b238ab536ac963929884da4dc9bab43679e6fa9aba4251c73ab7e5cbe5d8eeb9 +dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.xz=797ea7a7643a8302e45347f21c4dc6bdee617c2a9d9ccef74ed525c7d2e9dd91 +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=d630a6b25a08af85d3d426e73d3231e018e0ab7176a5934572786147fbbf3823 +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d0259a0112f452ee49b8c9bebd760ab8945e5bc3a0d57b1cdc2b8e24accd35c7 +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.gz=5febe478e5040f0f74a14c23e78eed21b080900d875d6b447354945c07677a6f +dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.xz=552c35bbe76a83439e66cf9ccd522d97e43a8fe4f6aadbabd1f02c4b2c1814dd +dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.gz=ff6db2d7b84e1b01c81e494de15ccd07f60fef6dc60fa46d47e128ebaba4022c +dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.xz=b27f89b175bee3769dab1c2d0c54f17ff3efba2038f3b600f4077435c7fd21d3 +dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz=5b5015483d0a98e9dc715c3cc8c23598c02fc14ea6e5878790ae68f2f1c8ef46 +dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ce5706f0397a1b2fd9e17dbf34ccfbc3e8c87cc81c92b54b81fd33accc2b7c06 +dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=3f5077c8743b5c4f233da7d0aa0aa13fc488ef0fa9da24b002bfa413d52dc845 +dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=087eb30f24ba7d8ee42e28bce2a6cd75e5fb7ef5dca8a738ef23fac82ad59566 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=28a716ef9c5318543559ab4c0c2d062b0deeab1ecec80d5d83ad5effb574f209 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=99cf9ec4b7bea4281f64a613784350a8ac34e9b0387fed7eb26d6f8c21c83735 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a23c3de89603bd4d1035a267e6ee456c6de12efa4029d76ded3edf7c69285a15 +dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=462dfd28b631b5a6d8277920cfa8037d8583cbf6a2e5c9159c492161013e820a +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=44af5b13726cab40865580df8bc05182a2359eae64e41a92f84790ef55ca6bdb +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=0a7c0b207e745d01194d96f0fbe2402273d630d4f1aa05001a5f5371c9585a2c +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=66e2fc688b8f746d15c0dce042f2a94e06c5b652d5e0b6534d9e992eec186784 +dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=15a2e087f7b482fa8c027fe6e6fbaf846d784c8e917fed375048a297d5e13c45 +dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=71788ea2544f8349ec548a2f150dca2afe80a49deb91c00c46484a5e3039742d +dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d9fa7b780b9d8b93549abf0a3f0e6f31cc8e1e991ddf682adf3b616fe2a1f0c8 +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=30924bad51ffa62f762d4c000f86ea3457b590f6397d65755c711ff7f77ac129 +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=14fff13942e6a65927776c49013249b2e75aa3a630667ecf49c9ba721e47bcb4 +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=02d82688bdf3bd3c261a4a6d4acfb07835e29ce262cdc3165ba849a6a8490bcc +dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=2a19b55bb609542ec49dea87e3b67532e5d18df8be43d0ad775bb34f4f9f96a0 +dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=d07ca0ddfb0dd89a9cc935b2b9662379bcc9503cb28a28d68c5165f787a7d762 +dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=de8106801b1e49dfd8a4fffbfc2a4f949218eaa011ca2085953ebf2a5ea9b141 +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=309024f86e80a4568721b5bb61aa936e027accc251fa97acd5043b513b325576 +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=55bf234aa2ec7fd4c6a7179f779d790e7f62969967519bacfeae84db5cd29abe +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=4bf9571182e7ef40e76c7e5905fab8ac35269ace390f5007480b4951f80cfa3b +dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=2a2cde80fcbf68768ba7a99cb059a0cdc9313ad0c934383dde9598d6147ef756 +dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=b747fb16b15cff3f9368ce1a1f5cad0d2930bde5a609547a3afa2679d7ab8a1a +dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=b861f8361ee806d83f38afbbbf312e0e5e4d8851e7048444c409de1a83484446 +dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=ebe56700ad0948e4dcd9930730f7df8e01a5eefca1d1157fe12160d782e2a5c0 +dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=5081c9b8677314464d8a3a50220809def18badb2269d2cd8b7106f3547b0e25a +dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2ed9094b538b6450371311b742f2d309a1f40b2b4c84deb9867059336b76d1b0 +dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d9d52d9b9f4da7a457d05dd4645885d092f170bd2f751a49b4ab3b88395a5248 +dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=a2e51d381645c6bf18502ca72fe9f10ffd309281dae87ec16c5627f232f77e50 +dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=c526efc054c33a08626b882eebadf887a9aaf8fd60a4adf6a146659a7c1ec8d7 +dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=04e5b7c97b57ff7d967abb4f98374f0833108c04f6edf482b8b3fefbde340956 +dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=1829afdebce1c3fe249f81958de68c765db18b431927e54fc42be37ea4ab8226 +dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz=d6cf138d02e50168f8ee4a89abb2a4a39e19458d060d7b46cf227bba1fd4c0d8 +dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e8185262c82c064c4bb9ae6f1d3072819410de9cfca943b77605012a546c254e +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=64d78f9f05a978b95b9e22a63bbb31dcf98152df5638f498a361a96d9d2b0c04 +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c07041ab84364ace58a357c18b5c4dca037852e1159edabb02f4579ac6853b4a +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=7ef0122ccd3a0c77c917bd75e93358eb95d7e87d78a165c724e3f0cd90f8209c +dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=d0d0566a0a50e1e9e7f4251cf207bde82d96c27016f0a0acc364754561ab4881 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=e4854528c31316894339bfa97b07ec607e8956877c285778e555885ce9c8a068 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d79c9b352ed7b2f132f06dcdf360527502b2153beb09cca968a5ced521edcd39 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=df76cbeae0a61506a29db22e8743d16fcd97ef2da216ea15bf4d6cd709814017 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=103cbb30bbe92da6666d84fab53dd7fe8105c2ebe62eeab5f6609488e62a481b +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=5f3c61663a319d6162240192f387e10ab87e2a972062198082158a243b667d7f +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=221b45c3928b1c45fedbeea987ad80750d3f55fbc564cf3ccf910a68447ad725 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=18eb24fd665ce1cc4ce66b37b19c22397bff9369963b127137780870c179228d +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=bcd09587a21ea10953a14521e9e0ba7b5100e8e15b6a10cc4e7bd359200d5279 +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=db712c5e1d21231770e12dc95f6bcbe2f1d04b9cde61bc7adf8b529b41773adf +dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=43303e426752dcd15964416822cdce0e5f3012366a9b77f3d68e6011c7bacd0f +dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.gz=95d543a835b11cb5ccbf0578df1ce4e1846e4915622d23a36cc6e18e44e17f29 +dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.xz=db9e0c51c35c81c2ec8be0838f3231f7374917215792ffee159e3d7ffed855d8 +dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=bf9b83d6418bf97caf2df70a8e8298cd8fecb7b950cdaaa2cecbec243ed57c74 +dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=bb520da5b522fffb5a20eed4390990c2ab9d22eb4f77196535a84ae7a434c9f5 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=4072d9ca2d617d09d394139c0b8608bb8b2b8b2b4fa450f13c41975a16a791c7 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3d75a8a534e86bb55b63f5b5b2df66ae47862cb7f3ecd1591a829435031d7279 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=3cf05e90bc1f95e92cca4769f74055245234037009cf464df3062238c88bc2b6 +dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=245ebb7886cfba64d667630ca8bd672520cfece0ccec3b916e3de0f26aeada52 +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=dadff4abd2f169f9aa1910d4ea247b7d1f767fca74238ad31485b73399ab6dda +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=ff97e1201e9a305673e8a9b740b7696cc4cb5e86bfaa3e137cd8e3e28cffd7a6 +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0c411e0824140323f51600d387d52bd01f601f5539d6457815e950224a6d29a4 +dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=dc5731a70c393f69555433d522cde8a52893bfb88beec519c1bbb03b2a0e060c +dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=01ef2f07f1222fbf3e0cfc5b957c287fb886fd0bd08cbf18f90dc37fb0b63541 +dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d45042b3ea0c0ce6befea7bfdd731e890dbd1f47d1992fe8718a1363f9f18779 +dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.gz=5437da4c0b73d203789829512d856a66c1697d95afb1ffeaa6347ad0f7c04672 +dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.xz=a7cb4cb627d75de1ade9211d8ea489ada9ac76ed38909751861ef0cb729dcbcd +dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.gz=fd6ee6fc171459092e5e8a012d9cfb7491313e021d1c38965605836b5b101b0a +dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.xz=314c7cd558a3654db85d75b3ed71da7cfec3614e4a5f2c449dbc6663b64c7e3d +dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.gz=7a1118011b11befb7df2df57e4450c7611bb3503b3b3cfece9c9c7d4a304391d +dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.xz=2cb95208e77546bcce56d8d5646c3fb5e49ed711894926cb50903ba10431a36e +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=4a76c4493e5ba19aaf14947a6c2e28ebfc7f2da530f1441a9fdfa328e15ea4cf +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=9b361904c691e17fbf44d80c7f7789511db1d8f251d65ba9cf6fda7f06fd495f +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=e89dc76ab061ae23081aee1619fcbf4a94e3acefef6b9b149231f3e1c22f9ec1 +dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=11266d557e6d1d9155e6f04f65e4815cfbfd9f8e1aaa47221030e3ff11b22f78 +dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=30f2eae1b8694607a04c836f750b4b7c204e1e14e52ec37885b9a821c2c9646e +dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=495316e70b26140c66b074e9d7f714ab949f422c2635cab784a5e133538e4bb9 +dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=ca560c4fe28051573d54f512652ac9740a2d1111aeb8e36b004a6ff9c325925c +dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=1191f15bb6da98b01b43f0e9d7f51c5c45d38e3c5be2b4ae5f7c0c8fd25e9a90 +dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5f85829aaab919fa4b2fa5ac843b87358e8da4797adbb6eeaed5be02666ce964 +dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=7c671d366fec561f0b568bfb4b6a08a6071303077a60f76da1307453e51ebc36 +dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=300307ab6cf88afc4312edaa510769e901598492deec4834176c6fc9f3eef6cb +dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=6fcf91c8679f4963f7d510cc8afbc24a1070b25ea6d20d5d31ad78ea659da194 +dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=ab905f6f3119648c83a2f37ebe1a55b7899a5ac6d10070e4dbbfb89762a369af +dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=13688b6857c8b10f7fb497f07c969d406cb6b76869957b5138f4b20fcc5d7c5a +dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.gz=e6bb782014e34fafdc5dcf3aeb407eb636d822d346c5a8c6227cc45bc645561a +dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.xz=6016ae620deddc42d1d6b6134b0164dab45a204089754b73db41ec837aa88a84 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ed3a381858612e25cacfd89c08496e9d06378d593ccedea4217ad4fa1ab326d4 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=4819bb9c25aa743de7ab7e93b10b30336a87f1f75e5122d578df2c83fbc59850 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=404aac87c77871c80f83cd7c59390af9af704ee468f40eba68d224d23e2c84e9 +dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=0e1e0d2454ad24fe1da2cce2dce425bc1167bbca68832da2476c7996c00ba612 +dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.gz=946d5bcc3ac0b83fd0b53b60290a6361b179f16ba2aa6a2467789ad520278792 +dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f3bd1a053399ec89dccaa7456da41d54a8e91deb5c628e4c502fdcf34c5fe780 +dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.gz=c353588a38705b7ae050d4b9868b6c4d3527295edbfb25c115b22cda4912be1f +dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.xz=a71d8b2b42f6cd522da237f99492ed59cd34ea8c86fc1e73c8854c8234e1c980 +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=5116b949572fd6c7b11a079d9453b15a4c48562bce22b26d82b7050da772789b +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=3635df40363273d44c6f8182f5f6a3a099ed55897bb764cab2565363cd31c1f4 +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=5233af0b907fb7b176d2b5fee07c486e92dcbbbab1d54a60d814a827befaa984 +dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c908cad6d28657f1fdcbe9d84ecb86f247c75134803dd5273ca24c6c68a58f37 +dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.gz=c799165c319218a2fb4cdc0ac8db87fc9e2992a8e402d984ea27938a5ad1c5af +dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.xz=ec12763fa5d4cc150f663361cd245c30835e05e3b1928898b1b7300de559468c \ No newline at end of file From 4342ec0cf29d5d2e8bc7f66546723882b7728789 Mon Sep 17 00:00:00 2001 From: Sebastian Urban Date: Wed, 27 Nov 2024 13:30:18 +0100 Subject: [PATCH 118/330] Implement code review --- library/std/src/sys/pal/wasi/thread.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index 3b44f77631f5..f5e19f26bfe1 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -192,8 +192,7 @@ pub fn available_parallelism() -> io::Result> { if #[cfg(target_feature = "atomics")] { match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { -1 => Err(io::Error::last_os_error()), - 0 => Err(io::Error::UNKNOWN_THREAD_COUNT), - cpus => Ok(unsafe { NonZero::new_unchecked(cpus as usize) }), + cpus => NonZero::new(cpus as usize).ok_or(io::Error::UNKNOWN_THREAD_COUNT), } } else { crate::sys::unsupported() From f592dd95dbfc892c1153af67e0ab5b4e593d33e7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 24 Nov 2024 09:08:07 -0800 Subject: [PATCH 119/330] Compiletest: Add proc-macro header This adds a proc-macro header to make it easier to depend on a proc-macro, and remove some of the boilerplate necessary. --- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header.rs | 1 + src/tools/compiletest/src/header/auxiliary.rs | 11 ++- src/tools/compiletest/src/runtest.rs | 76 ++++++++++++++----- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 0c47ef871d21..952533e904c5 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -215,6 +215,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "pp-exact", "pretty-compare-only", "pretty-mode", + "proc-macro", "reference", "regex-error-pattern", "remap-src-base", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e945797647e2..fe4c5fdd8b51 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -221,6 +221,7 @@ mod directives { pub const AUX_BIN: &'static str = "aux-bin"; pub const AUX_BUILD: &'static str = "aux-build"; pub const AUX_CRATE: &'static str = "aux-crate"; + pub const PROC_MACRO: &'static str = "proc-macro"; pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend"; pub const EXEC_ENV: &'static str = "exec-env"; pub const RUSTC_ENV: &'static str = "rustc-env"; diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs index 6f6538ce196d..0e1f3a785f87 100644 --- a/src/tools/compiletest/src/header/auxiliary.rs +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -4,7 +4,7 @@ use std::iter; use crate::common::Config; -use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; +use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; /// Properties parsed from `aux-*` test directives. #[derive(Clone, Debug, Default)] @@ -17,6 +17,8 @@ pub(crate) struct AuxProps { /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies /// to build and pass with the `--extern` flag. pub(crate) crates: Vec<(String, String)>, + /// Same as `builds`, but for proc-macros. + pub(crate) proc_macros: Vec, /// Similar to `builds`, but also uses the resulting dylib as a /// `-Zcodegen-backend` when compiling the test file. pub(crate) codegen_backend: Option, @@ -26,12 +28,13 @@ impl AuxProps { /// Yields all of the paths (relative to `./auxiliary/`) that have been /// specified in `aux-*` directives for this test. pub(crate) fn all_aux_path_strings(&self) -> impl Iterator { - let Self { builds, bins, crates, codegen_backend } = self; + let Self { builds, bins, crates, proc_macros, codegen_backend } = self; iter::empty() .chain(builds.iter().map(String::as_str)) .chain(bins.iter().map(String::as_str)) .chain(crates.iter().map(|(_, path)| path.as_str())) + .chain(proc_macros.iter().map(String::as_str)) .chain(codegen_backend.iter().map(String::as_str)) } } @@ -39,13 +42,15 @@ impl AuxProps { /// If the given test directive line contains an `aux-*` directive, parse it /// and update [`AuxProps`] accordingly. pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { - if !ln.starts_with("aux-") { + if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) { return; } config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); + config + .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string()); if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { aux.codegen_backend = Some(r.trim().to_owned()); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index bc80c8246ad0..93e5980f1f5f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -102,7 +102,7 @@ fn get_lib_name(name: &str, aux_type: AuxType) -> Option { // In this case, the only path we can pass // with '--extern-meta' is the '.rlib' file AuxType::Lib => Some(format!("lib{name}.rlib")), - AuxType::Dylib => Some(dylib_name(name)), + AuxType::Dylib | AuxType::ProcMacro => Some(dylib_name(name)), } } @@ -1097,7 +1097,9 @@ impl<'test> TestCx<'test> { } fn has_aux_dir(&self) -> bool { - !self.props.aux.builds.is_empty() || !self.props.aux.crates.is_empty() + !self.props.aux.builds.is_empty() + || !self.props.aux.crates.is_empty() + || !self.props.aux.proc_macros.is_empty() } fn aux_output_dir(&self) -> PathBuf { @@ -1118,31 +1120,48 @@ impl<'test> TestCx<'test> { fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { for rel_ab in &self.props.aux.builds { - self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */); + self.build_auxiliary(of, rel_ab, &aux_dir, None); } for rel_ab in &self.props.aux.bins { - self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */); + self.build_auxiliary(of, rel_ab, &aux_dir, Some(AuxType::Bin)); } + let path_to_crate_name = |path: &str| -> String { + path.rsplit_once('/') + .map_or(path, |(_, tail)| tail) + .trim_end_matches(".rs") + .replace('-', "_") + }; + + let add_extern = + |rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| { + let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type); + if let Some(lib_name) = lib_name { + rustc.arg("--extern").arg(format!( + "{}={}/{}", + aux_name, + aux_dir.display(), + lib_name + )); + } + }; + for (aux_name, aux_path) in &self.props.aux.crates { - let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */); - let lib_name = - get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); - if let Some(lib_name) = lib_name { - rustc.arg("--extern").arg(format!( - "{}={}/{}", - aux_name, - aux_dir.display(), - lib_name - )); - } + let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, None); + add_extern(rustc, aux_name, aux_path, aux_type); + } + + for proc_macro in &self.props.aux.proc_macros { + self.build_auxiliary(of, proc_macro, &aux_dir, Some(AuxType::ProcMacro)); + let crate_name = path_to_crate_name(proc_macro); + add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro); } // Build any `//@ aux-codegen-backend`, and pass the resulting library // to `-Zcodegen-backend` when compiling the test file. if let Some(aux_file) = &self.props.aux.codegen_backend { - let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false); + let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None); if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { let lib_path = aux_dir.join(&lib_name); rustc.arg(format!("-Zcodegen-backend={}", lib_path.display())); @@ -1209,17 +1228,23 @@ impl<'test> TestCx<'test> { } /// Builds an aux dependency. + /// + /// If `aux_type` is `None`, then this will determine the aux-type automatically. fn build_auxiliary( &self, of: &TestPaths, source_path: &str, aux_dir: &Path, - is_bin: bool, + aux_type: Option, ) -> AuxType { let aux_testpaths = self.compute_aux_test_paths(of, source_path); - let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + let mut aux_props = + self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + if aux_type == Some(AuxType::ProcMacro) { + aux_props.force_host = true; + } let mut aux_dir = aux_dir.to_path_buf(); - if is_bin { + if aux_type == Some(AuxType::Bin) { // On unix, the binary of `auxiliary/foo.rs` will be named // `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so // put bins in a `bin` subfolder. @@ -1250,8 +1275,12 @@ impl<'test> TestCx<'test> { aux_rustc.env_remove(key); } - let (aux_type, crate_type) = if is_bin { + let (aux_type, crate_type) = if aux_type == Some(AuxType::Bin) { (AuxType::Bin, Some("bin")) + } else if aux_type == Some(AuxType::ProcMacro) { + (AuxType::ProcMacro, Some("proc-macro")) + } else if aux_type.is_some() { + panic!("aux_type {aux_type:?} not expected"); } else if aux_props.no_prefer_dynamic { (AuxType::Dylib, None) } else if self.config.target.contains("emscripten") @@ -1287,6 +1316,11 @@ impl<'test> TestCx<'test> { aux_rustc.args(&["--crate-type", crate_type]); } + if aux_type == AuxType::ProcMacro { + // For convenience, but this only works on 2018. + aux_rustc.args(&["--extern", "proc_macro"]); + } + aux_rustc.arg("-L").arg(&aux_dir); let auxres = aux_cx.compose_and_run( @@ -2768,8 +2802,10 @@ enum LinkToAux { No, } +#[derive(Debug, PartialEq)] enum AuxType { Bin, Lib, Dylib, + ProcMacro, } From 41c3b5c3778c8c9aac20a01ea47407acab3cacf3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 27 Nov 2024 15:26:11 +0100 Subject: [PATCH 120/330] show forbidden_lint_groups in future-compat reports --- compiler/rustc_lint_defs/src/builtin.rs | 2 +- tests/ui/lint/forbid-group-group-2.stderr | 54 +++ tests/ui/lint/forbid-group-member.stderr | 14 + ...-dont-override-forbid-in-same-scope.stderr | 396 +++++++++++++++++ tests/ui/lint/outer-forbid.stderr | 414 ++++++++++++++++++ 5 files changed, 879 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 3b406c7e161a..d2b7ae620e2b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -179,7 +179,7 @@ declare_lint! { Warn, "applying forbid to lint-groups", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #81670 ", }; } diff --git a/tests/ui/lint/forbid-group-group-2.stderr b/tests/ui/lint/forbid-group-group-2.stderr index 80e2f566eb84..b075a521cc96 100644 --- a/tests/ui/lint/forbid-group-group-2.stderr +++ b/tests/ui/lint/forbid-group-group-2.stderr @@ -43,3 +43,57 @@ LL | #[allow(nonstandard_style)] error: aborting due to 3 previous errors +Future incompatibility report: Future breakage diagnostic: +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(nonstandard_style) incompatible with previous forbid + --> $DIR/forbid-group-group-2.rs:7:9 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +... +LL | #[allow(nonstandard_style)] + | ^^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/forbid-group-group-2.rs:5:9 + | +LL | #![deny(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/forbid-group-member.stderr b/tests/ui/lint/forbid-group-member.stderr index 8794591bd313..2e0147693f33 100644 --- a/tests/ui/lint/forbid-group-member.stderr +++ b/tests/ui/lint/forbid-group-member.stderr @@ -13,3 +13,17 @@ LL | #[allow(unused_variables)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: allow(unused_variables) incompatible with previous forbid + --> $DIR/forbid-group-member.rs:8:9 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 + = note: `#[warn(forbidden_lint_groups)]` on by default + diff --git a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr index 407eaf1c60a7..77c8d1eab584 100644 --- a/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr +++ b/tests/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr @@ -17,3 +17,399 @@ LL | #![forbid(forbidden_lint_groups)] error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: warn(unused) incompatible with previous forbid + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13 + | +LL | #![forbid(unused)] + | ------ `forbid` level set here +LL | #![deny(unused)] +LL | #![warn(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/lint/outer-forbid.stderr b/tests/ui/lint/outer-forbid.stderr index a47877980a06..64a1077462ab 100644 --- a/tests/ui/lint/outer-forbid.stderr +++ b/tests/ui/lint/outer-forbid.stderr @@ -39,3 +39,417 @@ LL | #[allow(nonstandard_style)] error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0453`. +Future incompatibility report: Future breakage diagnostic: +error: allow(unused_variables) incompatible with previous forbid + --> $DIR/outer-forbid.rs:20:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused_variables)] + | ^^^^^^^^^^^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: allow(unused) incompatible with previous forbid + --> $DIR/outer-forbid.rs:25:9 + | +LL | #![forbid(unused, non_snake_case)] + | ------ `forbid` level set here +... +LL | #[allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 +note: the lint level is defined here + --> $DIR/outer-forbid.rs:18:11 + | +LL | #![forbid(forbidden_lint_groups)] + | ^^^^^^^^^^^^^^^^^^^^^ + From 22998f078588cf479530ff93e4a66ab4bb666398 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 27 Nov 2024 15:14:47 +0000 Subject: [PATCH 121/330] update cfgs --- compiler/rustc_builtin_macros/src/lib.rs | 2 +- library/alloc/benches/lib.rs | 3 +- library/alloc/src/boxed.rs | 11 +- library/alloc/src/lib.rs | 3 +- library/alloc/src/raw_vec.rs | 3 - library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/alloc/src/vec/mod.rs | 4 +- library/alloc/tests/boxed.rs | 2 +- library/alloc/tests/lib.rs | 3 +- library/core/Cargo.toml | 2 - library/core/src/alloc/layout.rs | 9 +- library/core/src/cell.rs | 9 +- library/core/src/char/methods.rs | 5 - library/core/src/ffi/c_str.rs | 8 +- library/core/src/fmt/mod.rs | 4 - library/core/src/future/future.rs | 2 +- library/core/src/hint.rs | 1 - library/core/src/intrinsics/mod.rs | 246 ++++-------------- library/core/src/lib.rs | 7 +- library/core/src/macros/mod.rs | 1 - library/core/src/mem/maybe_uninit.rs | 9 +- library/core/src/num/int_macros.rs | 7 - library/core/src/num/mod.rs | 1 - library/core/src/num/uint_macros.rs | 7 - library/core/src/ops/deref.rs | 6 +- library/core/src/ops/mod.rs | 1 - library/core/src/option.rs | 2 +- library/core/src/panic.rs | 3 +- library/core/src/panicking.rs | 27 +- library/core/src/ptr/alignment.rs | 7 - library/core/src/ptr/const_ptr.rs | 2 - library/core/src/ptr/metadata.rs | 3 - library/core/src/ptr/mut_ptr.rs | 2 - library/core/src/ptr/non_null.rs | 1 - library/core/src/result.rs | 2 +- library/core/src/slice/memchr.rs | 4 - library/core/src/slice/mod.rs | 4 +- library/core/src/str/mod.rs | 4 +- library/core/src/task/wake.rs | 2 - library/core/src/ub_checks.rs | 2 - library/core/src/unicode/unicode_data.rs | 3 - library/core/tests/lib.rs | 4 +- library/panic_unwind/Cargo.toml | 5 +- library/std/Cargo.toml | 2 - library/std/src/lib.rs | 6 +- .../std/src/sys/sync/condvar/no_threads.rs | 1 - library/std/src/sys/sync/mutex/no_threads.rs | 1 - library/std/src/sys/sync/once/no_threads.rs | 1 - library/std/src/sys/sync/once/queue.rs | 1 - library/std/src/sys/sync/rwlock/no_threads.rs | 1 - library/std/src/sys/thread_local/key/racy.rs | 1 - library/std/src/sys/thread_local/os.rs | 1 - library/std/src/thread/local.rs | 1 - library/unwind/Cargo.toml | 5 +- .../src/range_search.rs | 1 - .../src/raw_emitter.rs | 4 - 57 files changed, 107 insertions(+), 356 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9eee92164cf1..cc4a974e7578 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,10 +5,10 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(autodiff)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index c1907361f93e..2633154318c1 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -4,8 +4,7 @@ #![feature(iter_next_chunk)] #![feature(repr_simd)] #![feature(slice_partition_dedup)] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] +#![feature(strict_provenance_lints)] #![feature(test)] #![deny(fuzzy_provenance_casts)] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ee60ec0fbacb..e0f94428cfa6 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -191,9 +191,7 @@ use core::error::{self, Error}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -#[cfg(not(bootstrap))] -use core::marker::PointerLike; -use core::marker::{Tuple, Unsize}; +use core::marker::{PointerLike, Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, @@ -227,7 +225,7 @@ pub use thin::ThinBox; #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] // The declaration of the `Box` struct must be kept in sync with the // compiler or ICEs will happen. pub struct Box< @@ -1502,7 +1500,7 @@ impl Box { /// [`as_ptr`]: Self::as_ptr #[unstable(feature = "box_as_ptr", issue = "129090")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub fn as_mut_ptr(b: &mut Self) -> *mut T { // This is a primitive deref, not going through `DerefMut`, and therefore not materializing @@ -1551,7 +1549,7 @@ impl Box { /// [`as_ptr`]: Self::as_ptr #[unstable(feature = "box_as_ptr", issue = "129090")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub fn as_ptr(b: &Self) -> *const T { // This is a primitive deref, not going through `DerefMut`, and therefore not materializing @@ -2134,6 +2132,5 @@ impl Error for Box { } } -#[cfg(not(bootstrap))] #[unstable(feature = "pointer_like_trait", issue = "none")] impl PointerLike for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 041ff37897f0..108224b27fa8 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -163,8 +163,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] @@ -188,6 +186,7 @@ #![feature(slice_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 85a9120c7e25..48429aea16bd 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -103,7 +103,6 @@ impl RawVec { /// `RawVec` with capacity `usize::MAX`. Useful for implementing /// delayed allocation. #[must_use] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] pub const fn new() -> Self { Self::new_in(Global) } @@ -179,7 +178,6 @@ impl RawVec { /// Like `new`, but parameterized over the choice of allocator for /// the returned `RawVec`. #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] pub const fn new_in(alloc: A) -> Self { Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } } @@ -409,7 +407,6 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] const fn new_in(alloc: A, align: usize) -> Self { let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 48ffdcb77d31..7aa1457b1df5 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -307,7 +307,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { /// `value.get_mut()`. This avoids conflicts with methods of the inner type `T`. /// /// [get_mut]: Rc::get_mut -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f7d1c9e4efb4..b8bdd298c27a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -235,7 +235,7 @@ macro_rules! acquire { /// counting in general. /// /// [rc_examples]: crate::rc#examples -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 990b7e8f7612..4750d663e0c3 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1662,7 +1662,7 @@ impl Vec { #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub const fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through @@ -1725,7 +1725,7 @@ impl Vec { #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub const fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 6a8ba5c92fb3..94389cf2de93 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -4,7 +4,7 @@ use core::mem::MaybeUninit; use core::ptr::NonNull; #[test] -#[cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))] +#[expect(dangling_pointers_from_temporaries)] fn uninitialized_zero_size_box() { assert_eq!( &*Box::<()>::new_uninit() as *const _, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 699a8e6776e6..02bbb40ef81d 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -32,10 +32,9 @@ #![feature(panic_update_hook)] #![feature(pointer_is_aligned_to)] #![feature(thin_box)] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(drain_keep_rest)] #![feature(local_waker)] +#![feature(strict_provenance_lints)] #![feature(vec_pop_if)] #![feature(unique_rc_arc)] #![feature(macro_metavar_expr_concat)] diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 94f343d06705..cace4582b489 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -43,8 +43,6 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', # core use #[path] imports to portable-simd `core_simd` crate # and to stdarch `core_arch` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index f412ca171633..60936da2e0b0 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -157,7 +157,6 @@ impl Layout { #[must_use = "this returns the minimum alignment, \ without modifying the layout"] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(ptr_alignment_type))] pub const fn align(&self) -> usize { self.align.as_usize() } @@ -255,7 +254,7 @@ impl Layout { /// `align` violates the conditions listed in [`Layout::from_size_align`]. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn align_to(&self, align: usize) -> Result { if let Some(align) = Alignment::new(align) { @@ -331,7 +330,7 @@ impl Layout { /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[must_use = "this returns a new `Layout`, \ without modifying the original"] #[inline] @@ -431,7 +430,7 @@ impl Layout { /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { let new_align = Alignment::max(self.align, next.align); @@ -495,7 +494,7 @@ impl Layout { /// `isize::MAX`, returns `LayoutError`. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn array(n: usize) -> Result { // Reduce the amount of code we need to monomorphize per `T`. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d62cb28fc572..c55397903277 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -587,7 +587,7 @@ impl Cell { #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] #[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn as_ptr(&self) -> *mut T { self.value.get() @@ -1150,7 +1150,7 @@ impl RefCell { /// ``` #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub fn as_ptr(&self) -> *mut T { self.value.get() @@ -2135,7 +2135,6 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(value: &mut T) -> &mut UnsafeCell { // SAFETY: `UnsafeCell` has the same memory layout as `T` due to #[repr(transparent)]. unsafe { &mut *(value as *mut T as *mut UnsafeCell) } @@ -2160,7 +2159,7 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of @@ -2308,7 +2307,7 @@ impl SyncUnsafeCell { /// when casting to `&mut T`, and ensure that there are no mutations /// or mutable aliases going on when casting to `&T` #[inline] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn get(&self) -> *mut T { self.value.get() diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 86822af31ca2..7d33765879f2 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1787,7 +1787,6 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0"))] #[doc(hidden)] #[inline] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { @@ -1836,10 +1835,6 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { /// Panics if the buffer is not large enough. /// A buffer of length 2 is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0") -)] #[doc(hidden)] #[inline] pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9e32f74227cf..8831443a10f1 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -138,11 +138,9 @@ enum FromBytesWithNulErrorKind { // FIXME: const stability attributes should not be required here, I think impl FromBytesWithNulError { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))] const fn interior_nul(pos: usize) -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } } - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))] const fn not_nul_terminated() -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } } @@ -464,8 +462,7 @@ impl CStr { /// /// ```no_run /// # #![allow(unused_must_use)] - /// # #![cfg_attr(bootstrap, expect(temporary_cstring_as_ptr))] - /// # #![cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))] + /// # #![expect(dangling_pointers_from_temporaries)] /// use std::ffi::CString; /// /// // Do not do this: @@ -500,7 +497,7 @@ impl CStr { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() @@ -732,7 +729,6 @@ impl AsRef for CStr { /// located within `isize::MAX` from `ptr`. #[inline] #[unstable(feature = "cstr_internals", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))] #[rustc_allow_const_fn_unstable(const_eval_select)] const unsafe fn strlen(ptr: *const c_char) -> usize { const_eval_select!( diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 9db6d27967ff..7fc9dd21fdd8 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -333,10 +333,6 @@ pub struct Arguments<'a> { #[unstable(feature = "fmt_internals", issue = "none")] impl<'a> Arguments<'a> { #[inline] - #[cfg_attr( - bootstrap, - rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none") - )] pub const fn new_const(pieces: &'a [&'static str; N]) -> Self { const { assert!(N <= 1) }; Arguments { pieces, fmt: None, args: &[] } diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 234914c20fc3..cfbd88bbe799 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -25,7 +25,7 @@ use crate::task::{Context, Poll}; /// [`async`]: ../../std/keyword.async.html /// [`Waker`]: crate::task::Waker #[doc(notable_trait)] -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 78df51f2bc47..c59e4414d372 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -506,7 +506,6 @@ pub const fn black_box(dummy: T) -> T { /// # } /// ``` #[unstable(feature = "hint_must_use", issue = "94745")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "hint_must_use", issue = "94745"))] #[must_use] // <-- :) #[inline(always)] pub const fn must_use(value: T) -> T { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 8741e1b08075..6b9011adf3d3 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1431,11 +1431,7 @@ pub fn abort() -> ! { /// reach code marked with this function. /// /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1453,8 +1449,7 @@ pub const unsafe fn unreachable() -> ! { /// own, or if it does not enable any significant optimizations. /// /// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -1474,8 +1469,7 @@ pub const unsafe fn assume(b: bool) { /// /// This intrinsic does not have a stable counterpart. #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(not(bootstrap), rustc_intrinsic)] -#[cfg(not(bootstrap))] +#[rustc_intrinsic] #[rustc_nounwind] #[miri::intrinsic_fallback_is_spec] #[cold] @@ -1492,19 +1486,10 @@ pub const fn cold_path() {} /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_likely", since = "1.84.0") -)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[inline(always)] pub const fn likely(b: bool) -> bool { - #[cfg(bootstrap)] - { - b - } - #[cfg(not(bootstrap))] if b { true } else { @@ -1524,19 +1509,10 @@ pub const fn likely(b: bool) -> bool { /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_likely", since = "1.84.0") -)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[inline(always)] pub const fn unlikely(b: bool) -> bool { - #[cfg(bootstrap)] - { - b - } - #[cfg(not(bootstrap))] if b { cold_path(); true @@ -1570,8 +1546,7 @@ pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { /// This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1583,8 +1558,7 @@ pub const fn assert_inhabited() { /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1595,8 +1569,7 @@ pub const fn assert_zero_valid() { /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1612,8 +1585,7 @@ pub const fn assert_mem_uninitialized_valid() { /// any safety invariants. /// /// Consider using [`core::panic::Location::caller`] instead. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1630,8 +1602,7 @@ pub const fn caller_location() -> &'static crate::panic::Location<'static> { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1944,8 +1915,7 @@ pub const unsafe fn transmute(_src: Src) -> Dst { /// /// This is not expected to ever be exposed directly to users, rather it /// may eventually be exposed through some more-constrained API. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1966,8 +1936,7 @@ pub const unsafe fn transmute_unchecked(_src: Src) -> Dst { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1992,8 +1961,7 @@ pub const fn needs_drop() -> bool { /// /// The stabilized version of this intrinsic is [`pointer::offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2015,8 +1983,7 @@ pub const unsafe fn offset(_dst: Ptr, _offset: Delta) -> Ptr { /// /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2723,8 +2690,7 @@ pub fn frem_algebraic(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2768,8 +2734,7 @@ pub const fn ctpop(_x: T) -> u32 { /// let num_leading = ctlz(x); /// assert_eq!(num_leading, 16); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2794,8 +2759,7 @@ pub const fn ctlz(_x: T) -> u32 { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2839,8 +2803,7 @@ pub const unsafe fn ctlz_nonzero(_x: T) -> u32 { /// let num_trailing = cttz(x); /// assert_eq!(num_trailing, 16); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2865,8 +2828,7 @@ pub const fn cttz(_x: T) -> u32 { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2884,8 +2846,7 @@ pub const unsafe fn cttz_nonzero(_x: T) -> u32 { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, /// [`u32::swap_bytes`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2903,8 +2864,7 @@ pub const fn bswap(_x: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, /// [`u32::reverse_bits`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2919,7 +2879,6 @@ pub const fn bitreverse(_x: T) -> T { /// large and difficult to optimize. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_three_way_compare", issue = "none"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Ordering { @@ -2936,8 +2895,7 @@ pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Orderi /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`u32::overflowing_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2955,8 +2913,7 @@ pub const fn add_with_overflow(_x: T, _y: T) -> (T, bool) { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`u32::overflowing_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2974,8 +2931,7 @@ pub const fn sub_with_overflow(_x: T, _y: T) -> (T, bool) { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`u32::overflowing_mul`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2987,7 +2943,6 @@ pub const fn mul_with_overflow(_x: T, _y: T) -> (T, bool) { /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_exact_div", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3001,8 +2956,7 @@ pub const unsafe fn exact_div(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_div` method. For example, /// [`u32::checked_div`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3015,8 +2969,7 @@ pub const unsafe fn unchecked_div(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_rem` method. For example, /// [`u32::checked_rem`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3030,8 +2983,7 @@ pub const unsafe fn unchecked_rem(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3044,8 +2996,7 @@ pub const unsafe fn unchecked_shl(_x: T, _y: U) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3058,8 +3009,7 @@ pub const unsafe fn unchecked_shr(_x: T, _y: U) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_add` on the various /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3072,8 +3022,7 @@ pub const unsafe fn unchecked_add(_x: T, _y: T) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_sub` on the various /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3086,8 +3035,7 @@ pub const unsafe fn unchecked_sub(_x: T, _y: T) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_mul` on the various /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3105,8 +3053,7 @@ pub const unsafe fn unchecked_mul(_x: T, _y: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3124,8 +3071,7 @@ pub const fn rotate_left(_x: T, _shift: u32) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3143,8 +3089,7 @@ pub const fn rotate_right(_x: T, _shift: u32) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`u32::wrapping_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3161,8 +3106,7 @@ pub const fn wrapping_add(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`u32::wrapping_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3179,8 +3123,7 @@ pub const fn wrapping_sub(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`u32::wrapping_mul`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3198,8 +3141,7 @@ pub const fn wrapping_mul(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, /// [`u32::saturating_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3216,8 +3158,7 @@ pub const fn saturating_add(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, /// [`u32::saturating_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3231,8 +3172,7 @@ pub const fn saturating_sub(_a: T, _b: T) -> T { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it /// trivially obeys runtime-MIR rules about derefs in operands. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3246,8 +3186,7 @@ pub const unsafe fn read_via_copy(_ptr: *const T) -> T { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3264,8 +3203,7 @@ pub const unsafe fn write_via_move(_ptr: *mut T, _value: T) { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3304,8 +3242,7 @@ extern "rust-intrinsic" { } /// See documentation of `<*const T>::offset_from` for details. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3314,7 +3251,6 @@ pub const unsafe fn ptr_offset_from(_ptr: *const T, _base: *const T) -> isize } /// See documentation of `<*const T>::sub_ptr` for details. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3326,7 +3262,6 @@ pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) /// Returns `2` if the result is unknown. /// Returns `1` if the pointers are guaranteed equal. /// Returns `0` if the pointers are guaranteed inequal. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[rustc_intrinsic] #[rustc_nounwind] #[rustc_do_not_const_check] @@ -3359,7 +3294,6 @@ pub const fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8 { /// /// (The implementation is allowed to branch on the results of comparisons, /// which is UB if any of their inputs are `undef`.) -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3381,10 +3315,6 @@ pub const unsafe fn raw_eq(_a: &T, _b: &T) -> bool { /// that differs. That allows optimizations that can read in large chunks. /// /// [valid]: crate::ptr#safety -#[cfg_attr( - bootstrap, - rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none") -)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3395,7 +3325,6 @@ pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: u /// See documentation of [`std::hint::black_box`] for details. /// /// [`std::hint::black_box`]: crate::hint::black_box -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_black_box", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3627,11 +3556,7 @@ pub(crate) macro const_eval_select { /// # _ = foo(&5_i32); /// # _ = bar(&5_i32); /// ``` -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_is_val_statically_known", since = "1.84.0") -)] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[rustc_const_stable_indirect] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -3673,8 +3598,7 @@ pub const unsafe fn typed_swap(x: *mut T, y: *mut T) { /// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] // just for UB checks +#[rustc_intrinsic_const_stable_indirect] // just for UB checks #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { @@ -3757,8 +3681,7 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize { /// The stabilized version of this intrinsic is [`core::mem::size_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn size_of() -> usize { @@ -3775,8 +3698,7 @@ pub const fn size_of() -> usize { /// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn min_align_of() -> usize { @@ -3789,7 +3711,6 @@ pub const fn min_align_of() -> usize { /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_pref_align_of", issue = "91971"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn pref_align_of() -> usize { @@ -3807,7 +3728,6 @@ pub const unsafe fn pref_align_of() -> usize { /// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "variant_count", issue = "73662"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn variant_count() -> usize { @@ -3823,7 +3743,6 @@ pub const fn variant_count() -> usize { /// See [`crate::mem::size_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_size_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn size_of_val(_ptr: *const T) -> usize { @@ -3839,7 +3758,6 @@ pub const unsafe fn size_of_val(_ptr: *const T) -> usize { /// See [`crate::mem::align_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_align_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize { @@ -3856,7 +3774,6 @@ pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize { /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name", issue = "63084"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_name() -> &'static str { @@ -3875,7 +3792,6 @@ pub const fn type_name() -> &'static str { /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_id", issue = "77125"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_id() -> u128 { @@ -3889,8 +3805,7 @@ pub const fn type_id() -> u128 { /// change the possible layouts of pointers. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { @@ -3915,11 +3830,7 @@ impl AggregateRawPtr<*mut T> for *mut P { /// This is used to implement functions like `ptr::metadata`. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr( - bootstrap, - cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")) -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { @@ -4025,8 +3936,7 @@ pub const fn ptr_metadata + ?Sized, M>(_ptr: *cons #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4132,8 +4042,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4216,8 +4125,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4250,7 +4158,6 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { /// The stabilized version of this intrinsic is /// [`f16::min`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf16(_x: f16, _y: f16) -> f16 { @@ -4267,11 +4174,7 @@ pub const fn minnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::min`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf32(_x: f32, _y: f32) -> f32 { @@ -4288,11 +4191,7 @@ pub const fn minnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::min`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf64(_x: f64, _y: f64) -> f64 { @@ -4309,7 +4208,6 @@ pub const fn minnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::min`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf128(_x: f128, _y: f128) -> f128 { @@ -4326,7 +4224,6 @@ pub const fn minnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::max`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { @@ -4343,11 +4240,7 @@ pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::max`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { @@ -4364,11 +4257,7 @@ pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::max`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { @@ -4385,7 +4274,6 @@ pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::max`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { @@ -4397,7 +4285,6 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::abs`](../../std/primitive.f16.html#method.abs) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf16(_x: f16) -> f16 { @@ -4409,11 +4296,7 @@ pub const unsafe fn fabsf16(_x: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::abs`](../../std/primitive.f32.html#method.abs) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf32(_x: f32) -> f32 { @@ -4425,11 +4308,7 @@ pub const unsafe fn fabsf32(_x: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::abs`](../../std/primitive.f64.html#method.abs) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf64(_x: f64) -> f64 { @@ -4441,7 +4320,6 @@ pub const unsafe fn fabsf64(_x: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::abs`](../../std/primitive.f128.html#method.abs) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf128(_x: f128) -> f128 { @@ -4453,7 +4331,6 @@ pub const unsafe fn fabsf128(_x: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { @@ -4465,11 +4342,7 @@ pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { @@ -4480,11 +4353,7 @@ pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { @@ -4496,7 +4365,6 @@ pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a178d1012547..9c6781f8f419 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,9 +107,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_exact_div))] -#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))] -#![cfg_attr(bootstrap, feature(const_ub_checks))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_align_of_val)] @@ -158,8 +155,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -209,6 +204,7 @@ #![feature(simd_ffi)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(target_feature_11)] #![feature(trait_alias)] #![feature(transparent_unions)] @@ -258,7 +254,6 @@ pub mod assert_matches { } // We don't export this through #[macro_export] for now, to avoid breakage. -#[cfg(not(bootstrap))] #[unstable(feature = "autodiff", issue = "124509")] /// Unstable module containing the unstable `autodiff` macro. pub mod autodiff { diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 771c2d31b60e..ab674b58902b 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1554,7 +1554,6 @@ pub(crate) mod builtin { #[unstable(feature = "autodiff", issue = "124509")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] - #[cfg(not(bootstrap))] pub macro autodiff($item:item) { /* compiler built-in */ } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 476a8f823cb6..3c1a098374ef 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -529,7 +529,7 @@ impl MaybeUninit { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] pub const fn as_ptr(&self) -> *const T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -571,7 +571,7 @@ impl MaybeUninit { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -911,10 +911,7 @@ impl MaybeUninit { /// }; /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_assume_init", - since = "1.84.0" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.84.0")] #[inline(always)] pub const unsafe fn assume_init_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` is initialized. diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 9e1474ecd1bb..aabe8969a914 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1152,7 +1152,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_neg", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_neg(self) -> Self { @@ -1217,7 +1216,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1282,7 +1280,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { @@ -1340,7 +1337,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1405,7 +1401,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { @@ -2134,7 +2129,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2164,7 +2158,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 4278fec9f58c..995ed6eac301 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1449,7 +1449,6 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } #[doc(hidden)] #[inline(always)] #[unstable(issue = "none", feature = "std_internals")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_from_str", since = "1.82.0"))] pub const fn can_not_overflow(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { radix <= 16 && digits.len() <= mem::size_of::() * 2 - is_signed_ty as usize } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d398119624a0..dfcb13cc1e5d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1434,7 +1434,6 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1499,7 +1498,6 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { @@ -1557,7 +1555,6 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1622,7 +1619,6 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { @@ -2193,7 +2189,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2226,7 +2221,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -3091,7 +3085,6 @@ macro_rules! uint_impl { // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_pow", since = "1.50.0"))] const fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index e9bb40d0fdd1..c36d55fe2a8c 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -405,18 +405,15 @@ unsafe impl DerefPure for &mut T {} /// } /// ``` #[lang = "receiver"] -#[cfg(not(bootstrap))] #[unstable(feature = "arbitrary_self_types", issue = "44874")] pub trait Receiver { /// The target type on which the method may be called. - #[cfg(not(bootstrap))] #[rustc_diagnostic_item = "receiver_target"] #[lang = "receiver_target"] #[unstable(feature = "arbitrary_self_types", issue = "44874")] type Target: ?Sized; } -#[cfg(not(bootstrap))] #[unstable(feature = "arbitrary_self_types", issue = "44874")] impl Receiver for P where @@ -433,8 +430,7 @@ where /// facility based around the current "arbitrary self types" unstable feature. /// That new facility will use the replacement trait above called `Receiver` /// which is why this is now named `LegacyReceiver`. -#[cfg_attr(bootstrap, lang = "receiver")] -#[cfg_attr(not(bootstrap), lang = "legacy_receiver")] +#[lang = "legacy_receiver"] #[unstable(feature = "legacy_receiver_trait", issue = "none")] #[doc(hidden)] pub trait LegacyReceiver { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index cea1f84f3fd6..40526f9583e6 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -171,7 +171,6 @@ pub use self::deref::DerefPure; #[unstable(feature = "legacy_receiver_trait", issue = "none")] pub use self::deref::LegacyReceiver; #[unstable(feature = "arbitrary_self_types", issue = "44874")] -#[cfg(not(bootstrap))] pub use self::deref::Receiver; #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a12fb6a827e7..f4ac7af63961 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -563,7 +563,7 @@ use crate::pin::Pin; use crate::{cmp, convert, hint, mem, slice}; /// The `Option` type. See [the module level documentation](self) for more. -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[derive(Copy, Eq, Debug, Hash)] #[rustc_diagnostic_item = "Option"] #[lang = "Option"] diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 1e61cfd804c2..5fa340a6147f 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -208,14 +208,13 @@ pub macro const_panic { #[rustc_allow_const_fn_unstable(const_eval_select)] #[inline(always)] // inline the wrapper #[track_caller] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "1.84.0"))] const fn do_panic($($arg: $ty),*) -> ! { $crate::intrinsics::const_eval_select!( @capture { $($arg: $ty = $arg),* } -> !: #[noinline] if const #[track_caller] #[inline] { // Inline this, to prevent codegen $crate::panic!($const_msg) - } else #[track_caller] #[cfg_attr(bootstrap, inline)] { // Do not inline this, it makes perf worse + } else #[track_caller] { // Do not inline this, it makes perf worse $crate::panic!($runtime_msg) } ) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index f603eb2971f6..53e2b238bae6 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -51,8 +51,7 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C #[track_caller] #[lang = "panic_fmt"] // needed for const-evaluated panics #[rustc_do_not_const_check] // hooked by const-eval -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() @@ -86,8 +85,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, // which causes a "panic in a function that cannot unwind". #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { const_eval_select!( @@ -130,8 +128,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = "panic"] // used by lints and miri for panics pub const fn panic(expr: &'static str) -> ! { // Use Arguments::new_const instead of format_args!("{expr}") to potentially @@ -169,8 +166,7 @@ macro_rules! panic_const { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable + #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = stringify!($lang)] pub const fn $lang() -> ! { // Use Arguments::new_const instead of format_args!("{expr}") to potentially @@ -217,8 +213,7 @@ panic_const! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_nounwind(expr: &'static str) -> ! { panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false); } @@ -234,8 +229,7 @@ pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! { #[track_caller] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_explicit() -> ! { panic_display(&"explicit panic"); } @@ -252,8 +246,7 @@ pub fn unreachable_display(x: &T) -> ! { #[inline] #[track_caller] #[rustc_diagnostic_item = "panic_str_2015"] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_str_2015(expr: &str) -> ! { panic_display(&expr); } @@ -263,8 +256,7 @@ pub const fn panic_str_2015(expr: &str) -> ! { #[rustc_do_not_const_check] // hooked by const-eval // enforce a &&str argument in const-check and hook this by const-eval #[rustc_const_panic_str] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_display(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); } @@ -333,8 +325,7 @@ fn panic_in_cleanup() -> ! { /// This function is used instead of panic_fmt in const eval. #[lang = "const_panic_fmt"] // needed by const-eval machine to replace calls to `panic_fmt` lang item -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if let Some(msg) = fmt.as_str() { // The panic_display function is hooked by const eval. diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 2538d60a8eee..74a1d40f4e73 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -41,7 +41,6 @@ impl Alignment { /// This provides the same numerical value as [`mem::align_of`], /// but in an `Alignment` instead of a `usize`. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn of() -> Self { // SAFETY: rustc ensures that type alignment is always a power of two. @@ -53,7 +52,6 @@ impl Alignment { /// /// Note that `0` is not a power of two, nor a valid alignment. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn new(align: usize) -> Option { if align.is_power_of_two() { @@ -73,7 +71,6 @@ impl Alignment { /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`. /// It must *not* be zero. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { assert_unsafe_precondition!( @@ -89,7 +86,6 @@ impl Alignment { /// Returns the alignment as a [`usize`]. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn as_usize(self) -> usize { self.0 as usize @@ -97,7 +93,6 @@ impl Alignment { /// Returns the alignment as a [NonZero]<[usize]>. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn as_nonzero(self) -> NonZero { // SAFETY: All the discriminants are non-zero. @@ -118,7 +113,6 @@ impl Alignment { /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn log2(self) -> u32 { self.as_nonzero().trailing_zeros() @@ -148,7 +142,6 @@ impl Alignment { /// assert_ne!(one.mask(Alignment::of::().mask()), one); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn mask(self) -> usize { // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index dfe905544af9..78d9a1b04c84 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -113,7 +113,6 @@ impl *const T { /// println!("{:?}", unsafe { &*bad }); /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *const U @@ -1018,7 +1017,6 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 5f20cb2ee720..ae9810e558aa 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -92,7 +92,6 @@ pub trait Thin = Pointee; /// /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { ptr_metadata(ptr) @@ -106,7 +105,6 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn from_raw_parts( data_pointer: *const impl Thin, @@ -120,7 +118,6 @@ pub const fn from_raw_parts( /// /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn from_raw_parts_mut( data_pointer: *mut impl Thin, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 5ed0b39f33b7..0a8279142452 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -94,7 +94,6 @@ impl *mut T { /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. /// println!("{:?}", unsafe { &*bad }); #[unstable(feature = "set_ptr_value", issue = "75091")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *mut U @@ -1097,7 +1096,6 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0fb5880fd1a0..d37b7eedfcbd 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -629,7 +629,6 @@ impl NonNull { #[must_use = "returns a new pointer rather than modifying its argument"] #[stable(feature = "non_null_convenience", since = "1.80.0")] #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] pub const unsafe fn sub(self, count: usize) -> Self where T: Sized, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b450123c5aa9..9c7be618bc77 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -520,7 +520,7 @@ use crate::{convert, fmt, hint}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// /// See the [module documentation](self) for details. -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[rustc_diagnostic_item = "Result"] diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 339adad1b17b..98db7aaf5332 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -16,7 +16,6 @@ const USIZE_BYTES: usize = mem::size_of::(); /// bytes where the borrow propagated all the way to the most significant /// bit." #[inline] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn contains_zero_byte(x: usize) -> bool { x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 } @@ -24,7 +23,6 @@ const fn contains_zero_byte(x: usize) -> bool { /// Returns the first index matching the byte `x` in `text`. #[inline] #[must_use] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] pub const fn memchr(x: u8, text: &[u8]) -> Option { // Fast path for small slices. if text.len() < 2 * USIZE_BYTES { @@ -35,7 +33,6 @@ pub const fn memchr(x: u8, text: &[u8]) -> Option { } #[inline] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn memchr_naive(x: u8, text: &[u8]) -> Option { let mut i = 0; @@ -52,7 +49,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option { } #[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn memchr_aligned(x: u8, text: &[u8]) -> Option { // The runtime version behaves the same as the compiletime version, it's // just more optimized. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b3defba5a982..498e4ea286c3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -735,7 +735,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] #[must_use] pub const fn as_ptr(&self) -> *const T { @@ -766,7 +766,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] #[must_use] pub const fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 189ab39e976f..8a473b398bb5 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -373,7 +373,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[must_use] #[inline(always)] pub const fn as_ptr(&self) -> *const u8 { @@ -391,7 +391,7 @@ impl str { #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[must_use] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut u8 { diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 34673707f010..41e9c593ebdb 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -319,7 +319,6 @@ impl<'a> ContextBuilder<'a> { /// Creates a ContextBuilder from a Waker. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))] pub const fn from_waker(waker: &'a Waker) -> Self { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; @@ -373,7 +372,6 @@ impl<'a> ContextBuilder<'a> { /// Builds the `Context`. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 3e6110c9c88a..b289f6026ffc 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -47,7 +47,6 @@ use crate::intrinsics::{self, const_eval_select}; /// order to call it. Since the precompiled standard library is built with full debuginfo and these /// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough /// debuginfo to have a measurable compile-time impact on debug builds. -#[cfg_attr(bootstrap, allow_internal_unstable(const_ub_checks))] // permit this to be called in stably-const fn #[macro_export] #[unstable(feature = "ub_checks", issue = "none")] macro_rules! assert_unsafe_precondition { @@ -89,7 +88,6 @@ pub use intrinsics::ub_checks as check_library_ub; /// /// The intention is to not do that when running in the interpreter, as that one has its own /// language UB checks which generally produce better errors. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] pub(crate) const fn check_language_ub() -> bool { diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 7f4826402eb5..4655d35e9c43 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1,7 +1,6 @@ ///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! #[inline(always)] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] const fn bitset_search< const N: usize, const CHUNK_SIZE: usize, @@ -424,7 +423,6 @@ pub mod lowercase { (5, 187), (6, 78), (7, 132), ]; - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] pub const fn lookup(c: char) -> bool { super::bitset_search( c as u32, @@ -549,7 +547,6 @@ pub mod uppercase { (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), ]; - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] pub const fn lookup(c: char) -> bool { super::bitset_search( c as u32, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index f7825571cd7a..40129619ce50 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,7 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_three_way_compare))] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] @@ -83,6 +80,7 @@ #![feature(step_trait)] #![feature(str_internals)] #![feature(strict_provenance_atomic_ptr)] +#![feature(strict_provenance_lints)] #![feature(test)] #![feature(trait_upcasting)] #![feature(trusted_len)] diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 6d1f9764efbf..252f118fecfb 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -23,7 +23,4 @@ libc = { version = "0.2", default-features = false } [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [ - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', -] +check-cfg = [] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index c1ab70b714a4..260732dee188 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -144,6 +144,4 @@ check-cfg = [ # and to the `backtrace` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg 'cfg(feature, values(any()))', - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', ] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index cf99a618e552..70a2e7fdb787 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -262,7 +262,6 @@ #![allow(unused_features)] // // Features: -#![cfg_attr(not(bootstrap), feature(autodiff))] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), @@ -274,13 +273,12 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(asm_experimental_arch)] +#![feature(autodiff)] #![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] @@ -314,6 +312,7 @@ #![feature(rustdoc_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(thread_local)] #![feature(try_blocks)] #![feature(type_alias_impl_trait)] @@ -622,7 +621,6 @@ pub mod simd { #[doc(inline)] pub use crate::std_float::StdFloat; } -#[cfg(not(bootstrap))] #[unstable(feature = "autodiff", issue = "124509")] /// This module provides support for automatic differentiation. pub mod autodiff { diff --git a/library/std/src/sys/sync/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs index 2a67ed766aa0..88ce39305e1a 100644 --- a/library/std/src/sys/sync/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -5,7 +5,6 @@ pub struct Condvar {} impl Condvar { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> Condvar { Condvar {} } diff --git a/library/std/src/sys/sync/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs index 7b243575e018..57c78f454c57 100644 --- a/library/std/src/sys/sync/mutex/no_threads.rs +++ b/library/std/src/sys/sync/mutex/no_threads.rs @@ -10,7 +10,6 @@ unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> Mutex { Mutex { locked: Cell::new(false) } } diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index fb1b496510ab..88a1d50361ee 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -35,7 +35,6 @@ unsafe impl Sync for Once {} impl Once { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))] pub const fn new() -> Once { Once { state: Cell::new(State::Incomplete) } } diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index 87837915b396..5beff4ce6836 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -116,7 +116,6 @@ fn to_state(current: StateAndQueue) -> usize { impl Once { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))] pub const fn new() -> Once { Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) } } diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index c11e59f719e9..573d0d602dbd 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -10,7 +10,6 @@ unsafe impl Sync for RwLock {} // no threads on this platform impl RwLock { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> RwLock { RwLock { mode: Cell::new(0) } } diff --git a/library/std/src/sys/thread_local/key/racy.rs b/library/std/src/sys/thread_local/key/racy.rs index 97df8997b80d..e1bc08eabb35 100644 --- a/library/std/src/sys/thread_local/key/racy.rs +++ b/library/std/src/sys/thread_local/key/racy.rs @@ -30,7 +30,6 @@ const KEY_SENTVAL: usize = 0; const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; impl LazyKey { - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const fn new(dtor: Option) -> LazyKey { LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } } diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 58f291ffdb98..00d2e30bd603 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -60,7 +60,6 @@ struct Value { } impl Storage { - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const fn new() -> Storage { Storage { key: LazyKey::new(Some(destroy_value::)), marker: PhantomData } } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 9edb3fa41933..5c5d694f83d9 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -237,7 +237,6 @@ impl LocalKey { reason = "recently added to create a key", issue = "none" )] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const unsafe fn new(inner: fn(Option<&mut Option>) -> *const T) -> LocalKey { LocalKey { inner } } diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 569a1b3299e5..96ddae16f0ab 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -37,7 +37,4 @@ system-llvm-libunwind = [] [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [ - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', -] +check-cfg = [] diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 14da876eda77..9a51979a2f0d 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -1,5 +1,4 @@ #[inline(always)] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] const fn bitset_search< const N: usize, const CHUNK_SIZE: usize, diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index dd064c592839..46010692fe56 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -97,10 +97,6 @@ impl RawEmitter { self.blank_line(); - writeln!( - &mut self.file, - r#"#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]"# - ).unwrap(); writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap(); if first_code_point > 0x7f { writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} &&").unwrap(); From f94142b366f9bc57c15e9ac274f83d0f9c03ffac Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 24 Nov 2024 17:37:25 -0800 Subject: [PATCH 122/330] Update tests to use new proc-macro header --- .../auxiliary/macro_def.rs | 4 - .../mir_inlined_twice_var_locs.rs | 2 +- .../auxiliary/incremental_proc_macro_aux.rs | 5 - .../auxiliary/issue-49482-macro-def.rs | 4 - .../auxiliary/issue-49482-reexport.rs | 1 + tests/incremental/auxiliary/issue-54059.rs | 4 - tests/incremental/incremental_proc_macro.rs | 2 +- .../auxiliary/egui_inspect_derive.rs | 4 - .../issue-110457-same-span-closures/main.rs | 2 +- tests/incremental/issue-49482.rs | 1 - tests/incremental/issue-54059.rs | 2 +- .../auxiliary/invalid-span-helper-lib.rs | 1 + .../auxiliary/respan.rs | 5 - .../invalid_span_main.rs | 1 - tests/pretty/attr-derive.rs | 2 +- tests/pretty/auxiliary/derive-foo.rs | 5 - .../annotate-snippet/auxiliary/multispan.rs | 4 - tests/ui/annotate-snippet/multispan.rs | 2 +- .../issues/auxiliary/issue-60674.rs | 4 - tests/ui/async-await/issues/issue-60674.rs | 2 +- .../auxiliary/key-value-expansion.rs | 5 - tests/ui/attributes/key-value-expansion.rs | 2 +- .../main-removed-2/auxiliary/tokyo.rs | 5 - tests/ui/attributes/main-removed-2/main.rs | 2 +- tests/ui/autodiff/auxiliary/my_macro.rs | 4 - tests/ui/autodiff/visibility.rs | 2 +- .../assume-incomplete.rs | 2 +- .../auxiliary/ver-cfg-rel.rs | 5 - .../ui/crate-loading/auxiliary/proc-macro.rs | 3 - .../cross-compiled-proc-macro.rs | 2 +- .../derives/auxiliary/derive-marker-tricky.rs | 5 - tests/ui/derives/derive-marker-tricky.rs | 2 +- .../deriving/auxiliary/another-proc-macro.rs | 4 - .../ui/deriving/built-in-proc-macro-scope.rs | 2 +- .../deriving/built-in-proc-macro-scope.stdout | 2 +- .../deriving/proc-macro-attribute-mixing.rs | 2 +- .../proc-macro-attribute-mixing.stdout | 2 +- .../auxiliary/proc-macro-helper.rs | 4 - .../existing_proc_macros.rs | 2 +- .../fmt/auxiliary/format-string-proc-macro.rs | 5 - ...mat-args-capture-first-literal-is-macro.rs | 2 +- ...at-args-capture-from-pm-first-arg-macro.rs | 2 +- .../fmt/format-args-capture-issue-106408.rs | 2 +- .../fmt/format-args-capture-macro-hygiene.rs | 2 +- tests/ui/fmt/format-expanded-string.rs | 2 +- tests/ui/fmt/indoc-issue-106408.rs | 2 +- .../ui/fmt/respanned-literal-issue-106191.rs | 2 +- .../hygiene/auxiliary/def-site-async-await.rs | 3 +- tests/ui/hygiene/auxiliary/opaque-hygiene.rs | 4 - .../issue-77523-def-site-async-await.rs | 1 - .../precise-capturing/auxiliary/no-use-pm.rs | 5 - .../precise-capturing/external-macro.rs | 2 +- .../auxiliary/repeat.rs | 5 - .../no-overlap.rs | 2 +- .../inherent-impls-overlap-check/overlap.rs | 2 +- .../ui/lifetimes/auxiliary/issue-91763-aux.rs | 5 - tests/ui/lifetimes/issue-91763.rs | 2 +- tests/ui/lint/auxiliary/add-impl.rs | 5 - .../redundant-semi-proc-macro-def.rs | 3 - .../redundant-semi-proc-macro.rs | 2 +- .../redundant-semi-proc-macro.stderr | 2 +- .../auxiliary/forge_unsafe_block.rs | 5 - .../ui/lint/unsafe_code/forge_unsafe_block.rs | 2 +- ...nused-qualification-in-derive-expansion.rs | 2 +- tests/ui/macros/auxiliary/hello_macro.rs | 4 - tests/ui/macros/auxiliary/issue-100199.rs | 4 - tests/ui/macros/auxiliary/proc_macro_def.rs | 4 - .../macros/auxiliary/proc_macro_sequence.rs | 4 - tests/ui/macros/issue-100199.rs | 2 +- tests/ui/macros/macro-quote-test.rs | 2 +- tests/ui/macros/proc_macro.rs | 2 +- tests/ui/macros/same-sequence-span.rs | 2 +- tests/ui/macros/same-sequence-span.stderr | 4 +- ...971-outer-attr-following-inner-attr-ice.rs | 5 - ...971-outer-attr-following-inner-attr-ice.rs | 2 +- tests/ui/proc-macro/add-impl.rs | 2 +- tests/ui/proc-macro/allowed-attr-stmt-expr.rs | 4 +- .../ambiguous-builtin-attrs-test.rs | 2 +- .../ui/proc-macro/ambiguous-builtin-attrs.rs | 2 +- tests/ui/proc-macro/amputate-span.fixed | 2 +- tests/ui/proc-macro/amputate-span.rs | 2 +- tests/ui/proc-macro/append-impl.rs | 2 +- tests/ui/proc-macro/attr-args.rs | 2 +- tests/ui/proc-macro/attr-cfg.rs | 2 +- tests/ui/proc-macro/attr-complex-fn.rs | 2 +- tests/ui/proc-macro/attr-invalid-exprs.rs | 2 +- tests/ui/proc-macro/attr-on-trait.rs | 2 +- tests/ui/proc-macro/attr-stmt-expr-rpass.rs | 2 +- tests/ui/proc-macro/attr-stmt-expr.rs | 4 +- tests/ui/proc-macro/attribute-after-derive.rs | 2 +- .../proc-macro/attribute-spans-preserved.rs | 2 +- tests/ui/proc-macro/attribute-with-error.rs | 2 +- tests/ui/proc-macro/attributes-included.rs | 2 +- .../proc-macro/attributes-on-definitions.rs | 2 +- .../proc-macro/attributes-on-modules-fail.rs | 2 +- tests/ui/proc-macro/attributes-on-modules.rs | 2 +- tests/ui/proc-macro/auxiliary/add-impl.rs | 5 - .../ui/proc-macro/auxiliary/amputate-span.rs | 5 - .../api/{mod.rs => proc_macro_api_tests.rs} | 4 - tests/ui/proc-macro/auxiliary/append-impl.rs | 5 - .../proc-macro/auxiliary/assert-span-pos.rs | 4 - tests/ui/proc-macro/auxiliary/attr-args.rs | 5 - tests/ui/proc-macro/auxiliary/attr-cfg.rs | 5 - .../ui/proc-macro/auxiliary/attr-on-trait.rs | 5 - .../auxiliary/attr-stmt-expr-rpass.rs | 5 - .../ui/proc-macro/auxiliary/attr-stmt-expr.rs | 5 - .../auxiliary/attribute-spans-preserved.rs | 5 - .../auxiliary/attributes-included.rs | 5 - .../auxiliary/attributes-on-definitions.rs | 5 - tests/ui/proc-macro/auxiliary/bang-macro.rs | 5 - .../proc-macro/auxiliary/bang_proc_macro2.rs | 5 - .../ui/proc-macro/auxiliary/builtin-attrs.rs | 5 - .../proc-macro/auxiliary/call-deprecated.rs | 5 - tests/ui/proc-macro/auxiliary/call-site.rs | 5 - tests/ui/proc-macro/auxiliary/cond_plugin.rs | 4 - .../auxiliary/count_compound_ops.rs | 4 - .../auxiliary/custom-attr-only-one-derive.rs | 5 - tests/ui/proc-macro/auxiliary/custom-quote.rs | 3 - tests/ui/proc-macro/auxiliary/derive-a.rs | 5 - tests/ui/proc-macro/auxiliary/derive-atob.rs | 5 - .../proc-macro/auxiliary/derive-attr-cfg.rs | 5 - .../ui/proc-macro/auxiliary/derive-b-rpass.rs | 5 - tests/ui/proc-macro/auxiliary/derive-b.rs | 5 - tests/ui/proc-macro/auxiliary/derive-bad.rs | 5 - tests/ui/proc-macro/auxiliary/derive-clona.rs | 5 - tests/ui/proc-macro/auxiliary/derive-ctod.rs | 5 - tests/ui/proc-macro/auxiliary/derive-foo.rs | 5 - .../auxiliary/derive-helper-shadowing-2.rs | 5 - .../auxiliary/derive-helper-shadowing.rs | 5 - .../ui/proc-macro/auxiliary/derive-nothing.rs | 5 - .../auxiliary/derive-same-struct.rs | 5 - .../proc-macro/auxiliary/derive-two-attrs.rs | 5 - tests/ui/proc-macro/auxiliary/derive-union.rs | 5 - .../proc-macro/auxiliary/derive-unstable-2.rs | 5 - .../proc-macro/auxiliary/derive-unstable.rs | 5 - tests/ui/proc-macro/auxiliary/double.rs | 5 - tests/ui/proc-macro/auxiliary/duplicate.rs | 4 - .../edition-gated-async-move-syntax.rs | 5 - .../auxiliary/edition-imports-2015.rs | 4 - tests/ui/proc-macro/auxiliary/empty-crate.rs | 4 - tests/ui/proc-macro/auxiliary/env.rs | 4 - tests/ui/proc-macro/auxiliary/expand-expr.rs | 4 - .../auxiliary/expand-with-a-macro.rs | 4 - tests/ui/proc-macro/auxiliary/first-second.rs | 5 - .../auxiliary/gen-lifetime-token.rs | 5 - .../auxiliary/gen-macro-rules-hygiene.rs | 5 - .../proc-macro/auxiliary/gen-macro-rules.rs | 5 - .../auxiliary/generate-dollar-ident.rs | 4 - tests/ui/proc-macro/auxiliary/generate-mod.rs | 4 - tests/ui/proc-macro/auxiliary/helper-attr.rs | 5 - .../proc-macro/auxiliary/hygiene_example.rs | 2 + .../auxiliary/hygiene_example_codegen.rs | 4 - .../auxiliary/invalid-punct-ident.rs | 4 - tests/ui/proc-macro/auxiliary/is-available.rs | 5 - tests/ui/proc-macro/auxiliary/issue-104884.rs | 5 - tests/ui/proc-macro/auxiliary/issue-107113.rs | 5 - tests/ui/proc-macro/auxiliary/issue-118809.rs | 5 - tests/ui/proc-macro/auxiliary/issue-38586.rs | 5 - tests/ui/proc-macro/auxiliary/issue-39889.rs | 5 - tests/ui/proc-macro/auxiliary/issue-42708.rs | 5 - tests/ui/proc-macro/auxiliary/issue-50061.rs | 5 - tests/ui/proc-macro/auxiliary/issue-50493.rs | 5 - tests/ui/proc-macro/auxiliary/issue-59191.rs | 4 - tests/ui/proc-macro/auxiliary/issue-66286.rs | 5 - tests/ui/proc-macro/auxiliary/issue-75801.rs | 5 - tests/ui/proc-macro/auxiliary/issue-79242.rs | 5 - tests/ui/proc-macro/auxiliary/issue-79825.rs | 4 - tests/ui/proc-macro/auxiliary/issue-83510.rs | 5 - .../proc-macro/auxiliary/issue-91800-macro.rs | 5 - .../proc-macro/auxiliary/lifetimes-rpass.rs | 5 - tests/ui/proc-macro/auxiliary/lifetimes.rs | 5 - .../proc-macro/auxiliary/macro-only-syntax.rs | 4 - .../auxiliary/macro_rules_edition_pm.rs | 5 - tests/ui/proc-macro/auxiliary/meta-macro.rs | 3 - .../proc-macro/auxiliary/mixed-site-span.rs | 5 - tests/ui/proc-macro/auxiliary/modify-ast.rs | 5 - .../proc-macro/auxiliary/multiple-derives.rs | 5 - tests/ui/proc-macro/auxiliary/multispan.rs | 4 - .../ui/proc-macro/auxiliary/negative-token.rs | 5 - .../auxiliary/nonterminal-recollect-attr.rs | 4 - tests/ui/proc-macro/auxiliary/not-joint.rs | 5 - .../auxiliary/parent-source-spans.rs | 4 - .../parse-invis-delim-issue-128895.rs | 5 - tests/ui/proc-macro/auxiliary/print-tokens.rs | 4 - .../proc-macro/auxiliary/proc-macro-panic.rs | 5 - tests/ui/proc-macro/auxiliary/raw-ident.rs | 5 - tests/ui/proc-macro/auxiliary/re-export.rs | 5 - tests/ui/proc-macro/auxiliary/recollect.rs | 5 - .../auxiliary/resolved-located-at.rs | 4 - .../ui/proc-macro/auxiliary/span-api-tests.rs | 4 - .../auxiliary/span-from-proc-macro.rs | 4 - tests/ui/proc-macro/auxiliary/subspan.rs | 4 - tests/ui/proc-macro/auxiliary/test-macros.rs | 5 - tests/ui/proc-macro/auxiliary/three-equals.rs | 4 - .../ui/proc-macro/auxiliary/weird-hygiene.rs | 5 - tests/ui/proc-macro/bang-macro.rs | 2 +- tests/ui/proc-macro/break-token-spans.rs | 2 +- tests/ui/proc-macro/call-deprecated.rs | 2 +- tests/ui/proc-macro/call-site.rs | 2 +- .../proc-macro/capture-macro-rules-invoke.rs | 2 +- tests/ui/proc-macro/capture-unglued-token.rs | 2 +- tests/ui/proc-macro/cfg-eval-inner.rs | 2 +- tests/ui/proc-macro/cfg-eval.rs | 2 +- tests/ui/proc-macro/count_compound_ops.rs | 2 +- tests/ui/proc-macro/crate-attrs-multiple.rs | 2 +- tests/ui/proc-macro/crate-var.rs | 2 +- .../proc-macro/custom-attr-only-one-derive.rs | 2 +- tests/ui/proc-macro/custom-attr-panic.rs | 2 +- .../debug/auxiliary/macro-dump-debug.rs | 4 - .../proc-macro/debug/dump-debug-span-debug.rs | 2 +- tests/ui/proc-macro/debug/dump-debug.rs | 2 +- tests/ui/proc-macro/debug/dump-debug.stderr | 60 +++--- tests/ui/proc-macro/derive-attr-cfg.rs | 2 +- tests/ui/proc-macro/derive-b.rs | 2 +- tests/ui/proc-macro/derive-bad.rs | 2 +- tests/ui/proc-macro/derive-expand-order.rs | 2 +- .../ui/proc-macro/derive-helper-configured.rs | 2 +- .../proc-macro/derive-helper-legacy-limits.rs | 2 +- .../derive-helper-legacy-spurious.rs | 2 +- tests/ui/proc-macro/derive-helper-shadowed.rs | 2 +- .../proc-macro/derive-helper-shadowing-2.rs | 2 +- .../ui/proc-macro/derive-helper-shadowing.rs | 4 +- .../ui/proc-macro/derive-helper-vs-legacy.rs | 2 +- tests/ui/proc-macro/derive-in-mod.rs | 2 +- tests/ui/proc-macro/derive-same-struct.rs | 2 +- tests/ui/proc-macro/derive-still-gated.rs | 2 +- tests/ui/proc-macro/derive-two-attrs.rs | 2 +- tests/ui/proc-macro/derive-union.rs | 2 +- .../ui/proc-macro/disappearing-resolution.rs | 2 +- .../proc-macro/disappearing-resolution.stderr | 2 +- tests/ui/proc-macro/doc-comment-preserved.rs | 2 +- .../proc-macro/dollar-crate-issue-101211.rs | 2 +- .../ui/proc-macro/dollar-crate-issue-57089.rs | 2 +- .../ui/proc-macro/dollar-crate-issue-62325.rs | 2 +- tests/ui/proc-macro/dollar-crate.rs | 2 +- ...tion-gated-async-move-syntax-issue89699.rs | 2 +- tests/ui/proc-macro/edition-imports-2018.rs | 2 +- tests/ui/proc-macro/empty-crate.rs | 2 +- tests/ui/proc-macro/empty-where-clause.rs | 2 +- tests/ui/proc-macro/env.rs | 2 +- tests/ui/proc-macro/expand-expr.rs | 2 +- tests/ui/proc-macro/expand-to-derive.rs | 2 +- tests/ui/proc-macro/expand-to-unstable.rs | 2 +- tests/ui/proc-macro/expand-with-a-macro.rs | 2 +- .../expr-stmt-nonterminal-tokens.rs | 2 +- .../expr-stmt-nonterminal-tokens.stdout | 196 +++++++++--------- tests/ui/proc-macro/gen-lifetime-token.rs | 2 +- .../ui/proc-macro/gen-macro-rules-hygiene.rs | 2 +- tests/ui/proc-macro/gen-macro-rules.rs | 2 +- tests/ui/proc-macro/generate-dollar-ident.rs | 2 +- tests/ui/proc-macro/generate-mod.rs | 2 +- .../helper-attr-blocked-by-import-ambig.rs | 2 +- .../helper-attr-blocked-by-import.rs | 2 +- .../proc-macro/helper-attr-builtin-derive.rs | 2 +- tests/ui/proc-macro/hygiene_example.rs | 1 - tests/ui/proc-macro/import.rs | 2 +- tests/ui/proc-macro/inert-attribute-order.rs | 2 +- .../proc-macro/inner-attr-non-inline-mod.rs | 2 +- tests/ui/proc-macro/inner-attrs.rs | 2 +- tests/ui/proc-macro/input-interpolated.rs | 2 +- tests/ui/proc-macro/input-interpolated.stdout | 22 +- tests/ui/proc-macro/invalid-punct-ident-1.rs | 2 +- tests/ui/proc-macro/invalid-punct-ident-2.rs | 2 +- tests/ui/proc-macro/invalid-punct-ident-3.rs | 2 +- tests/ui/proc-macro/invalid-punct-ident-4.rs | 2 +- tests/ui/proc-macro/is-available.rs | 2 +- .../issue-104884-trait-impl-sugg-err.rs | 2 +- tests/ui/proc-macro/issue-107113-wrap.rs | 2 +- tests/ui/proc-macro/issue-118809.rs | 2 +- tests/ui/proc-macro/issue-36935.rs | 2 +- tests/ui/proc-macro/issue-37788.rs | 2 +- tests/ui/proc-macro/issue-38586.rs | 2 +- tests/ui/proc-macro/issue-39889.rs | 2 +- tests/ui/proc-macro/issue-42708.rs | 2 +- tests/ui/proc-macro/issue-50061.rs | 2 +- tests/ui/proc-macro/issue-50493.rs | 2 +- tests/ui/proc-macro/issue-53481.rs | 2 +- .../issue-59191-replace-root-with-fn.rs | 2 +- tests/ui/proc-macro/issue-66286.rs | 2 +- .../issue-73933-procedural-masquerade.rs | 2 +- .../issue-73933-procedural-masquerade.stdout | 8 +- tests/ui/proc-macro/issue-75734-pp-paren.rs | 2 +- tests/ui/proc-macro/issue-75801.rs | 2 +- tests/ui/proc-macro/issue-75930-derive-cfg.rs | 2 +- .../issue-76182-leading-vert-pat.rs | 2 +- .../issue-76270-panic-in-libproc-macro.rs | 2 +- .../issue-78675-captured-inner-attrs.rs | 2 +- tests/ui/proc-macro/issue-79148.rs | 2 +- .../issue-79242-slow-retokenize-check.rs | 2 +- tests/ui/proc-macro/issue-79825.rs | 2 +- tests/ui/proc-macro/issue-80760-empty-stmt.rs | 2 +- tests/ui/proc-macro/issue-81007-item-attrs.rs | 2 +- .../proc-macro/issue-81543-item-parse-err.rs | 2 +- tests/ui/proc-macro/issue-81555.rs | 2 +- tests/ui/proc-macro/issue-83510.rs | 2 +- .../issue-86781-bad-inner-doc.fixed | 2 +- .../proc-macro/issue-86781-bad-inner-doc.rs | 2 +- tests/ui/proc-macro/issue-91800.rs | 2 +- tests/ui/proc-macro/item-error.rs | 2 +- tests/ui/proc-macro/keep-expr-tokens.rs | 2 +- tests/ui/proc-macro/lifetimes-rpass.rs | 2 +- tests/ui/proc-macro/lifetimes.rs | 2 +- tests/ui/proc-macro/lints_in_proc_macros.rs | 2 +- tests/ui/proc-macro/literal-to-string.rs | 2 +- tests/ui/proc-macro/literal-to-string.stdout | 30 +-- tests/ui/proc-macro/load-panic-backtrace.rs | 2 +- .../ui/proc-macro/load-panic-backtrace.stderr | 2 +- tests/ui/proc-macro/load-panic.rs | 2 +- tests/ui/proc-macro/load-two.rs | 4 +- tests/ui/proc-macro/macro-brackets.rs | 2 +- .../proc-macro/macro-crate-multi-decorator.rs | 2 +- tests/ui/proc-macro/macro-quote-cond.rs | 2 +- tests/ui/proc-macro/macro-rules-derive-cfg.rs | 2 +- tests/ui/proc-macro/macro-rules-derive.rs | 2 +- tests/ui/proc-macro/macro-use-attr.rs | 2 +- tests/ui/proc-macro/macro-use-bang.rs | 2 +- .../proc-macro/macro_rules_edition_from_pm.rs | 2 +- tests/ui/proc-macro/macros-in-extern.rs | 2 +- tests/ui/proc-macro/macros-in-type.rs | 2 +- tests/ui/proc-macro/meta-macro-hygiene.rs | 2 +- tests/ui/proc-macro/meta-macro-hygiene.stdout | 2 +- tests/ui/proc-macro/meta-macro.rs | 2 +- tests/ui/proc-macro/mixed-site-span.rs | 2 +- tests/ui/proc-macro/modify-ast.rs | 2 +- tests/ui/proc-macro/multispan.rs | 2 +- tests/ui/proc-macro/negative-token.rs | 2 +- tests/ui/proc-macro/nested-derive-cfg.rs | 2 +- tests/ui/proc-macro/nested-item-spans.rs | 2 +- tests/ui/proc-macro/nested-macro-rules.rs | 2 +- .../proc-macro/nested-nonterminal-tokens.rs | 2 +- tests/ui/proc-macro/no-macro-use-attr.rs | 2 +- tests/ui/proc-macro/nodelim-groups.rs | 2 +- tests/ui/proc-macro/nonterminal-expansion.rs | 2 +- .../proc-macro/nonterminal-recollect-attr.rs | 2 +- .../proc-macro/nonterminal-token-hygiene.rs | 2 +- .../nonterminal-token-hygiene.stdout | 2 +- tests/ui/proc-macro/not-joint.rs | 2 +- tests/ui/proc-macro/out-of-line-mod.rs | 2 +- tests/ui/proc-macro/parent-source-spans.rs | 2 +- .../parse-invis-delim-issue-128895.rs | 2 +- tests/ui/proc-macro/pretty-print-hack-hide.rs | 2 +- tests/ui/proc-macro/pretty-print-hack-show.rs | 2 +- tests/ui/proc-macro/pretty-print-tts.rs | 2 +- tests/ui/proc-macro/proc-macro-attributes.rs | 2 +- tests/ui/proc-macro/proc-macro-gates.rs | 2 +- tests/ui/proc-macro/proc-macro-gates2.rs | 2 +- tests/ui/proc-macro/raw-ident.rs | 2 +- tests/ui/proc-macro/resolve-error.rs | 6 +- tests/ui/proc-macro/resolve-error.stderr | 12 +- tests/ui/proc-macro/resolved-located-at.rs | 2 +- tests/ui/proc-macro/shadow.rs | 2 +- tests/ui/proc-macro/smoke.rs | 2 +- .../proc-macro/span-absolute-posititions.rs | 2 +- tests/ui/proc-macro/span-api-tests.rs | 2 +- tests/ui/proc-macro/span-from-proc-macro.rs | 4 +- .../ui/proc-macro/span-from-proc-macro.stderr | 8 +- tests/ui/proc-macro/span-preservation.rs | 2 +- tests/ui/proc-macro/struct-field-macro.rs | 2 +- tests/ui/proc-macro/subspan.rs | 2 +- tests/ui/proc-macro/test.rs | 2 +- tests/ui/proc-macro/three-equals.rs | 2 +- tests/ui/proc-macro/trailing-plus.rs | 2 +- tests/ui/proc-macro/trait-fn-args-2015.rs | 2 +- tests/ui/proc-macro/unsafe-foreign-mod.rs | 2 +- tests/ui/proc-macro/unsafe-mod.rs | 2 +- tests/ui/proc-macro/weird-braces.rs | 2 +- tests/ui/proc-macro/weird-hygiene.rs | 2 +- .../ui/resolve/auxiliary/issue-112831-aux.rs | 5 - .../auxiliary/proc_macro_generate_packed.rs | 4 - tests/ui/resolve/derive-macro-1.rs | 2 +- tests/ui/resolve/derive-macro-2.rs | 2 +- .../ui/resolve/proc_macro_generated_packed.rs | 2 +- .../auxiliary/ident-mac.rs | 5 - .../auxiliary/param-attrs.rs | 5 - ...-64682-dropping-first-attrs-in-impl-fns.rs | 2 +- .../param-attrs-pretty.rs | 2 +- .../proc-macro-cannot-be-used.rs | 2 +- .../auxiliary/count.rs | 3 - .../edition-spans.rs | 2 +- .../suggestions-not-always-applicable.rs | 5 - .../suggestions-not-always-applicable.fixed | 2 +- .../suggestions-not-always-applicable.rs | 2 +- .../auxiliary/reserved-prefixes-macro-2018.rs | 4 - .../auxiliary/reserved-prefixes-macro-2021.rs | 4 - .../reserved-prefixes-via-macro-2.rs | 4 +- .../rust-2021/reserved-prefixes-via-macro.rs | 2 +- .../reserved-guarded-strings-macro-2021.rs | 4 - .../reserved-guarded-strings-macro-2024.rs | 4 - .../reserved-guarded-strings-via-macro-2.rs | 4 +- .../reserved-guarded-strings-via-macro.rs | 2 +- .../auxiliary/unsafe-attributes-pm.rs | 5 +- .../unsafe-attributes-from-pm.rs | 2 +- .../ui/suggestions/auxiliary/issue-61963-1.rs | 4 - tests/ui/suggestions/auxiliary/issue-61963.rs | 4 - .../auxiliary/proc-macro-type-error.rs | 3 - tests/ui/suggestions/issue-61963.rs | 4 +- tests/ui/suggestions/suggest-ref-macro.rs | 2 +- .../underscore-imports/auxiliary/duplicate.rs | 5 - tests/ui/underscore-imports/duplicate.rs | 2 +- 399 files changed, 425 insertions(+), 1084 deletions(-) rename tests/ui/proc-macro/auxiliary/api/{mod.rs => proc_macro_api_tests.rs} (76%) diff --git a/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs b/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs index 159ecfd09743..c0691b23275e 100644 --- a/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs +++ b/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs index c3858044c0c9..0f6e99f9b1ee 100644 --- a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs +++ b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs @@ -3,7 +3,7 @@ // MSVC is different because of the individual allocas. //@ ignore-msvc -//@ aux-build:macro_def.rs +//@ proc-macro: macro_def.rs // Find the variable. // CHECK-DAG: ![[#var_dbg:]] = !DILocalVariable(name: "n",{{( arg: 1,)?}} scope: ![[#var_scope:]] diff --git a/tests/incremental/auxiliary/incremental_proc_macro_aux.rs b/tests/incremental/auxiliary/incremental_proc_macro_aux.rs index 505a9ee27a40..d0730eb00ee8 100644 --- a/tests/incremental/auxiliary/incremental_proc_macro_aux.rs +++ b/tests/incremental/auxiliary/incremental_proc_macro_aux.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/incremental/auxiliary/issue-49482-macro-def.rs b/tests/incremental/auxiliary/issue-49482-macro-def.rs index 9218d6b62cbb..6cd565c3a110 100644 --- a/tests/incremental/auxiliary/issue-49482-macro-def.rs +++ b/tests/incremental/auxiliary/issue-49482-macro-def.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type="proc-macro"] #![allow(non_snake_case)] extern crate proc_macro; diff --git a/tests/incremental/auxiliary/issue-49482-reexport.rs b/tests/incremental/auxiliary/issue-49482-reexport.rs index 39f19e3f15f2..686766de54fe 100644 --- a/tests/incremental/auxiliary/issue-49482-reexport.rs +++ b/tests/incremental/auxiliary/issue-49482-reexport.rs @@ -1,3 +1,4 @@ +//@ proc-macro: issue-49482-macro-def.rs #[macro_use] extern crate issue_49482_macro_def; diff --git a/tests/incremental/auxiliary/issue-54059.rs b/tests/incremental/auxiliary/issue-54059.rs index 5f45403735cd..6bbc94149e82 100644 --- a/tests/incremental/auxiliary/issue-54059.rs +++ b/tests/incremental/auxiliary/issue-54059.rs @@ -1,9 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - // check that having extern "C" functions in a proc macro doesn't crash. -#![crate_type="proc-macro"] #![allow(non_snake_case)] extern crate proc_macro; diff --git a/tests/incremental/incremental_proc_macro.rs b/tests/incremental/incremental_proc_macro.rs index 97faf8e698a2..3cf89cae6528 100644 --- a/tests/incremental/incremental_proc_macro.rs +++ b/tests/incremental/incremental_proc_macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:incremental_proc_macro_aux.rs +//@ proc-macro: incremental_proc_macro_aux.rs //@ revisions: cfail1 cfail2 //@ build-pass (FIXME(62277): could be check-pass?) diff --git a/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs b/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs index 3b4933811d3f..877d74d731d5 100644 --- a/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs +++ b/tests/incremental/issue-110457-same-span-closures/auxiliary/egui_inspect_derive.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; diff --git a/tests/incremental/issue-110457-same-span-closures/main.rs b/tests/incremental/issue-110457-same-span-closures/main.rs index c36b7e3ca804..6a5e4b315ce3 100644 --- a/tests/incremental/issue-110457-same-span-closures/main.rs +++ b/tests/incremental/issue-110457-same-span-closures/main.rs @@ -1,4 +1,4 @@ -//@ aux-build: egui_inspect_derive.rs +//@ proc-macro: egui_inspect_derive.rs //@ revisions: cpass1 cpass2 extern crate egui_inspect_derive; diff --git a/tests/incremental/issue-49482.rs b/tests/incremental/issue-49482.rs index 2dddde6c1710..849f1c666009 100644 --- a/tests/incremental/issue-49482.rs +++ b/tests/incremental/issue-49482.rs @@ -1,4 +1,3 @@ -//@ aux-build:issue-49482-macro-def.rs //@ aux-build:issue-49482-reexport.rs //@ revisions: rpass1 diff --git a/tests/incremental/issue-54059.rs b/tests/incremental/issue-54059.rs index bfce4d487db1..b6668b4be28a 100644 --- a/tests/incremental/issue-54059.rs +++ b/tests/incremental/issue-54059.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-54059.rs +//@ proc-macro: issue-54059.rs //@ ignore-windows - dealing with weird symbols issues on dylibs isn't worth it //@ revisions: rpass1 diff --git a/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs index f84c4fe9895e..704193cffd0b 100644 --- a/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs +++ b/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs @@ -1,3 +1,4 @@ +//@ proc-macro: respan.rs //@ revisions: rpass1 rpass2 extern crate respan; diff --git a/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs index c56d9052e32c..5bedca8a265b 100644 --- a/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs +++ b/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs b/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs index eaad44780c74..6db5107cbe43 100644 --- a/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs +++ b/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs @@ -1,5 +1,4 @@ //@ revisions: rpass1 rpass2 -//@ aux-build:respan.rs //@ aux-build:invalid-span-helper-lib.rs // This issue has several different parts. The high level idea is: diff --git a/tests/pretty/attr-derive.rs b/tests/pretty/attr-derive.rs index 79b6ea514463..afb86b293156 100644 --- a/tests/pretty/attr-derive.rs +++ b/tests/pretty/attr-derive.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-foo.rs +//@ proc-macro: derive-foo.rs //@ pp-exact // Testing that both the inner item and next outer item are // preserved, and that the first outer item parsed in main is not diff --git a/tests/pretty/auxiliary/derive-foo.rs b/tests/pretty/auxiliary/derive-foo.rs index dc682beafade..160275082811 100644 --- a/tests/pretty/auxiliary/derive-foo.rs +++ b/tests/pretty/auxiliary/derive-foo.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/annotate-snippet/auxiliary/multispan.rs b/tests/ui/annotate-snippet/auxiliary/multispan.rs index b5f1ed9b56a9..1eb379d3877d 100644 --- a/tests/ui/annotate-snippet/auxiliary/multispan.rs +++ b/tests/ui/annotate-snippet/auxiliary/multispan.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/annotate-snippet/multispan.rs b/tests/ui/annotate-snippet/multispan.rs index c9ec4043e374..b7cf22eebcbf 100644 --- a/tests/ui/annotate-snippet/multispan.rs +++ b/tests/ui/annotate-snippet/multispan.rs @@ -1,4 +1,4 @@ -//@ aux-build:multispan.rs +//@ proc-macro: multispan.rs //@ error-pattern:hello to you, too! //@ compile-flags: --error-format human-annotate-rs -Z unstable-options diff --git a/tests/ui/async-await/issues/auxiliary/issue-60674.rs b/tests/ui/async-await/issues/auxiliary/issue-60674.rs index da11142a3a4a..a22f90e95168 100644 --- a/tests/ui/async-await/issues/auxiliary/issue-60674.rs +++ b/tests/ui/async-await/issues/auxiliary/issue-60674.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/async-await/issues/issue-60674.rs b/tests/ui/async-await/issues/issue-60674.rs index 9def3552e677..d04fa23840e6 100644 --- a/tests/ui/async-await/issues/issue-60674.rs +++ b/tests/ui/async-await/issues/issue-60674.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-60674.rs +//@ proc-macro: issue-60674.rs //@ build-pass (FIXME(62277): could be check-pass?) //@ edition:2018 diff --git a/tests/ui/attributes/auxiliary/key-value-expansion.rs b/tests/ui/attributes/auxiliary/key-value-expansion.rs index 9db82cec6356..5ecc62ed3fa3 100644 --- a/tests/ui/attributes/auxiliary/key-value-expansion.rs +++ b/tests/ui/attributes/auxiliary/key-value-expansion.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/attributes/key-value-expansion.rs b/tests/ui/attributes/key-value-expansion.rs index dd408ebb77e4..e5700a759356 100644 --- a/tests/ui/attributes/key-value-expansion.rs +++ b/tests/ui/attributes/key-value-expansion.rs @@ -1,7 +1,7 @@ // Regression tests for issue #55414, expansion happens in the value of a key-value attribute, // and the expanded expression is more complex than simply a macro call. -//@ aux-build:key-value-expansion.rs +//@ proc-macro: key-value-expansion.rs #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs b/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs index 25879d17027b..038183a80b8b 100644 --- a/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs +++ b/tests/ui/attributes/main-removed-2/auxiliary/tokyo.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/attributes/main-removed-2/main.rs b/tests/ui/attributes/main-removed-2/main.rs index e4a3de79ec99..53696d68ced0 100644 --- a/tests/ui/attributes/main-removed-2/main.rs +++ b/tests/ui/attributes/main-removed-2/main.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:tokyo.rs +//@ proc-macro: tokyo.rs //@ compile-flags:--extern tokyo //@ edition:2021 diff --git a/tests/ui/autodiff/auxiliary/my_macro.rs b/tests/ui/autodiff/auxiliary/my_macro.rs index 417199611cca..217631a33c9b 100644 --- a/tests/ui/autodiff/auxiliary/my_macro.rs +++ b/tests/ui/autodiff/auxiliary/my_macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/autodiff/visibility.rs b/tests/ui/autodiff/visibility.rs index 6a4851de2dc0..dfaec03aef01 100644 --- a/tests/ui/autodiff/visibility.rs +++ b/tests/ui/autodiff/visibility.rs @@ -1,7 +1,7 @@ //@ ignore-enzyme //@ revisions: std_autodiff no_std_autodiff //@[no_std_autodiff] check-pass -//@ aux-build: my_macro.rs +//@ proc-macro: my_macro.rs #![crate_type = "lib"] #![feature(autodiff)] diff --git a/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs b/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs index b04b1e0c3262..cafb7389e29f 100644 --- a/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs +++ b/tests/ui/cfg/assume-incomplete-release/assume-incomplete.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:ver-cfg-rel.rs +//@ proc-macro: ver-cfg-rel.rs //@ revisions: assume no_assume //@ [assume]compile-flags: -Z assume-incomplete-release diff --git a/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs b/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs index e06ee94a1e96..5d3e9c7a32fe 100644 --- a/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs +++ b/tests/ui/cfg/assume-incomplete-release/auxiliary/ver-cfg-rel.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree as Tt}; use std::str::FromStr; diff --git a/tests/ui/crate-loading/auxiliary/proc-macro.rs b/tests/ui/crate-loading/auxiliary/proc-macro.rs index ad227c069d20..a87a2b243a1e 100644 --- a/tests/ui/crate-loading/auxiliary/proc-macro.rs +++ b/tests/ui/crate-loading/auxiliary/proc-macro.rs @@ -1,7 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic #![crate_name = "reproduction"] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/crate-loading/cross-compiled-proc-macro.rs b/tests/ui/crate-loading/cross-compiled-proc-macro.rs index 51431c058655..b727f22e188a 100644 --- a/tests/ui/crate-loading/cross-compiled-proc-macro.rs +++ b/tests/ui/crate-loading/cross-compiled-proc-macro.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ compile-flags:--extern reproduction -//@ aux-build:proc-macro.rs +//@ proc-macro: proc-macro.rs //@ check-pass reproduction::mac!(); diff --git a/tests/ui/derives/auxiliary/derive-marker-tricky.rs b/tests/ui/derives/auxiliary/derive-marker-tricky.rs index 0f1c30811a2d..f31baa43c3d1 100644 --- a/tests/ui/derives/auxiliary/derive-marker-tricky.rs +++ b/tests/ui/derives/auxiliary/derive-marker-tricky.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/derives/derive-marker-tricky.rs b/tests/ui/derives/derive-marker-tricky.rs index ad03b6c2cd27..3831bd485818 100644 --- a/tests/ui/derives/derive-marker-tricky.rs +++ b/tests/ui/derives/derive-marker-tricky.rs @@ -2,7 +2,7 @@ // a built-in derive in non-trivial scope (e.g. in a nested module). //@ check-pass -//@ aux-build:derive-marker-tricky.rs +//@ proc-macro: derive-marker-tricky.rs extern crate derive_marker_tricky; diff --git a/tests/ui/deriving/auxiliary/another-proc-macro.rs b/tests/ui/deriving/auxiliary/another-proc-macro.rs index c992cde4066b..47f3c5b9c4b0 100644 --- a/tests/ui/deriving/auxiliary/another-proc-macro.rs +++ b/tests/ui/deriving/auxiliary/another-proc-macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/deriving/built-in-proc-macro-scope.rs b/tests/ui/deriving/built-in-proc-macro-scope.rs index 6c473aefc5b0..e67197b7e205 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.rs +++ b/tests/ui/deriving/built-in-proc-macro-scope.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout index 07767dc229fd..db97c7145ea0 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.stdout +++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout @@ -1,7 +1,7 @@ #![feature(prelude_import)] #![no_std] //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.rs b/tests/ui/deriving/proc-macro-attribute-mixing.rs index 80a0d068ce7d..2c11c3f72ca5 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.rs +++ b/tests/ui/deriving/proc-macro-attribute-mixing.rs @@ -5,7 +5,7 @@ // are in scope. //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.stdout b/tests/ui/deriving/proc-macro-attribute-mixing.stdout index 03128c6c957c..ad743d013d25 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.stdout +++ b/tests/ui/deriving/proc-macro-attribute-mixing.stdout @@ -7,7 +7,7 @@ // are in scope. //@ check-pass -//@ aux-build: another-proc-macro.rs +//@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded #![feature(derive_coerce_pointee)] diff --git a/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs b/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs index 4edae48923a2..3fe84317d70e 100644 --- a/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs +++ b/tests/ui/diagnostic_namespace/auxiliary/proc-macro-helper.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/diagnostic_namespace/existing_proc_macros.rs b/tests/ui/diagnostic_namespace/existing_proc_macros.rs index 014ec46f1b98..55b6b0ab441b 100644 --- a/tests/ui/diagnostic_namespace/existing_proc_macros.rs +++ b/tests/ui/diagnostic_namespace/existing_proc_macros.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:proc-macro-helper.rs +//@ proc-macro: proc-macro-helper.rs extern crate proc_macro_helper; diff --git a/tests/ui/fmt/auxiliary/format-string-proc-macro.rs b/tests/ui/fmt/auxiliary/format-string-proc-macro.rs index 5c00c9c0800c..f473fee0987c 100644 --- a/tests/ui/fmt/auxiliary/format-string-proc-macro.rs +++ b/tests/ui/fmt/auxiliary/format-string-proc-macro.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; diff --git a/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs b/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs index 3a0b7ba46662..8ba6fcc46d41 100644 --- a/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs +++ b/tests/ui/fmt/format-args-capture-first-literal-is-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs #[macro_use] extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs index 24531e4ece45..26d483e43ae5 100644 --- a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs +++ b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-args-capture-issue-106408.rs b/tests/ui/fmt/format-args-capture-issue-106408.rs index 7c29e37441cb..10f944dd9ba6 100644 --- a/tests/ui/fmt/format-args-capture-issue-106408.rs +++ b/tests/ui/fmt/format-args-capture-issue-106408.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-args-capture-macro-hygiene.rs b/tests/ui/fmt/format-args-capture-macro-hygiene.rs index 2ef81f2cd42f..21e445624a5f 100644 --- a/tests/ui/fmt/format-args-capture-macro-hygiene.rs +++ b/tests/ui/fmt/format-args-capture-macro-hygiene.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs #[macro_use] extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/format-expanded-string.rs b/tests/ui/fmt/format-expanded-string.rs index d9b96bdece38..1466dabd7f70 100644 --- a/tests/ui/fmt/format-expanded-string.rs +++ b/tests/ui/fmt/format-expanded-string.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs #[macro_use] extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/indoc-issue-106408.rs b/tests/ui/fmt/indoc-issue-106408.rs index 36e5c23a3945..8c302e5b03aa 100644 --- a/tests/ui/fmt/indoc-issue-106408.rs +++ b/tests/ui/fmt/indoc-issue-106408.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs //@ check-pass extern crate format_string_proc_macro; diff --git a/tests/ui/fmt/respanned-literal-issue-106191.rs b/tests/ui/fmt/respanned-literal-issue-106191.rs index 0a127b1a0ca2..39f09b6e63a7 100644 --- a/tests/ui/fmt/respanned-literal-issue-106191.rs +++ b/tests/ui/fmt/respanned-literal-issue-106191.rs @@ -1,4 +1,4 @@ -//@ aux-build:format-string-proc-macro.rs +//@ proc-macro: format-string-proc-macro.rs extern crate format_string_proc_macro; diff --git a/tests/ui/hygiene/auxiliary/def-site-async-await.rs b/tests/ui/hygiene/auxiliary/def-site-async-await.rs index 41c4b871e736..88042b484a1f 100644 --- a/tests/ui/hygiene/auxiliary/def-site-async-await.rs +++ b/tests/ui/hygiene/auxiliary/def-site-async-await.rs @@ -1,6 +1,5 @@ //@ edition:2018 - -extern crate opaque_hygiene; +//@ proc-macro: opaque-hygiene.rs pub async fn serve() { opaque_hygiene::make_it!(); diff --git a/tests/ui/hygiene/auxiliary/opaque-hygiene.rs b/tests/ui/hygiene/auxiliary/opaque-hygiene.rs index b6192d653f56..08dc592925aa 100644 --- a/tests/ui/hygiene/auxiliary/opaque-hygiene.rs +++ b/tests/ui/hygiene/auxiliary/opaque-hygiene.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::{TokenStream, quote}; diff --git a/tests/ui/hygiene/issue-77523-def-site-async-await.rs b/tests/ui/hygiene/issue-77523-def-site-async-await.rs index 102112381d39..ad6bd5e0b78b 100644 --- a/tests/ui/hygiene/issue-77523-def-site-async-await.rs +++ b/tests/ui/hygiene/issue-77523-def-site-async-await.rs @@ -1,5 +1,4 @@ //@ build-pass -//@ aux-build:opaque-hygiene.rs //@ aux-build:def-site-async-await.rs // Regression test for issue #77523 diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs index e197dcfef804..fab55f11a53a 100644 --- a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs @@ -1,11 +1,6 @@ // A proc-macro in 2015 that has an RPIT without `use<>` that would cause a // problem with 2024 capturing rules. -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.rs b/tests/ui/impl-trait/precise-capturing/external-macro.rs index 87bad7455eb1..9d4d8a1bb119 100644 --- a/tests/ui/impl-trait/precise-capturing/external-macro.rs +++ b/tests/ui/impl-trait/precise-capturing/external-macro.rs @@ -2,7 +2,7 @@ // has an RPIT will not fail when the call-site is 2024. // https://github.com/rust-lang/rust/issues/132917 -//@ aux-crate: no_use_pm=no-use-pm.rs +//@ proc-macro: no-use-pm.rs //@ aux-crate: no_use_macro=no-use-macro.rs //@ edition: 2024 //@ check-pass diff --git a/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs b/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs index a2970cb5c805..b87c4b14abc5 100644 --- a/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs +++ b/tests/ui/inherent-impls-overlap-check/auxiliary/repeat.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt}; diff --git a/tests/ui/inherent-impls-overlap-check/no-overlap.rs b/tests/ui/inherent-impls-overlap-check/no-overlap.rs index 85565a221ac2..df60031bae03 100644 --- a/tests/ui/inherent-impls-overlap-check/no-overlap.rs +++ b/tests/ui/inherent-impls-overlap-check/no-overlap.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:repeat.rs +//@ proc-macro: repeat.rs // This tests the allocating algo branch of the // inherent impls overlap checker. diff --git a/tests/ui/inherent-impls-overlap-check/overlap.rs b/tests/ui/inherent-impls-overlap-check/overlap.rs index 326539436981..114035a13b63 100644 --- a/tests/ui/inherent-impls-overlap-check/overlap.rs +++ b/tests/ui/inherent-impls-overlap-check/overlap.rs @@ -1,4 +1,4 @@ -//@ aux-build:repeat.rs +//@ proc-macro: repeat.rs #![allow(unused)] diff --git a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs index 35ef6fc019dd..4e4b7f61f1ef 100644 --- a/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs +++ b/tests/ui/lifetimes/auxiliary/issue-91763-aux.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - //#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/lifetimes/issue-91763.rs b/tests/ui/lifetimes/issue-91763.rs index 5df69cff3be7..6abb64db5feb 100644 --- a/tests/ui/lifetimes/issue-91763.rs +++ b/tests/ui/lifetimes/issue-91763.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-91763-aux.rs +//@ proc-macro: issue-91763-aux.rs #![deny(elided_lifetimes_in_paths)] diff --git a/tests/ui/lint/auxiliary/add-impl.rs b/tests/ui/lint/auxiliary/add-impl.rs index 7ee4a4e4fde6..d0f2baf94bff 100644 --- a/tests/ui/lint/auxiliary/add-impl.rs +++ b/tests/ui/lint/auxiliary/add-impl.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs index 2a58af0fedcc..72303f12b7e4 100644 --- a/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs +++ b/tests/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs @@ -1,6 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type="proc-macro"] #![crate_name="redundant_semi_proc_macro"] extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs index 33c7e26ba472..3469614aab04 100644 --- a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:redundant-semi-proc-macro-def.rs +//@ proc-macro: redundant-semi-proc-macro-def.rs #![deny(redundant_semicolons)] extern crate redundant_semi_proc_macro; diff --git a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index d42aa1d613ff..1ec440b4e45b 100644 --- a/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/tests/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(199..201) }, Ident { ident: "span_preservation", span: #0 bytes(202..219) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(219..221) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(229..232) }, Ident { ident: "tst", span: #0 bytes(233..236) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(237..238) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(239..242) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(242..243) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(243..244) }, Ident { ident: "match", span: #0 bytes(290..295) }, Ident { ident: "tst", span: #0 bytes(296..299) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(484..487) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(488..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(489..490) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(491..493) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(493..494) }, Ident { ident: "_", span: #0 bytes(503..504) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(505..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(506..507) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(508..510) }], span: #0 bytes(300..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(517..518) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(518..519) }], span: #0 bytes(223..563) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(201..203) }, Ident { ident: "span_preservation", span: #0 bytes(204..221) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(221..223) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(231..234) }, Ident { ident: "tst", span: #0 bytes(235..238) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(239..240) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(241..244) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(244..245) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(245..246) }, Ident { ident: "match", span: #0 bytes(292..297) }, Ident { ident: "tst", span: #0 bytes(298..301) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(486..489) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(490..491) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(491..492) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(493..495) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(495..496) }, Ident { ident: "_", span: #0 bytes(505..506) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(507..508) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(508..509) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(510..512) }], span: #0 bytes(302..518) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(518..519) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(519..520) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(520..521) }], span: #0 bytes(225..565) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | diff --git a/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs index 6849e9170c15..b00f5838749d 100644 --- a/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs +++ b/tests/ui/lint/unsafe_code/auxiliary/forge_unsafe_block.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; diff --git a/tests/ui/lint/unsafe_code/forge_unsafe_block.rs b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs index 6392849f9159..93b2b60647d6 100644 --- a/tests/ui/lint/unsafe_code/forge_unsafe_block.rs +++ b/tests/ui/lint/unsafe_code/forge_unsafe_block.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:forge_unsafe_block.rs +//@ proc-macro: forge_unsafe_block.rs #[macro_use] extern crate forge_unsafe_block; diff --git a/tests/ui/lint/unused-qualification-in-derive-expansion.rs b/tests/ui/lint/unused-qualification-in-derive-expansion.rs index 5cea9086d12d..b2067e22c444 100644 --- a/tests/ui/lint/unused-qualification-in-derive-expansion.rs +++ b/tests/ui/lint/unused-qualification-in-derive-expansion.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:add-impl.rs +//@ proc-macro: add-impl.rs #![forbid(unused_qualifications)] diff --git a/tests/ui/macros/auxiliary/hello_macro.rs b/tests/ui/macros/auxiliary/hello_macro.rs index 10f474bd1b39..79125a1f86e3 100644 --- a/tests/ui/macros/auxiliary/hello_macro.rs +++ b/tests/ui/macros/auxiliary/hello_macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/auxiliary/issue-100199.rs b/tests/ui/macros/auxiliary/issue-100199.rs index 9ee9a2f50394..f05c4f0722cf 100644 --- a/tests/ui/macros/auxiliary/issue-100199.rs +++ b/tests/ui/macros/auxiliary/issue-100199.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/auxiliary/proc_macro_def.rs b/tests/ui/macros/auxiliary/proc_macro_def.rs index 6574bf184fb7..38a1f6fa3c13 100644 --- a/tests/ui/macros/auxiliary/proc_macro_def.rs +++ b/tests/ui/macros/auxiliary/proc_macro_def.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/auxiliary/proc_macro_sequence.rs b/tests/ui/macros/auxiliary/proc_macro_sequence.rs index de2efdfecf14..0f5435401711 100644 --- a/tests/ui/macros/auxiliary/proc_macro_sequence.rs +++ b/tests/ui/macros/auxiliary/proc_macro_sequence.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_span, proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/macros/issue-100199.rs b/tests/ui/macros/issue-100199.rs index b1bcc535d74a..78a6ff149e2a 100644 --- a/tests/ui/macros/issue-100199.rs +++ b/tests/ui/macros/issue-100199.rs @@ -5,7 +5,7 @@ struct Foo {} // an unexpected dummy span (lo == 0 == hi) while attempting to print a // suggestion. -//@ aux-build: issue-100199.rs +//@ proc-macro: issue-100199.rs extern crate issue_100199; diff --git a/tests/ui/macros/macro-quote-test.rs b/tests/ui/macros/macro-quote-test.rs index dd7b10f6322a..a4b667b4af6f 100644 --- a/tests/ui/macros/macro-quote-test.rs +++ b/tests/ui/macros/macro-quote-test.rs @@ -1,7 +1,7 @@ // Test that a macro can emit delimiters with nothing inside - `()`, `{}` //@ run-pass -//@ aux-build:hello_macro.rs +//@ proc-macro: hello_macro.rs extern crate hello_macro; diff --git a/tests/ui/macros/proc_macro.rs b/tests/ui/macros/proc_macro.rs index 8fea4ca282cf..b73f31125369 100644 --- a/tests/ui/macros/proc_macro.rs +++ b/tests/ui/macros/proc_macro.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:proc_macro_def.rs +//@ proc-macro: proc_macro_def.rs extern crate proc_macro_def; diff --git a/tests/ui/macros/same-sequence-span.rs b/tests/ui/macros/same-sequence-span.rs index 67f6b6ad1cda..dfaf669a769a 100644 --- a/tests/ui/macros/same-sequence-span.rs +++ b/tests/ui/macros/same-sequence-span.rs @@ -1,4 +1,4 @@ -//@ aux-build:proc_macro_sequence.rs +//@ proc-macro: proc_macro_sequence.rs // Regression test for issue #62831: Check that multiple sequences with the same span in the // left-hand side of a macro definition behave as if they had unique spans, and in particular that diff --git a/tests/ui/macros/same-sequence-span.stderr b/tests/ui/macros/same-sequence-span.stderr index 3242a32e2f4d..ff32ef943861 100644 --- a/tests/ui/macros/same-sequence-span.stderr +++ b/tests/ui/macros/same-sequence-span.stderr @@ -17,9 +17,9 @@ LL | $(= $z:tt)* error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments --> $DIR/same-sequence-span.rs:19:1 | -LL | | } +LL | | macro_rules! manual_foo { | |_________________________________^ not allowed after `expr` fragments -LL | +... LL | proc_macro_sequence::make_foo!(); | ^------------------------------- | | diff --git a/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs b/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs index 44697afcfed6..2df0b3a17dcf 100644 --- a/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs +++ b/tests/ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs index 51bb04dba192..461890e63e37 100644 --- a/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs +++ b/tests/ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs +//@ proc-macro: issue-89971-outer-attr-following-inner-attr-ice.rs #[macro_use] extern crate issue_89971_outer_attr_following_inner_attr_ice; diff --git a/tests/ui/proc-macro/add-impl.rs b/tests/ui/proc-macro/add-impl.rs index 7780c39f0c14..2299f05c2e7f 100644 --- a/tests/ui/proc-macro/add-impl.rs +++ b/tests/ui/proc-macro/add-impl.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:add-impl.rs +//@ proc-macro: add-impl.rs #[macro_use] extern crate add_impl; diff --git a/tests/ui/proc-macro/allowed-attr-stmt-expr.rs b/tests/ui/proc-macro/allowed-attr-stmt-expr.rs index c5e3ffa1672a..10c2d3f9d131 100644 --- a/tests/ui/proc-macro/allowed-attr-stmt-expr.rs +++ b/tests/ui/proc-macro/allowed-attr-stmt-expr.rs @@ -1,5 +1,5 @@ -//@ aux-build:attr-stmt-expr.rs -//@ aux-build:test-macros.rs +//@ proc-macro: attr-stmt-expr.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ check-pass diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs index 3f191cba7458..8ee2223822a3 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs-test.rs @@ -1,4 +1,4 @@ -//@ aux-build:builtin-attrs.rs +//@ proc-macro: builtin-attrs.rs //@ compile-flags:--test #![feature(decl_macro, test)] diff --git a/tests/ui/proc-macro/ambiguous-builtin-attrs.rs b/tests/ui/proc-macro/ambiguous-builtin-attrs.rs index c82663541a79..edc7748eff3d 100644 --- a/tests/ui/proc-macro/ambiguous-builtin-attrs.rs +++ b/tests/ui/proc-macro/ambiguous-builtin-attrs.rs @@ -1,5 +1,5 @@ //@ edition:2018 -//@ aux-build:builtin-attrs.rs +//@ proc-macro: builtin-attrs.rs #![feature(decl_macro)] //~ ERROR `feature` is ambiguous extern crate builtin_attrs; diff --git a/tests/ui/proc-macro/amputate-span.fixed b/tests/ui/proc-macro/amputate-span.fixed index 0fdaf01357c7..9742f585d499 100644 --- a/tests/ui/proc-macro/amputate-span.fixed +++ b/tests/ui/proc-macro/amputate-span.fixed @@ -1,4 +1,4 @@ -//@ aux-build:amputate-span.rs +//@ proc-macro: amputate-span.rs //@ run-rustfix //@ edition:2018 //@ compile-flags: --extern amputate_span diff --git a/tests/ui/proc-macro/amputate-span.rs b/tests/ui/proc-macro/amputate-span.rs index 7081660bc29f..6cdde46962eb 100644 --- a/tests/ui/proc-macro/amputate-span.rs +++ b/tests/ui/proc-macro/amputate-span.rs @@ -1,4 +1,4 @@ -//@ aux-build:amputate-span.rs +//@ proc-macro: amputate-span.rs //@ run-rustfix //@ edition:2018 //@ compile-flags: --extern amputate_span diff --git a/tests/ui/proc-macro/append-impl.rs b/tests/ui/proc-macro/append-impl.rs index f5163e965a03..c0f208460b29 100644 --- a/tests/ui/proc-macro/append-impl.rs +++ b/tests/ui/proc-macro/append-impl.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:append-impl.rs +//@ proc-macro: append-impl.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/attr-args.rs b/tests/ui/proc-macro/attr-args.rs index ed7e96bcc89c..1d3e0f725d25 100644 --- a/tests/ui/proc-macro/attr-args.rs +++ b/tests/ui/proc-macro/attr-args.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-args.rs +//@ proc-macro: attr-args.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/attr-cfg.rs b/tests/ui/proc-macro/attr-cfg.rs index 4679807ad79a..af0c6e1b5410 100644 --- a/tests/ui/proc-macro/attr-cfg.rs +++ b/tests/ui/proc-macro/attr-cfg.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-cfg.rs +//@ proc-macro: attr-cfg.rs //@ revisions: foo bar extern crate attr_cfg; diff --git a/tests/ui/proc-macro/attr-complex-fn.rs b/tests/ui/proc-macro/attr-complex-fn.rs index 7baf469d7d0f..bf100401a65f 100644 --- a/tests/ui/proc-macro/attr-complex-fn.rs +++ b/tests/ui/proc-macro/attr-complex-fn.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(stmt_expr_attributes)] #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/attr-invalid-exprs.rs b/tests/ui/proc-macro/attr-invalid-exprs.rs index ec0b79469a45..f476858a32ba 100644 --- a/tests/ui/proc-macro/attr-invalid-exprs.rs +++ b/tests/ui/proc-macro/attr-invalid-exprs.rs @@ -1,6 +1,6 @@ //! Attributes producing expressions in invalid locations -//@ aux-build:attr-stmt-expr.rs +//@ proc-macro: attr-stmt-expr.rs #![feature(proc_macro_hygiene)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/attr-on-trait.rs b/tests/ui/proc-macro/attr-on-trait.rs index 659b461f7593..e95760a837c0 100644 --- a/tests/ui/proc-macro/attr-on-trait.rs +++ b/tests/ui/proc-macro/attr-on-trait.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-on-trait.rs +//@ proc-macro: attr-on-trait.rs extern crate attr_on_trait; diff --git a/tests/ui/proc-macro/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/attr-stmt-expr-rpass.rs index 18e477f01296..c4188bde3094 100644 --- a/tests/ui/proc-macro/attr-stmt-expr-rpass.rs +++ b/tests/ui/proc-macro/attr-stmt-expr-rpass.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:attr-stmt-expr-rpass.rs +//@ proc-macro: attr-stmt-expr-rpass.rs #![feature(stmt_expr_attributes, proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/attr-stmt-expr.rs b/tests/ui/proc-macro/attr-stmt-expr.rs index f33c686f284c..1ed2bd048e60 100644 --- a/tests/ui/proc-macro/attr-stmt-expr.rs +++ b/tests/ui/proc-macro/attr-stmt-expr.rs @@ -1,5 +1,5 @@ -//@ aux-build:attr-stmt-expr.rs -//@ aux-build:test-macros.rs +//@ proc-macro: attr-stmt-expr.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![feature(proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/attribute-after-derive.rs b/tests/ui/proc-macro/attribute-after-derive.rs index 3120b23e97ee..f2e2eb12a195 100644 --- a/tests/ui/proc-macro/attribute-after-derive.rs +++ b/tests/ui/proc-macro/attribute-after-derive.rs @@ -3,7 +3,7 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build: test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/attribute-spans-preserved.rs b/tests/ui/proc-macro/attribute-spans-preserved.rs index 946b16a0c80e..4d5b93797e6e 100644 --- a/tests/ui/proc-macro/attribute-spans-preserved.rs +++ b/tests/ui/proc-macro/attribute-spans-preserved.rs @@ -1,4 +1,4 @@ -//@ aux-build:attribute-spans-preserved.rs +//@ proc-macro: attribute-spans-preserved.rs extern crate attribute_spans_preserved as foo; diff --git a/tests/ui/proc-macro/attribute-with-error.rs b/tests/ui/proc-macro/attribute-with-error.rs index 5e81a9c70116..d44d558badd1 100644 --- a/tests/ui/proc-macro/attribute-with-error.rs +++ b/tests/ui/proc-macro/attribute-with-error.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/attributes-included.rs b/tests/ui/proc-macro/attributes-included.rs index 47fd21fdd249..73d1c1a8f05a 100644 --- a/tests/ui/proc-macro/attributes-included.rs +++ b/tests/ui/proc-macro/attributes-included.rs @@ -1,4 +1,4 @@ -//@ aux-build:attributes-included.rs +//@ proc-macro: attributes-included.rs //@ check-pass #![warn(unused)] diff --git a/tests/ui/proc-macro/attributes-on-definitions.rs b/tests/ui/proc-macro/attributes-on-definitions.rs index 187d1be23640..d9700434b51a 100644 --- a/tests/ui/proc-macro/attributes-on-definitions.rs +++ b/tests/ui/proc-macro/attributes-on-definitions.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:attributes-on-definitions.rs +//@ proc-macro: attributes-on-definitions.rs #![forbid(unsafe_code)] diff --git a/tests/ui/proc-macro/attributes-on-modules-fail.rs b/tests/ui/proc-macro/attributes-on-modules-fail.rs index 9b2eb703eacc..80300b47c5fc 100644 --- a/tests/ui/proc-macro/attributes-on-modules-fail.rs +++ b/tests/ui/proc-macro/attributes-on-modules-fail.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/attributes-on-modules.rs b/tests/ui/proc-macro/attributes-on-modules.rs index 26c8d8e113b5..f1be7e44a479 100644 --- a/tests/ui/proc-macro/attributes-on-modules.rs +++ b/tests/ui/proc-macro/attributes-on-modules.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/auxiliary/add-impl.rs b/tests/ui/proc-macro/auxiliary/add-impl.rs index 23a86e76ef9b..327e6065ef2d 100644 --- a/tests/ui/proc-macro/auxiliary/add-impl.rs +++ b/tests/ui/proc-macro/auxiliary/add-impl.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/amputate-span.rs b/tests/ui/proc-macro/auxiliary/amputate-span.rs index c1ab0477ba2a..969176eaa673 100644 --- a/tests/ui/proc-macro/auxiliary/amputate-span.rs +++ b/tests/ui/proc-macro/auxiliary/amputate-span.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs similarity index 76% rename from tests/ui/proc-macro/auxiliary/api/mod.rs rename to tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs index e0a381cb6c1a..abd667d8ce1d 100644 --- a/tests/ui/proc-macro/auxiliary/api/mod.rs +++ b/tests/ui/proc-macro/auxiliary/api/proc_macro_api_tests.rs @@ -1,9 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic //@ edition: 2021 -#![crate_type = "proc-macro"] -#![crate_name = "proc_macro_api_tests"] #![feature(proc_macro_span)] #![deny(dead_code)] // catch if a test function is never called diff --git a/tests/ui/proc-macro/auxiliary/append-impl.rs b/tests/ui/proc-macro/auxiliary/append-impl.rs index 30657d2738e1..e286f01a9711 100644 --- a/tests/ui/proc-macro/auxiliary/append-impl.rs +++ b/tests/ui/proc-macro/auxiliary/append-impl.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/assert-span-pos.rs b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs index 8935ce2bc0ae..6459d2169a99 100644 --- a/tests/ui/proc-macro/auxiliary/assert-span-pos.rs +++ b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_diagnostic, proc_macro_span)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/attr-args.rs b/tests/ui/proc-macro/auxiliary/attr-args.rs index 1fac41c37217..6a1041603f15 100644 --- a/tests/ui/proc-macro/auxiliary/attr-args.rs +++ b/tests/ui/proc-macro/auxiliary/attr-args.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-cfg.rs b/tests/ui/proc-macro/auxiliary/attr-cfg.rs index 3645128b5090..0e6259325121 100644 --- a/tests/ui/proc-macro/auxiliary/attr-cfg.rs +++ b/tests/ui/proc-macro/auxiliary/attr-cfg.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-on-trait.rs b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs index c4581359da12..012243febce0 100644 --- a/tests/ui/proc-macro/auxiliary/attr-on-trait.rs +++ b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs index c8b7aa412b52..022f10e56152 100644 --- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs index 888aab848d47..7efeda16b9cd 100644 --- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs index d06903c27089..76cf959279cf 100644 --- a/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs +++ b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/attributes-included.rs b/tests/ui/proc-macro/auxiliary/attributes-included.rs index cc29818380b6..3a129c8185ef 100644 --- a/tests/ui/proc-macro/auxiliary/attributes-included.rs +++ b/tests/ui/proc-macro/auxiliary/attributes-included.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group}; diff --git a/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs index c7e6e681da30..ef981ba85002 100644 --- a/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs +++ b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -1,11 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/bang-macro.rs b/tests/ui/proc-macro/auxiliary/bang-macro.rs index 361643aa8e5e..3ac30ab8e328 100644 --- a/tests/ui/proc-macro/auxiliary/bang-macro.rs +++ b/tests/ui/proc-macro/auxiliary/bang-macro.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs index 3df2676ddab7..7a094c2d4773 100644 --- a/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs +++ b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/builtin-attrs.rs b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs index bd634b4f41cd..9743ec78c967 100644 --- a/tests/ui/proc-macro/auxiliary/builtin-attrs.rs +++ b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/call-deprecated.rs b/tests/ui/proc-macro/auxiliary/call-deprecated.rs index 8864de17ed3b..28919ab29ece 100644 --- a/tests/ui/proc-macro/auxiliary/call-deprecated.rs +++ b/tests/ui/proc-macro/auxiliary/call-deprecated.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/call-site.rs b/tests/ui/proc-macro/auxiliary/call-site.rs index ce0fc70c1a6c..8201ec5c48fe 100644 --- a/tests/ui/proc-macro/auxiliary/call-site.rs +++ b/tests/ui/proc-macro/auxiliary/call-site.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/cond_plugin.rs b/tests/ui/proc-macro/auxiliary/cond_plugin.rs index c6cdc8ce8baf..9858be230c95 100644 --- a/tests/ui/proc-macro/auxiliary/cond_plugin.rs +++ b/tests/ui/proc-macro/auxiliary/cond_plugin.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/count_compound_ops.rs b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs index 86c27f2d818b..c5a1c561976e 100644 --- a/tests/ui/proc-macro/auxiliary/count_compound_ops.rs +++ b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs index eab7d903e91c..0f50aedcd9eb 100644 --- a/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs +++ b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/custom-quote.rs b/tests/ui/proc-macro/auxiliary/custom-quote.rs index 88800596ce56..bccbed8a6b49 100644 --- a/tests/ui/proc-macro/auxiliary/custom-quote.rs +++ b/tests/ui/proc-macro/auxiliary/custom-quote.rs @@ -1,9 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic // ignore-tidy-linelength #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use std::iter::FromIterator; diff --git a/tests/ui/proc-macro/auxiliary/derive-a.rs b/tests/ui/proc-macro/auxiliary/derive-a.rs index 50e963a0a416..89d0263c9e28 100644 --- a/tests/ui/proc-macro/auxiliary/derive-a.rs +++ b/tests/ui/proc-macro/auxiliary/derive-a.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-atob.rs b/tests/ui/proc-macro/auxiliary/derive-atob.rs index 8a1f81450fa8..0ed625657712 100644 --- a/tests/ui/proc-macro/auxiliary/derive-atob.rs +++ b/tests/ui/proc-macro/auxiliary/derive-atob.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs index b9c0b5e6f776..cb60c182a43c 100644 --- a/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs +++ b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs index 82f0b4f19eda..de2935eb9c1d 100644 --- a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs +++ b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-b.rs b/tests/ui/proc-macro/auxiliary/derive-b.rs index 0b2cf31b0591..efdb785c23be 100644 --- a/tests/ui/proc-macro/auxiliary/derive-b.rs +++ b/tests/ui/proc-macro/auxiliary/derive-b.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-bad.rs b/tests/ui/proc-macro/auxiliary/derive-bad.rs index 3fd2bfc4b63a..bd25478fb1de 100644 --- a/tests/ui/proc-macro/auxiliary/derive-bad.rs +++ b/tests/ui/proc-macro/auxiliary/derive-bad.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-clona.rs b/tests/ui/proc-macro/auxiliary/derive-clona.rs index 83bcc5b08be8..b38bf31dbccb 100644 --- a/tests/ui/proc-macro/auxiliary/derive-clona.rs +++ b/tests/ui/proc-macro/auxiliary/derive-clona.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-ctod.rs b/tests/ui/proc-macro/auxiliary/derive-ctod.rs index 78b1b8615b0b..1e08ec612621 100644 --- a/tests/ui/proc-macro/auxiliary/derive-ctod.rs +++ b/tests/ui/proc-macro/auxiliary/derive-ctod.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-foo.rs b/tests/ui/proc-macro/auxiliary/derive-foo.rs index 5c63c3937e4b..22fbc4bc54f1 100644 --- a/tests/ui/proc-macro/auxiliary/derive-foo.rs +++ b/tests/ui/proc-macro/auxiliary/derive-foo.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs index d09ff6cadc57..da474cf5614b 100644 --- a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs index d1f5b67cf85b..32136f79ff28 100644 --- a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs +++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/derive-nothing.rs b/tests/ui/proc-macro/auxiliary/derive-nothing.rs index adf9b4e83fdf..eefa2c40ac36 100644 --- a/tests/ui/proc-macro/auxiliary/derive-nothing.rs +++ b/tests/ui/proc-macro/auxiliary/derive-nothing.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs index bfdd71e9a15f..8e7bcb6aaba8 100644 --- a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs +++ b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs index 24a88dceb4b5..532c72dacffc 100644 --- a/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs +++ b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/derive-union.rs b/tests/ui/proc-macro/auxiliary/derive-union.rs index 8bf7041ebad2..da4132604a78 100644 --- a/tests/ui/proc-macro/auxiliary/derive-union.rs +++ b/tests/ui/proc-macro/auxiliary/derive-union.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs index f80a2cfdd992..4bc56efecdbf 100644 --- a/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs +++ b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable.rs b/tests/ui/proc-macro/auxiliary/derive-unstable.rs index c92df49191b6..8ba3a06e3549 100644 --- a/tests/ui/proc-macro/auxiliary/derive-unstable.rs +++ b/tests/ui/proc-macro/auxiliary/derive-unstable.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/double.rs b/tests/ui/proc-macro/auxiliary/double.rs index ffde0bce2451..b6d952437ea1 100644 --- a/tests/ui/proc-macro/auxiliary/double.rs +++ b/tests/ui/proc-macro/auxiliary/double.rs @@ -1,10 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/duplicate.rs b/tests/ui/proc-macro/auxiliary/duplicate.rs index bcbb1c7474c8..0474aed22665 100644 --- a/tests/ui/proc-macro/auxiliary/duplicate.rs +++ b/tests/ui/proc-macro/auxiliary/duplicate.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![deny(unused)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs b/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs index da6584e31e5f..9347a2e975b2 100644 --- a/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs +++ b/tests/ui/proc-macro/auxiliary/edition-gated-async-move-syntax.rs @@ -1,12 +1,7 @@ -//@ force-host -//@ no-prefer-dynamic - // Proc macro helper for issue #89699, used by tests/ui/proc-macro/edition-gated-async-move- // syntax-issue89699.rs, emitting an `async move` closure. This syntax is only available in // editions 2018 and up, but is used in edition 2015 in the test. -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs index c33736a74a70..6d584f4e6abf 100644 --- a/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs +++ b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs @@ -1,8 +1,4 @@ //@ edition:2015 -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/empty-crate.rs b/tests/ui/proc-macro/auxiliary/empty-crate.rs index c502cd921cc8..5e15112a9cbf 100644 --- a/tests/ui/proc-macro/auxiliary/empty-crate.rs +++ b/tests/ui/proc-macro/auxiliary/empty-crate.rs @@ -1,5 +1 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![deny(unused_variables)] diff --git a/tests/ui/proc-macro/auxiliary/env.rs b/tests/ui/proc-macro/auxiliary/env.rs index da9aaa5cb562..d01e3b42d4ce 100644 --- a/tests/ui/proc-macro/auxiliary/env.rs +++ b/tests/ui/proc-macro/auxiliary/env.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_tracked_env)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/expand-expr.rs b/tests/ui/proc-macro/auxiliary/expand-expr.rs index 68d0843be5ab..78c9fa75d9ff 100644 --- a/tests/ui/proc-macro/auxiliary/expand-expr.rs +++ b/tests/ui/proc-macro/auxiliary/expand-expr.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![deny(warnings)] #![feature(proc_macro_expand, proc_macro_span)] diff --git a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs index 9096fd713975..c6281a42d2a1 100644 --- a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs +++ b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![deny(warnings)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/first-second.rs b/tests/ui/proc-macro/auxiliary/first-second.rs index c8c1defa9f10..110d054add71 100644 --- a/tests/ui/proc-macro/auxiliary/first-second.rs +++ b/tests/ui/proc-macro/auxiliary/first-second.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Group, Delimiter}; diff --git a/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs index fb05c97833c3..b0728b8a0b8a 100644 --- a/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs +++ b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs index 9d6767dc11f5..40ecf4ef7046 100644 --- a/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs +++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs index d2f82c52c589..855cb1d7095c 100644 --- a/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs +++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs index 855084be84d3..28d35c82148e 100644 --- a/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs +++ b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/generate-mod.rs b/tests/ui/proc-macro/auxiliary/generate-mod.rs index 2ef1faffaa66..62710bd1e2df 100644 --- a/tests/ui/proc-macro/auxiliary/generate-mod.rs +++ b/tests/ui/proc-macro/auxiliary/generate-mod.rs @@ -1,10 +1,6 @@ //@ run-pass -//@ force-host -//@ no-prefer-dynamic //@ ignore-pass -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/helper-attr.rs b/tests/ui/proc-macro/auxiliary/helper-attr.rs index 79ccefd98440..ee2968688f9c 100644 --- a/tests/ui/proc-macro/auxiliary/helper-attr.rs +++ b/tests/ui/proc-macro/auxiliary/helper-attr.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; // Doesn't do anything, but has a helper attribute. diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example.rs b/tests/ui/proc-macro/auxiliary/hygiene_example.rs index f7e7e0b5751e..b690dbfaae72 100644 --- a/tests/ui/proc-macro/auxiliary/hygiene_example.rs +++ b/tests/ui/proc-macro/auxiliary/hygiene_example.rs @@ -1,3 +1,5 @@ +//@ proc-macro: hygiene_example_codegen.rs + extern crate hygiene_example_codegen; pub use hygiene_example_codegen::hello; diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs index e324e3f31296..dde997bf3ea3 100644 --- a/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs +++ b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro as proc_macro_renamed; // This does not break `quote!` diff --git a/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs index 19b3632dc3fd..47d060864670 100644 --- a/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs +++ b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_raw_ident)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/is-available.rs b/tests/ui/proc-macro/auxiliary/is-available.rs index f1d0e3c78f5b..1eeffa50913b 100644 --- a/tests/ui/proc-macro/auxiliary/is-available.rs +++ b/tests/ui/proc-macro/auxiliary/is-available.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Literal, TokenStream, TokenTree}; diff --git a/tests/ui/proc-macro/auxiliary/issue-104884.rs b/tests/ui/proc-macro/auxiliary/issue-104884.rs index 55d0d76ad184..64922d997b6f 100644 --- a/tests/ui/proc-macro/auxiliary/issue-104884.rs +++ b/tests/ui/proc-macro/auxiliary/issue-104884.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-107113.rs b/tests/ui/proc-macro/auxiliary/issue-107113.rs index 5662277acce5..f7c2c856435b 100644 --- a/tests/ui/proc-macro/auxiliary/issue-107113.rs +++ b/tests/ui/proc-macro/auxiliary/issue-107113.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-118809.rs b/tests/ui/proc-macro/auxiliary/issue-118809.rs index f662f623b190..2751b16b6b55 100644 --- a/tests/ui/proc-macro/auxiliary/issue-118809.rs +++ b/tests/ui/proc-macro/auxiliary/issue-118809.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-38586.rs b/tests/ui/proc-macro/auxiliary/issue-38586.rs index e2bba3e13d10..7e30ba371d1d 100644 --- a/tests/ui/proc-macro/auxiliary/issue-38586.rs +++ b/tests/ui/proc-macro/auxiliary/issue-38586.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; #[proc_macro_derive(A)] diff --git a/tests/ui/proc-macro/auxiliary/issue-39889.rs b/tests/ui/proc-macro/auxiliary/issue-39889.rs index b1659d6168e6..e4975fddd4c6 100644 --- a/tests/ui/proc-macro/auxiliary/issue-39889.rs +++ b/tests/ui/proc-macro/auxiliary/issue-39889.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-42708.rs b/tests/ui/proc-macro/auxiliary/issue-42708.rs index ed5ba5303410..c055409ba061 100644 --- a/tests/ui/proc-macro/auxiliary/issue-42708.rs +++ b/tests/ui/proc-macro/auxiliary/issue-42708.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-50061.rs b/tests/ui/proc-macro/auxiliary/issue-50061.rs index 9ecbb383d4be..9137a78f5307 100644 --- a/tests/ui/proc-macro/auxiliary/issue-50061.rs +++ b/tests/ui/proc-macro/auxiliary/issue-50061.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-50493.rs b/tests/ui/proc-macro/auxiliary/issue-50493.rs index e9ad86005339..22bf1428e568 100644 --- a/tests/ui/proc-macro/auxiliary/issue-50493.rs +++ b/tests/ui/proc-macro/auxiliary/issue-50493.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-59191.rs b/tests/ui/proc-macro/auxiliary/issue-59191.rs index 40ba0063e439..84b156d61e5f 100644 --- a/tests/ui/proc-macro/auxiliary/issue-59191.rs +++ b/tests/ui/proc-macro/auxiliary/issue-59191.rs @@ -1,8 +1,4 @@ //@ edition:2018 -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-66286.rs b/tests/ui/proc-macro/auxiliary/issue-66286.rs index d224dcda5901..a317e68a3d7f 100644 --- a/tests/ui/proc-macro/auxiliary/issue-66286.rs +++ b/tests/ui/proc-macro/auxiliary/issue-66286.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-75801.rs b/tests/ui/proc-macro/auxiliary/issue-75801.rs index bd553b7ab846..f1554f0fe750 100644 --- a/tests/ui/proc-macro/auxiliary/issue-75801.rs +++ b/tests/ui/proc-macro/auxiliary/issue-75801.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-79242.rs b/tests/ui/proc-macro/auxiliary/issue-79242.rs index 7b24e5a2ef22..165318d67b06 100644 --- a/tests/ui/proc-macro/auxiliary/issue-79242.rs +++ b/tests/ui/proc-macro/auxiliary/issue-79242.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-79825.rs b/tests/ui/proc-macro/auxiliary/issue-79825.rs index 4326712458bc..912a3c2147c5 100644 --- a/tests/ui/proc-macro/auxiliary/issue-79825.rs +++ b/tests/ui/proc-macro/auxiliary/issue-79825.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-83510.rs b/tests/ui/proc-macro/auxiliary/issue-83510.rs index 6e8e2d1f7802..50bdd36607d5 100644 --- a/tests/ui/proc-macro/auxiliary/issue-83510.rs +++ b/tests/ui/proc-macro/auxiliary/issue-83510.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs index a638a33cf257..e6f91a52de5d 100644 --- a/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs +++ b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs index 4f605ed07b35..d487d8f989c9 100644 --- a/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs +++ b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/lifetimes.rs b/tests/ui/proc-macro/auxiliary/lifetimes.rs index 79885a92f684..5d7ebecf8323 100644 --- a/tests/ui/proc-macro/auxiliary/lifetimes.rs +++ b/tests/ui/proc-macro/auxiliary/lifetimes.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs index 501a03985cb3..4971de284b76 100644 --- a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs +++ b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -1,6 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - // These are tests for syntax that is accepted by the Rust parser but // unconditionally rejected semantically after macro expansion. Attribute macros // are permitted to accept such syntax as long as they replace it with something @@ -9,7 +6,6 @@ // We also inspect some of the spans to verify the syntax is not triggering the // lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081). -#![crate_type = "proc-macro"] #![feature(proc_macro_span)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs b/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs index a4fd76b9c9d3..fb244d09d9cb 100644 --- a/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs +++ b/tests/ui/proc-macro/auxiliary/macro_rules_edition_pm.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/meta-macro.rs b/tests/ui/proc-macro/auxiliary/meta-macro.rs index cbe882c173f6..3436b1944d00 100644 --- a/tests/ui/proc-macro/auxiliary/meta-macro.rs +++ b/tests/ui/proc-macro/auxiliary/meta-macro.rs @@ -1,9 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic //@ edition:2018 #![feature(proc_macro_def_site)] -#![crate_type = "proc-macro"] extern crate proc_macro; extern crate make_macro; diff --git a/tests/ui/proc-macro/auxiliary/mixed-site-span.rs b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs index c143e2d40f3c..d837c88c9556 100644 --- a/tests/ui/proc-macro/auxiliary/mixed-site-span.rs +++ b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs @@ -1,10 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/modify-ast.rs b/tests/ui/proc-macro/auxiliary/modify-ast.rs index 174c588e8bf2..389b09688147 100644 --- a/tests/ui/proc-macro/auxiliary/modify-ast.rs +++ b/tests/ui/proc-macro/auxiliary/modify-ast.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/multiple-derives.rs b/tests/ui/proc-macro/auxiliary/multiple-derives.rs index 84a826cf1f6a..6f03f0a08f0b 100644 --- a/tests/ui/proc-macro/auxiliary/multiple-derives.rs +++ b/tests/ui/proc-macro/auxiliary/multiple-derives.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/multispan.rs b/tests/ui/proc-macro/auxiliary/multispan.rs index b5f1ed9b56a9..1eb379d3877d 100644 --- a/tests/ui/proc-macro/auxiliary/multispan.rs +++ b/tests/ui/proc-macro/auxiliary/multispan.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/negative-token.rs b/tests/ui/proc-macro/auxiliary/negative-token.rs index 43355bfd20bb..d3731c1c8cc4 100644 --- a/tests/ui/proc-macro/auxiliary/negative-token.rs +++ b/tests/ui/proc-macro/auxiliary/negative-token.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs index 48ae36001923..96aed8625aa5 100644 --- a/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs +++ b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/not-joint.rs b/tests/ui/proc-macro/auxiliary/not-joint.rs index 5f94805361a6..bc15ced05665 100644 --- a/tests/ui/proc-macro/auxiliary/not-joint.rs +++ b/tests/ui/proc-macro/auxiliary/not-joint.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/parent-source-spans.rs b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs index 3ec92d713325..257d1489ce2a 100644 --- a/tests/ui/proc-macro/auxiliary/parent-source-spans.rs +++ b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs @@ -1,8 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_diagnostic, proc_macro_span)] -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs index 07e135ee8ebe..2b77b45565a8 100644 --- a/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs +++ b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/print-tokens.rs b/tests/ui/proc-macro/auxiliary/print-tokens.rs index 6d25f1f8471a..171ff6e61fbd 100644 --- a/tests/ui/proc-macro/auxiliary/print-tokens.rs +++ b/tests/ui/proc-macro/auxiliary/print-tokens.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree}; diff --git a/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs index cfd6464661ef..8506c9f0de0b 100644 --- a/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs +++ b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, Ident, Span}; diff --git a/tests/ui/proc-macro/auxiliary/raw-ident.rs b/tests/ui/proc-macro/auxiliary/raw-ident.rs index 1fec61797568..7fd73dd97ba5 100644 --- a/tests/ui/proc-macro/auxiliary/raw-ident.rs +++ b/tests/ui/proc-macro/auxiliary/raw-ident.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Ident, Punct, Spacing, Span}; diff --git a/tests/ui/proc-macro/auxiliary/re-export.rs b/tests/ui/proc-macro/auxiliary/re-export.rs index a886015a031d..ae88e2f3e114 100644 --- a/tests/ui/proc-macro/auxiliary/re-export.rs +++ b/tests/ui/proc-macro/auxiliary/re-export.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/recollect.rs b/tests/ui/proc-macro/auxiliary/recollect.rs index 7db29035f714..439f37c88327 100644 --- a/tests/ui/proc-macro/auxiliary/recollect.rs +++ b/tests/ui/proc-macro/auxiliary/recollect.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/proc-macro/auxiliary/resolved-located-at.rs b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs index 032d41688aff..493956c00e98 100644 --- a/tests/ui/proc-macro/auxiliary/resolved-located-at.rs +++ b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs @@ -1,10 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_def_site)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_quote)] -#![crate_type = "proc-macro"] extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs index 16640a32098a..99db66ed6a94 100644 --- a/tests/ui/proc-macro/auxiliary/span-api-tests.rs +++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_span)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs index fdcca29e177b..16ca5e3f9e2d 100644 --- a/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs +++ b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs @@ -1,9 +1,5 @@ -//@ force-host -//@ no-prefer-dynamic - #![feature(proc_macro_quote)] #![feature(proc_macro_internals)] // FIXME - this shouldn't be necessary -#![crate_type = "proc-macro"] extern crate proc_macro; extern crate custom_quote; diff --git a/tests/ui/proc-macro/auxiliary/subspan.rs b/tests/ui/proc-macro/auxiliary/subspan.rs index 69a9c8a9fa84..edfb053d6f10 100644 --- a/tests/ui/proc-macro/auxiliary/subspan.rs +++ b/tests/ui/proc-macro/auxiliary/subspan.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/test-macros.rs b/tests/ui/proc-macro/auxiliary/test-macros.rs index 69a89e94cd6f..8375767d6fb6 100644 --- a/tests/ui/proc-macro/auxiliary/test-macros.rs +++ b/tests/ui/proc-macro/auxiliary/test-macros.rs @@ -1,11 +1,6 @@ -//@ force-host -//@ no-prefer-dynamic - // Proc macros commonly used by tests. // `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree}; diff --git a/tests/ui/proc-macro/auxiliary/three-equals.rs b/tests/ui/proc-macro/auxiliary/three-equals.rs index f0ff0437a8b4..56cfd4a2828c 100644 --- a/tests/ui/proc-macro/auxiliary/three-equals.rs +++ b/tests/ui/proc-macro/auxiliary/three-equals.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)] extern crate proc_macro; diff --git a/tests/ui/proc-macro/auxiliary/weird-hygiene.rs b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs index f401f7d55baa..c37eed360f06 100644 --- a/tests/ui/proc-macro/auxiliary/weird-hygiene.rs +++ b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{TokenStream, TokenTree, Group}; diff --git a/tests/ui/proc-macro/bang-macro.rs b/tests/ui/proc-macro/bang-macro.rs index 03d4174d652b..2287e34c5dda 100644 --- a/tests/ui/proc-macro/bang-macro.rs +++ b/tests/ui/proc-macro/bang-macro.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:bang-macro.rs +//@ proc-macro: bang-macro.rs extern crate bang_macro; use bang_macro::rewrite; diff --git a/tests/ui/proc-macro/break-token-spans.rs b/tests/ui/proc-macro/break-token-spans.rs index ae90e04e0812..efbd0c0d7e23 100644 --- a/tests/ui/proc-macro/break-token-spans.rs +++ b/tests/ui/proc-macro/break-token-spans.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Regression test for issues #68489 and #70987 // Tests that we properly break tokens in `probably_equal_for_proc_macro` // See #72306 diff --git a/tests/ui/proc-macro/call-deprecated.rs b/tests/ui/proc-macro/call-deprecated.rs index 1779e33f3b1b..fc9354331cce 100644 --- a/tests/ui/proc-macro/call-deprecated.rs +++ b/tests/ui/proc-macro/call-deprecated.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:call-deprecated.rs +//@ proc-macro: call-deprecated.rs extern crate call_deprecated; diff --git a/tests/ui/proc-macro/call-site.rs b/tests/ui/proc-macro/call-site.rs index 31fa78902d5d..9c285e1ed117 100644 --- a/tests/ui/proc-macro/call-site.rs +++ b/tests/ui/proc-macro/call-site.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:call-site.rs +//@ proc-macro: call-site.rs extern crate call_site; diff --git a/tests/ui/proc-macro/capture-macro-rules-invoke.rs b/tests/ui/proc-macro/capture-macro-rules-invoke.rs index 71a290c1fc06..101461854c4a 100644 --- a/tests/ui/proc-macro/capture-macro-rules-invoke.rs +++ b/tests/ui/proc-macro/capture-macro-rules-invoke.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass //@ compile-flags: -Z span-debug diff --git a/tests/ui/proc-macro/capture-unglued-token.rs b/tests/ui/proc-macro/capture-unglued-token.rs index 32286ed084c2..586fb934931d 100644 --- a/tests/ui/proc-macro/capture-unglued-token.rs +++ b/tests/ui/proc-macro/capture-unglued-token.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ check-pass diff --git a/tests/ui/proc-macro/cfg-eval-inner.rs b/tests/ui/proc-macro/cfg-eval-inner.rs index d0a6c1afa230..7493f3ea5236 100644 --- a/tests/ui/proc-macro/cfg-eval-inner.rs +++ b/tests/ui/proc-macro/cfg-eval-inner.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass #![feature(cfg_eval)] diff --git a/tests/ui/proc-macro/cfg-eval.rs b/tests/ui/proc-macro/cfg-eval.rs index bbf11949e7e3..1d9b4f23ea5c 100644 --- a/tests/ui/proc-macro/cfg-eval.rs +++ b/tests/ui/proc-macro/cfg-eval.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(cfg_eval)] #![feature(proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/count_compound_ops.rs b/tests/ui/proc-macro/count_compound_ops.rs index e58c36e047db..20b0b87817e2 100644 --- a/tests/ui/proc-macro/count_compound_ops.rs +++ b/tests/ui/proc-macro/count_compound_ops.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:count_compound_ops.rs +//@ proc-macro: count_compound_ops.rs extern crate count_compound_ops; use count_compound_ops::count_compound_ops; diff --git a/tests/ui/proc-macro/crate-attrs-multiple.rs b/tests/ui/proc-macro/crate-attrs-multiple.rs index 24f46b0a2fab..ebd14590a215 100644 --- a/tests/ui/proc-macro/crate-attrs-multiple.rs +++ b/tests/ui/proc-macro/crate-attrs-multiple.rs @@ -1,7 +1,7 @@ // Multiple custom crate-level attributes, both inert and active. //@ check-pass -//@ aux-crate:test_macros=test-macros.rs +//@ proc-macro: test-macros.rs #![feature(custom_inner_attributes)] #![feature(prelude_import)] diff --git a/tests/ui/proc-macro/crate-var.rs b/tests/ui/proc-macro/crate-var.rs index 7388ca683580..cea5d48e0806 100644 --- a/tests/ui/proc-macro/crate-var.rs +++ b/tests/ui/proc-macro/crate-var.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:double.rs +//@ proc-macro: double.rs //@ aux-build:external-crate-var.rs #![allow(unused)] diff --git a/tests/ui/proc-macro/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/custom-attr-only-one-derive.rs index 2616c122a659..f0e82f367579 100644 --- a/tests/ui/proc-macro/custom-attr-only-one-derive.rs +++ b/tests/ui/proc-macro/custom-attr-only-one-derive.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:custom-attr-only-one-derive.rs +//@ proc-macro: custom-attr-only-one-derive.rs #[macro_use] extern crate custom_attr_only_one_derive; diff --git a/tests/ui/proc-macro/custom-attr-panic.rs b/tests/ui/proc-macro/custom-attr-panic.rs index 23bcb66319d2..560af228c2ae 100644 --- a/tests/ui/proc-macro/custom-attr-panic.rs +++ b/tests/ui/proc-macro/custom-attr-panic.rs @@ -1,4 +1,4 @@ -//@ aux-build: test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; diff --git a/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs index 2d7bff836815..1e261ea32130 100644 --- a/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs +++ b/tests/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] #![crate_name = "macro_dump_debug"] extern crate proc_macro; diff --git a/tests/ui/proc-macro/debug/dump-debug-span-debug.rs b/tests/ui/proc-macro/debug/dump-debug-span-debug.rs index d4d9199bf3b0..618e13c0f15e 100644 --- a/tests/ui/proc-macro/debug/dump-debug-span-debug.rs +++ b/tests/ui/proc-macro/debug/dump-debug-span-debug.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-dump-debug.rs +//@ proc-macro: macro-dump-debug.rs //@ compile-flags: -Z span-debug diff --git a/tests/ui/proc-macro/debug/dump-debug.rs b/tests/ui/proc-macro/debug/dump-debug.rs index 7a5cc979df9b..b20cd2dc948a 100644 --- a/tests/ui/proc-macro/debug/dump-debug.rs +++ b/tests/ui/proc-macro/debug/dump-debug.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-dump-debug.rs +//@ proc-macro: macro-dump-debug.rs extern crate macro_dump_debug; use macro_dump_debug::dump_debug; diff --git a/tests/ui/proc-macro/debug/dump-debug.stderr b/tests/ui/proc-macro/debug/dump-debug.stderr index 6aefacacd002..abcbfbfd5ec0 100644 --- a/tests/ui/proc-macro/debug/dump-debug.stderr +++ b/tests/ui/proc-macro/debug/dump-debug.stderr @@ -1,166 +1,166 @@ -TokenStream [Ident { ident: "ident", span: #0 bytes(132..137) }, Ident { ident: "r#ident", span: #0 bytes(153..160) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(178..179) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(205..206) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(206..207) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(207..208) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(232..234) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(260..261) }], span: #0 bytes(259..262) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(317..318) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(323..326) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(331..334) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(339..343) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(348..352) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(357..365) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(370..376) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(381..391) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(396..399) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(404..408) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(439..441) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(446..450) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(455..459) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(464..469) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(474..479) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(484..493) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(498..505) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(510..521) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(526..530) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(535..540) }] +TokenStream [Ident { ident: "ident", span: #0 bytes(134..139) }, Ident { ident: "r#ident", span: #0 bytes(155..162) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(180..181) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(207..208) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(208..209) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(209..210) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(234..236) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(262..263) }], span: #0 bytes(261..264) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(319..320) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(325..328) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(333..336) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(341..345) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(350..354) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(359..367) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(372..378) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(383..393) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(398..401) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(406..410) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(441..443) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(448..452) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(457..461) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(466..471) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(476..481) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(486..495) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(500..507) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(512..523) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(528..532) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(537..542) }] TokenStream [ Ident { ident: "ident", - span: #0 bytes(132..137), + span: #0 bytes(134..139), }, Ident { ident: "r#ident", - span: #0 bytes(153..160), + span: #0 bytes(155..162), }, Punct { ch: ',', spacing: Alone, - span: #0 bytes(178..179), + span: #0 bytes(180..181), }, Punct { ch: '=', spacing: Joint, - span: #0 bytes(205..206), + span: #0 bytes(207..208), }, Punct { ch: '=', spacing: Joint, - span: #0 bytes(206..207), + span: #0 bytes(208..209), }, Punct { ch: '>', spacing: Alone, - span: #0 bytes(207..208), + span: #0 bytes(209..210), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: #0 bytes(232..234), + span: #0 bytes(234..236), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "_", - span: #0 bytes(260..261), + span: #0 bytes(262..263), }, ], - span: #0 bytes(259..262), + span: #0 bytes(261..264), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(317..318), + span: #0 bytes(319..320), }, Literal { kind: Float, symbol: "1.0", suffix: None, - span: #0 bytes(323..326), + span: #0 bytes(325..328), }, Literal { kind: Str, symbol: "S", suffix: None, - span: #0 bytes(331..334), + span: #0 bytes(333..336), }, Literal { kind: ByteStr, symbol: "B", suffix: None, - span: #0 bytes(339..343), + span: #0 bytes(341..345), }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, - span: #0 bytes(348..352), + span: #0 bytes(350..354), }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, - span: #0 bytes(357..365), + span: #0 bytes(359..367), }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, - span: #0 bytes(370..376), + span: #0 bytes(372..378), }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, - span: #0 bytes(381..391), + span: #0 bytes(383..393), }, Literal { kind: Char, symbol: "C", suffix: None, - span: #0 bytes(396..399), + span: #0 bytes(398..401), }, Literal { kind: Byte, symbol: "B", suffix: None, - span: #0 bytes(404..408), + span: #0 bytes(406..410), }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), - span: #0 bytes(439..441), + span: #0 bytes(441..443), }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), - span: #0 bytes(446..450), + span: #0 bytes(448..452), }, Literal { kind: Str, symbol: "S", suffix: Some("q"), - span: #0 bytes(455..459), + span: #0 bytes(457..461), }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), - span: #0 bytes(464..469), + span: #0 bytes(466..471), }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), - span: #0 bytes(474..479), + span: #0 bytes(476..481), }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), - span: #0 bytes(484..493), + span: #0 bytes(486..495), }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), - span: #0 bytes(498..505), + span: #0 bytes(500..507), }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), - span: #0 bytes(510..521), + span: #0 bytes(512..523), }, Literal { kind: Char, symbol: "C", suffix: Some("q"), - span: #0 bytes(526..530), + span: #0 bytes(528..532), }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), - span: #0 bytes(535..540), + span: #0 bytes(537..542), }, ] diff --git a/tests/ui/proc-macro/derive-attr-cfg.rs b/tests/ui/proc-macro/derive-attr-cfg.rs index 162be0754d91..2f3516cabae9 100644 --- a/tests/ui/proc-macro/derive-attr-cfg.rs +++ b/tests/ui/proc-macro/derive-attr-cfg.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:derive-attr-cfg.rs +//@ proc-macro: derive-attr-cfg.rs extern crate derive_attr_cfg; use derive_attr_cfg::Foo; diff --git a/tests/ui/proc-macro/derive-b.rs b/tests/ui/proc-macro/derive-b.rs index 6cbe1fd0a3f8..68d341478f18 100644 --- a/tests/ui/proc-macro/derive-b.rs +++ b/tests/ui/proc-macro/derive-b.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:derive-b-rpass.rs +//@ proc-macro: derive-b-rpass.rs extern crate derive_b_rpass as derive_b; diff --git a/tests/ui/proc-macro/derive-bad.rs b/tests/ui/proc-macro/derive-bad.rs index c8f3a77ea4c5..9b237c731dbe 100644 --- a/tests/ui/proc-macro/derive-bad.rs +++ b/tests/ui/proc-macro/derive-bad.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-bad.rs +//@ proc-macro: derive-bad.rs #[macro_use] extern crate derive_bad; diff --git a/tests/ui/proc-macro/derive-expand-order.rs b/tests/ui/proc-macro/derive-expand-order.rs index 75981f16a7fd..076590bdb4cd 100644 --- a/tests/ui/proc-macro/derive-expand-order.rs +++ b/tests/ui/proc-macro/derive-expand-order.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:multiple-derives.rs +//@ proc-macro: multiple-derives.rs extern crate multiple_derives; diff --git a/tests/ui/proc-macro/derive-helper-configured.rs b/tests/ui/proc-macro/derive-helper-configured.rs index 45e6e64d392c..b753e29b8bf3 100644 --- a/tests/ui/proc-macro/derive-helper-configured.rs +++ b/tests/ui/proc-macro/derive-helper-configured.rs @@ -1,7 +1,7 @@ // Derive helpers are resolved successfully inside `cfg_attr`. //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-helper-legacy-limits.rs b/tests/ui/proc-macro/derive-helper-legacy-limits.rs index ff09095a60f9..76b09f33ecc0 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-limits.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-limits.rs @@ -2,7 +2,7 @@ // (that's exactly the reason why they are deprecated). //@ edition:2018 -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs index 2b5bb905e830..8e902f304193 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![dummy] //~ ERROR cannot find attribute `dummy` in this scope diff --git a/tests/ui/proc-macro/derive-helper-shadowed.rs b/tests/ui/proc-macro/derive-helper-shadowed.rs index 9b2a4ab6bc74..ea2c56b0b73b 100644 --- a/tests/ui/proc-macro/derive-helper-shadowed.rs +++ b/tests/ui/proc-macro/derive-helper-shadowed.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ aux-build:derive-helper-shadowed-2.rs #[macro_use] diff --git a/tests/ui/proc-macro/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/derive-helper-shadowing-2.rs index dc35dd05498b..6aba061acf35 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing-2.rs +++ b/tests/ui/proc-macro/derive-helper-shadowing-2.rs @@ -2,7 +2,7 @@ // then make sure that it's usable without ambiguities. //@ check-pass -//@ aux-build:derive-helper-shadowing-2.rs +//@ proc-macro: derive-helper-shadowing-2.rs #[macro_use] extern crate derive_helper_shadowing_2; diff --git a/tests/ui/proc-macro/derive-helper-shadowing.rs b/tests/ui/proc-macro/derive-helper-shadowing.rs index 1c66a60b294b..e774e4640538 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.rs +++ b/tests/ui/proc-macro/derive-helper-shadowing.rs @@ -1,6 +1,6 @@ //@ edition:2018 -//@ aux-build:test-macros.rs -//@ aux-build:derive-helper-shadowing.rs +//@ proc-macro: test-macros.rs +//@ proc-macro: derive-helper-shadowing.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-helper-vs-legacy.rs b/tests/ui/proc-macro/derive-helper-vs-legacy.rs index feae7adda68f..83917a2fbf70 100644 --- a/tests/ui/proc-macro/derive-helper-vs-legacy.rs +++ b/tests/ui/proc-macro/derive-helper-vs-legacy.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-in-mod.rs b/tests/ui/proc-macro/derive-in-mod.rs index 3bd70f1090d0..7ec7cf62fb40 100644 --- a/tests/ui/proc-macro/derive-in-mod.rs +++ b/tests/ui/proc-macro/derive-in-mod.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-same-struct.rs b/tests/ui/proc-macro/derive-same-struct.rs index 432476d1ebb1..f7669ba1480b 100644 --- a/tests/ui/proc-macro/derive-same-struct.rs +++ b/tests/ui/proc-macro/derive-same-struct.rs @@ -2,7 +2,7 @@ #![allow(path_statements)] #![allow(dead_code)] -//@ aux-build:derive-same-struct.rs +//@ proc-macro: derive-same-struct.rs #[macro_use] extern crate derive_same_struct; diff --git a/tests/ui/proc-macro/derive-still-gated.rs b/tests/ui/proc-macro/derive-still-gated.rs index bce7badeffe1..518ed9d51be8 100644 --- a/tests/ui/proc-macro/derive-still-gated.rs +++ b/tests/ui/proc-macro/derive-still-gated.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/derive-two-attrs.rs b/tests/ui/proc-macro/derive-two-attrs.rs index 911160976658..33a8fef2ac7b 100644 --- a/tests/ui/proc-macro/derive-two-attrs.rs +++ b/tests/ui/proc-macro/derive-two-attrs.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:derive-two-attrs.rs +//@ proc-macro: derive-two-attrs.rs extern crate derive_two_attrs as foo; diff --git a/tests/ui/proc-macro/derive-union.rs b/tests/ui/proc-macro/derive-union.rs index d1e65bf45957..e0fe9dee85cb 100644 --- a/tests/ui/proc-macro/derive-union.rs +++ b/tests/ui/proc-macro/derive-union.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_variables)] -//@ aux-build:derive-union.rs +//@ proc-macro: derive-union.rs #[macro_use] extern crate derive_union; diff --git a/tests/ui/proc-macro/disappearing-resolution.rs b/tests/ui/proc-macro/disappearing-resolution.rs index b8bc2953576a..8e7fa85eba15 100644 --- a/tests/ui/proc-macro/disappearing-resolution.rs +++ b/tests/ui/proc-macro/disappearing-resolution.rs @@ -1,6 +1,6 @@ // Regression test for issue #64803 (initial attribute resolution can disappear later). -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/disappearing-resolution.stderr b/tests/ui/proc-macro/disappearing-resolution.stderr index e6d0868687e2..e66f721444fc 100644 --- a/tests/ui/proc-macro/disappearing-resolution.stderr +++ b/tests/ui/proc-macro/disappearing-resolution.stderr @@ -16,7 +16,7 @@ note: the derive macro import `Empty` is defined here... LL | use test_macros::Empty; | ^^^^^^^^^^^^^^^^^^ note: ...and refers to the derive macro `Empty` which is defined here - --> $DIR/auxiliary/test-macros.rs:25:1 + --> $DIR/auxiliary/test-macros.rs:20:1 | LL | pub fn empty_derive(_: TokenStream) -> TokenStream { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly diff --git a/tests/ui/proc-macro/doc-comment-preserved.rs b/tests/ui/proc-macro/doc-comment-preserved.rs index f0891e7d6a74..a4bfd105d36e 100644 --- a/tests/ui/proc-macro/doc-comment-preserved.rs +++ b/tests/ui/proc-macro/doc-comment-preserved.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/dollar-crate-issue-101211.rs b/tests/ui/proc-macro/dollar-crate-issue-101211.rs index fd5768dc7d1c..ca871d57a691 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-101211.rs +++ b/tests/ui/proc-macro/dollar-crate-issue-101211.rs @@ -1,6 +1,6 @@ //@ check-pass //@ edition:2021 -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/dollar-crate-issue-57089.rs b/tests/ui/proc-macro/dollar-crate-issue-57089.rs index d4540643e029..52f41b78375f 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-57089.rs +++ b/tests/ui/proc-macro/dollar-crate-issue-57089.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/dollar-crate-issue-62325.rs b/tests/ui/proc-macro/dollar-crate-issue-62325.rs index ee2e0c3973dc..716bf6790fe6 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-62325.rs +++ b/tests/ui/proc-macro/dollar-crate-issue-62325.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ aux-build:dollar-crate-external.rs diff --git a/tests/ui/proc-macro/dollar-crate.rs b/tests/ui/proc-macro/dollar-crate.rs index a487e77a8331..0d13bbd8967b 100644 --- a/tests/ui/proc-macro/dollar-crate.rs +++ b/tests/ui/proc-macro/dollar-crate.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ aux-build:dollar-crate-external.rs #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs index 0f302708537e..e4878a93af12 100644 --- a/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs +++ b/tests/ui/proc-macro/edition-gated-async-move-syntax-issue89699.rs @@ -1,4 +1,4 @@ -//@ aux-build:edition-gated-async-move-syntax.rs +//@ proc-macro: edition-gated-async-move-syntax.rs //@ edition: 2015 // Non-regression test for issue #89699, where a proc-macro emitting syntax only available in diff --git a/tests/ui/proc-macro/edition-imports-2018.rs b/tests/ui/proc-macro/edition-imports-2018.rs index de05868ebf93..a3808d9dce82 100644 --- a/tests/ui/proc-macro/edition-imports-2018.rs +++ b/tests/ui/proc-macro/edition-imports-2018.rs @@ -1,6 +1,6 @@ //@ check-pass //@ edition:2018 -//@ aux-build:edition-imports-2015.rs +//@ proc-macro: edition-imports-2015.rs #[macro_use] extern crate edition_imports_2015; diff --git a/tests/ui/proc-macro/empty-crate.rs b/tests/ui/proc-macro/empty-crate.rs index ba4de590e636..f82660ac4fd5 100644 --- a/tests/ui/proc-macro/empty-crate.rs +++ b/tests/ui/proc-macro/empty-crate.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_imports)] -//@ aux-build:empty-crate.rs +//@ proc-macro: empty-crate.rs #[macro_use] extern crate empty_crate; diff --git a/tests/ui/proc-macro/empty-where-clause.rs b/tests/ui/proc-macro/empty-where-clause.rs index 4e432934e3cd..770b44515f91 100644 --- a/tests/ui/proc-macro/empty-where-clause.rs +++ b/tests/ui/proc-macro/empty-where-clause.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; use test_macros::recollect_attr; diff --git a/tests/ui/proc-macro/env.rs b/tests/ui/proc-macro/env.rs index 85bcf4521fe6..94e3b09e5269 100644 --- a/tests/ui/proc-macro/env.rs +++ b/tests/ui/proc-macro/env.rs @@ -1,4 +1,4 @@ -//@ aux-build:env.rs +//@ proc-macro: env.rs //@ run-pass //@ rustc-env: THE_CONST=1 //@ compile-flags: -Zunstable-options --env-set THE_CONST=12 --env-set ANOTHER=4 diff --git a/tests/ui/proc-macro/expand-expr.rs b/tests/ui/proc-macro/expand-expr.rs index e06ddc51a297..8a4ed9768d53 100644 --- a/tests/ui/proc-macro/expand-expr.rs +++ b/tests/ui/proc-macro/expand-expr.rs @@ -1,4 +1,4 @@ -//@ aux-build:expand-expr.rs +//@ proc-macro: expand-expr.rs // no-remap-src-base: check_expand_expr_file!() fails when enabled. #![feature(concat_bytes)] diff --git a/tests/ui/proc-macro/expand-to-derive.rs b/tests/ui/proc-macro/expand-to-derive.rs index 0b603cd4bccb..0e38e471980b 100644 --- a/tests/ui/proc-macro/expand-to-derive.rs +++ b/tests/ui/proc-macro/expand-to-derive.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] diff --git a/tests/ui/proc-macro/expand-to-unstable.rs b/tests/ui/proc-macro/expand-to-unstable.rs index c4eaba6bba23..8968471ebd87 100644 --- a/tests/ui/proc-macro/expand-to-unstable.rs +++ b/tests/ui/proc-macro/expand-to-unstable.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-unstable.rs +//@ proc-macro: derive-unstable.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/expand-with-a-macro.rs b/tests/ui/proc-macro/expand-with-a-macro.rs index fcaafbbc1490..e5baf3601db0 100644 --- a/tests/ui/proc-macro/expand-with-a-macro.rs +++ b/tests/ui/proc-macro/expand-with-a-macro.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ aux-build:expand-with-a-macro.rs +//@ proc-macro: expand-with-a-macro.rs #![deny(warnings)] diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs index 0b34b07edbee..6f31c07ff89b 100644 --- a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(decl_macro)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout index 0168689b605f..7555ef8f6329 100644 --- a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout @@ -2,39 +2,39 @@ PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0; 0 }, PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #3 bytes(301..305), + span: #3 bytes(303..307), }, Ident { ident: "E", - span: #3 bytes(306..307), + span: #3 bytes(308..309), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #3 bytes(322..323), + span: #3 bytes(324..325), }, Punct { ch: '=', spacing: Alone, - span: #3 bytes(324..325), + span: #3 bytes(326..327), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #3 bytes(328..331), + span: #3 bytes(330..333), }, Ident { ident: "_", - span: #3 bytes(332..333), + span: #3 bytes(334..335), }, Punct { ch: '=', spacing: Alone, - span: #3 bytes(334..335), + span: #3 bytes(336..337), }, Group { delimiter: None, @@ -42,97 +42,97 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: #0 bytes(543..544), + span: #0 bytes(545..546), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "allow", - span: #0 bytes(545..550), + span: #0 bytes(547..552), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "warnings", - span: #0 bytes(551..559), + span: #0 bytes(553..561), }, ], - span: #0 bytes(550..560), + span: #0 bytes(552..562), }, ], - span: #0 bytes(544..561), + span: #0 bytes(546..563), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(562..563), + span: #0 bytes(564..565), }, ], - span: #3 bytes(336..341), + span: #3 bytes(338..343), }, Punct { ch: ';', spacing: Alone, - span: #3 bytes(341..342), + span: #3 bytes(343..344), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #3 bytes(343..344), + span: #3 bytes(345..346), }, ], - span: #3 bytes(326..346), + span: #3 bytes(328..348), }, Punct { ch: ',', spacing: Alone, - span: #3 bytes(346..347), + span: #3 bytes(348..349), }, ], - span: #3 bytes(308..357), + span: #3 bytes(310..359), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #7 bytes(425..429), + span: #7 bytes(427..431), }, Ident { ident: "E", - span: #7 bytes(430..431), + span: #7 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #7 bytes(446..447), + span: #7 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #7 bytes(448..449), + span: #7 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #7 bytes(452..455), + span: #7 bytes(454..457), }, Ident { ident: "_", - span: #7 bytes(456..457), + span: #7 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #7 bytes(458..459), + span: #7 bytes(460..461), }, Group { delimiter: Brace, @@ -144,74 +144,74 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(580..581), + span: #0 bytes(582..583), }, ], - span: #7 bytes(462..467), + span: #7 bytes(464..469), }, ], - span: #7 bytes(460..469), + span: #7 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #7 bytes(469..470), + span: #7 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #7 bytes(471..472), + span: #7 bytes(473..474), }, ], - span: #7 bytes(450..474), + span: #7 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #7 bytes(474..475), + span: #7 bytes(476..477), }, ], - span: #7 bytes(432..485), + span: #7 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #11 bytes(425..429), + span: #11 bytes(427..431), }, Ident { ident: "E", - span: #11 bytes(430..431), + span: #11 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #11 bytes(446..447), + span: #11 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #11 bytes(448..449), + span: #11 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #11 bytes(452..455), + span: #11 bytes(454..457), }, Ident { ident: "_", - span: #11 bytes(456..457), + span: #11 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #11 bytes(458..459), + span: #11 bytes(460..461), }, Group { delimiter: Brace, @@ -222,74 +222,74 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Group { delimiter: Brace, stream: TokenStream [], - span: #0 bytes(598..600), + span: #0 bytes(600..602), }, ], - span: #11 bytes(462..467), + span: #11 bytes(464..469), }, ], - span: #11 bytes(460..469), + span: #11 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #11 bytes(469..470), + span: #11 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #11 bytes(471..472), + span: #11 bytes(473..474), }, ], - span: #11 bytes(450..474), + span: #11 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #11 bytes(474..475), + span: #11 bytes(476..477), }, ], - span: #11 bytes(432..485), + span: #11 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #15 bytes(425..429), + span: #15 bytes(427..431), }, Ident { ident: "E", - span: #15 bytes(430..431), + span: #15 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #15 bytes(446..447), + span: #15 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #15 bytes(448..449), + span: #15 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #15 bytes(452..455), + span: #15 bytes(454..457), }, Ident { ident: "_", - span: #15 bytes(456..457), + span: #15 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #15 bytes(458..459), + span: #15 bytes(460..461), }, Group { delimiter: Brace, @@ -299,74 +299,74 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "PATH", - span: #0 bytes(617..621), + span: #0 bytes(619..623), }, ], - span: #15 bytes(462..467), + span: #15 bytes(464..469), }, ], - span: #15 bytes(460..469), + span: #15 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #15 bytes(469..470), + span: #15 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #15 bytes(471..472), + span: #15 bytes(473..474), }, ], - span: #15 bytes(450..474), + span: #15 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #15 bytes(474..475), + span: #15 bytes(476..477), }, ], - span: #15 bytes(432..485), + span: #15 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #19 bytes(425..429), + span: #19 bytes(427..431), }, Ident { ident: "E", - span: #19 bytes(430..431), + span: #19 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #19 bytes(446..447), + span: #19 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #19 bytes(448..449), + span: #19 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #19 bytes(452..455), + span: #19 bytes(454..457), }, Ident { ident: "_", - span: #19 bytes(456..457), + span: #19 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #19 bytes(458..459), + span: #19 bytes(460..461), }, Group { delimiter: Brace, @@ -378,85 +378,85 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "0", suffix: None, - span: #0 bytes(638..639), + span: #0 bytes(640..641), }, Punct { ch: '+', spacing: Alone, - span: #0 bytes(640..641), + span: #0 bytes(642..643), }, Literal { kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(642..643), + span: #0 bytes(644..645), }, ], - span: #19 bytes(462..467), + span: #19 bytes(464..469), }, ], - span: #19 bytes(460..469), + span: #19 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #19 bytes(469..470), + span: #19 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #19 bytes(471..472), + span: #19 bytes(473..474), }, ], - span: #19 bytes(450..474), + span: #19 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #19 bytes(474..475), + span: #19 bytes(476..477), }, ], - span: #19 bytes(432..485), + span: #19 bytes(434..487), }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #23 bytes(425..429), + span: #23 bytes(427..431), }, Ident { ident: "E", - span: #23 bytes(430..431), + span: #23 bytes(432..433), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "V", - span: #23 bytes(446..447), + span: #23 bytes(448..449), }, Punct { ch: '=', spacing: Alone, - span: #23 bytes(448..449), + span: #23 bytes(450..451), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "let", - span: #23 bytes(452..455), + span: #23 bytes(454..457), }, Ident { ident: "_", - span: #23 bytes(456..457), + span: #23 bytes(458..459), }, Punct { ch: '=', spacing: Alone, - span: #23 bytes(458..459), + span: #23 bytes(460..461), }, Group { delimiter: Brace, @@ -466,45 +466,45 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "PATH", - span: #0 bytes(660..664), + span: #0 bytes(662..666), }, Punct { ch: '+', spacing: Alone, - span: #0 bytes(665..666), + span: #0 bytes(667..668), }, Literal { kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(667..668), + span: #0 bytes(669..670), }, ], - span: #23 bytes(462..467), + span: #23 bytes(464..469), }, ], - span: #23 bytes(460..469), + span: #23 bytes(462..471), }, Punct { ch: ';', spacing: Alone, - span: #23 bytes(469..470), + span: #23 bytes(471..472), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #23 bytes(471..472), + span: #23 bytes(473..474), }, ], - span: #23 bytes(450..474), + span: #23 bytes(452..476), }, Punct { ch: ',', spacing: Alone, - span: #23 bytes(474..475), + span: #23 bytes(476..477), }, ], - span: #23 bytes(432..485), + span: #23 bytes(434..487), }, ] diff --git a/tests/ui/proc-macro/gen-lifetime-token.rs b/tests/ui/proc-macro/gen-lifetime-token.rs index d65efb5c4647..4296d58df0d5 100644 --- a/tests/ui/proc-macro/gen-lifetime-token.rs +++ b/tests/ui/proc-macro/gen-lifetime-token.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:gen-lifetime-token.rs +//@ proc-macro: gen-lifetime-token.rs extern crate gen_lifetime_token as bar; diff --git a/tests/ui/proc-macro/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/gen-macro-rules-hygiene.rs index 2bfbf9dcccaa..3deec94fa341 100644 --- a/tests/ui/proc-macro/gen-macro-rules-hygiene.rs +++ b/tests/ui/proc-macro/gen-macro-rules-hygiene.rs @@ -2,7 +2,7 @@ // Local variables and labels are hygienic, items are not hygienic. // `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro. -//@ aux-build:gen-macro-rules-hygiene.rs +//@ proc-macro: gen-macro-rules-hygiene.rs #[macro_use] extern crate gen_macro_rules_hygiene; diff --git a/tests/ui/proc-macro/gen-macro-rules.rs b/tests/ui/proc-macro/gen-macro-rules.rs index 5f2cfc70d8ec..121d029e2e34 100644 --- a/tests/ui/proc-macro/gen-macro-rules.rs +++ b/tests/ui/proc-macro/gen-macro-rules.rs @@ -1,7 +1,7 @@ // Derive macros can generate `macro_rules` items, regression test for issue #63651. //@ check-pass -//@ aux-build:gen-macro-rules.rs +//@ proc-macro: gen-macro-rules.rs extern crate gen_macro_rules as repro; diff --git a/tests/ui/proc-macro/generate-dollar-ident.rs b/tests/ui/proc-macro/generate-dollar-ident.rs index c087a206566f..54e872fefb62 100644 --- a/tests/ui/proc-macro/generate-dollar-ident.rs +++ b/tests/ui/proc-macro/generate-dollar-ident.rs @@ -2,7 +2,7 @@ // without it being recognized as an unknown macro variable. //@ check-pass -//@ aux-build:generate-dollar-ident.rs +//@ proc-macro: generate-dollar-ident.rs extern crate generate_dollar_ident; use generate_dollar_ident::*; diff --git a/tests/ui/proc-macro/generate-mod.rs b/tests/ui/proc-macro/generate-mod.rs index ab93666f28af..729bfc1db667 100644 --- a/tests/ui/proc-macro/generate-mod.rs +++ b/tests/ui/proc-macro/generate-mod.rs @@ -1,6 +1,6 @@ // Modules generated by transparent proc macros still acts as barriers for names (issue #50504). -//@ aux-build:generate-mod.rs +//@ proc-macro: generate-mod.rs extern crate generate_mod; diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs index 03bb04b77860..1197dd7f3bfd 100644 --- a/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use(Empty)] extern crate test_macros; diff --git a/tests/ui/proc-macro/helper-attr-blocked-by-import.rs b/tests/ui/proc-macro/helper-attr-blocked-by-import.rs index 03c307834114..53c079fd19cf 100644 --- a/tests/ui/proc-macro/helper-attr-blocked-by-import.rs +++ b/tests/ui/proc-macro/helper-attr-blocked-by-import.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use(Empty)] extern crate test_macros; diff --git a/tests/ui/proc-macro/helper-attr-builtin-derive.rs b/tests/ui/proc-macro/helper-attr-builtin-derive.rs index eb7292e093c3..7d36e055c143 100644 --- a/tests/ui/proc-macro/helper-attr-builtin-derive.rs +++ b/tests/ui/proc-macro/helper-attr-builtin-derive.rs @@ -2,7 +2,7 @@ // other built-in derive macros. // issue: rust-lang/rust#132561 //@ check-pass -//@ aux-build:helper-attr.rs +//@ proc-macro: helper-attr.rs //@ edition:2021 #[macro_use] diff --git a/tests/ui/proc-macro/hygiene_example.rs b/tests/ui/proc-macro/hygiene_example.rs index 6c3e1067436d..84b5e345608a 100644 --- a/tests/ui/proc-macro/hygiene_example.rs +++ b/tests/ui/proc-macro/hygiene_example.rs @@ -1,5 +1,4 @@ //@ check-pass -//@ aux-build:hygiene_example_codegen.rs //@ aux-build:hygiene_example.rs extern crate hygiene_example; diff --git a/tests/ui/proc-macro/import.rs b/tests/ui/proc-macro/import.rs index 53dc0f4cbedc..44a37dad5c53 100644 --- a/tests/ui/proc-macro/import.rs +++ b/tests/ui/proc-macro/import.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs extern crate test_macros; diff --git a/tests/ui/proc-macro/inert-attribute-order.rs b/tests/ui/proc-macro/inert-attribute-order.rs index bca4df960406..5a4eae03594b 100644 --- a/tests/ui/proc-macro/inert-attribute-order.rs +++ b/tests/ui/proc-macro/inert-attribute-order.rs @@ -2,7 +2,7 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs index df006a4d7a93..714463b62250 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs +++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.rs @@ -2,7 +2,7 @@ //@ error-pattern:custom inner attributes are unstable //@ error-pattern:inner macro attributes are unstable //@ error-pattern:this was previously accepted -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/inner-attrs.rs b/tests/ui/proc-macro/inner-attrs.rs index 45bb4d3c5bfe..34c37ddfac35 100644 --- a/tests/ui/proc-macro/inner-attrs.rs +++ b/tests/ui/proc-macro/inner-attrs.rs @@ -1,7 +1,7 @@ // gate-test-custom_inner_attributes //@ compile-flags: -Z span-debug --error-format human //@ error-pattern:expected non-macro inner attribute -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ edition:2018 #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/input-interpolated.rs b/tests/ui/proc-macro/input-interpolated.rs index d84572a6afe7..a20fe72c6d5d 100644 --- a/tests/ui/proc-macro/input-interpolated.rs +++ b/tests/ui/proc-macro/input-interpolated.rs @@ -2,7 +2,7 @@ //@ check-pass //@ edition:2018 -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/input-interpolated.stdout b/tests/ui/proc-macro/input-interpolated.stdout index 1bccd8806be9..b567292ea9a9 100644 --- a/tests/ui/proc-macro/input-interpolated.stdout +++ b/tests/ui/proc-macro/input-interpolated.stdout @@ -2,58 +2,58 @@ PRINT-BANG INPUT (DISPLAY): A PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "A", - span: #0 bytes(506..507), + span: #0 bytes(508..509), }, ] PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "const", - span: #3 bytes(419..424), + span: #3 bytes(421..426), }, Ident { ident: "A", - span: #0 bytes(506..507), + span: #0 bytes(508..509), }, Punct { ch: ':', spacing: Alone, - span: #3 bytes(427..428), + span: #3 bytes(429..430), }, Ident { ident: "u8", - span: #3 bytes(429..431), + span: #3 bytes(431..433), }, Punct { ch: '=', spacing: Alone, - span: #3 bytes(432..433), + span: #3 bytes(434..435), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: #3 bytes(434..435), + span: #3 bytes(436..437), }, Punct { ch: ';', spacing: Alone, - span: #3 bytes(435..436), + span: #3 bytes(437..438), }, ] PRINT-DERIVE INPUT (DISPLAY): struct A {} PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #3 bytes(471..477), + span: #3 bytes(473..479), }, Ident { ident: "A", - span: #0 bytes(506..507), + span: #0 bytes(508..509), }, Group { delimiter: Brace, stream: TokenStream [], - span: #3 bytes(481..483), + span: #3 bytes(483..485), }, ] diff --git a/tests/ui/proc-macro/invalid-punct-ident-1.rs b/tests/ui/proc-macro/invalid-punct-ident-1.rs index b0f163adc02e..e7306a7e8ba8 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-1.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-1.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/invalid-punct-ident-2.rs b/tests/ui/proc-macro/invalid-punct-ident-2.rs index b1f7f570d3f1..14656652e1d3 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-2.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-2.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/invalid-punct-ident-3.rs b/tests/ui/proc-macro/invalid-punct-ident-3.rs index 7698d2c4b394..266e8d3d9258 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-3.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-3.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/invalid-punct-ident-4.rs b/tests/ui/proc-macro/invalid-punct-ident-4.rs index 042fe6c600da..dbffddd15857 100644 --- a/tests/ui/proc-macro/invalid-punct-ident-4.rs +++ b/tests/ui/proc-macro/invalid-punct-ident-4.rs @@ -1,4 +1,4 @@ -//@ aux-build:invalid-punct-ident.rs +//@ proc-macro: invalid-punct-ident.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/is-available.rs b/tests/ui/proc-macro/is-available.rs index 36fd44b266f7..faee560d7a97 100644 --- a/tests/ui/proc-macro/is-available.rs +++ b/tests/ui/proc-macro/is-available.rs @@ -2,7 +2,7 @@ extern crate proc_macro; -//@ aux-build:is-available.rs +//@ proc-macro: is-available.rs extern crate is_available; fn main() { diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index 29793e9f7347..abdd6bf136dc 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-104884.rs +//@ proc-macro: issue-104884.rs use std::collections::BinaryHeap; diff --git a/tests/ui/proc-macro/issue-107113-wrap.rs b/tests/ui/proc-macro/issue-107113-wrap.rs index 01bf3615acfe..2799e79bb1cb 100644 --- a/tests/ui/proc-macro/issue-107113-wrap.rs +++ b/tests/ui/proc-macro/issue-107113-wrap.rs @@ -1,5 +1,5 @@ //@ edition:2021 -//@ aux-build:issue-107113.rs +//@ proc-macro: issue-107113.rs #[macro_use] extern crate issue_107113; diff --git a/tests/ui/proc-macro/issue-118809.rs b/tests/ui/proc-macro/issue-118809.rs index 770b19e81721..a6a3956981a7 100644 --- a/tests/ui/proc-macro/issue-118809.rs +++ b/tests/ui/proc-macro/issue-118809.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-118809.rs +//@ proc-macro: issue-118809.rs #[macro_use] extern crate issue_118809; diff --git a/tests/ui/proc-macro/issue-36935.rs b/tests/ui/proc-macro/issue-36935.rs index eb019d1e1740..51d85c7dfa94 100644 --- a/tests/ui/proc-macro/issue-36935.rs +++ b/tests/ui/proc-macro/issue-36935.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/issue-37788.rs b/tests/ui/proc-macro/issue-37788.rs index c32ab6b8116e..b44525b3b20e 100644 --- a/tests/ui/proc-macro/issue-37788.rs +++ b/tests/ui/proc-macro/issue-37788.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/issue-38586.rs b/tests/ui/proc-macro/issue-38586.rs index 54d5d1038a62..88dbb8037beb 100644 --- a/tests/ui/proc-macro/issue-38586.rs +++ b/tests/ui/proc-macro/issue-38586.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-38586.rs +//@ proc-macro: issue-38586.rs #[macro_use] extern crate issue_38586; diff --git a/tests/ui/proc-macro/issue-39889.rs b/tests/ui/proc-macro/issue-39889.rs index 687aefbc068a..a10fa02e14a8 100644 --- a/tests/ui/proc-macro/issue-39889.rs +++ b/tests/ui/proc-macro/issue-39889.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code, unused_macros)] -//@ aux-build:issue-39889.rs +//@ proc-macro: issue-39889.rs extern crate issue_39889; use issue_39889::Issue39889; diff --git a/tests/ui/proc-macro/issue-42708.rs b/tests/ui/proc-macro/issue-42708.rs index 27cb2f73d562..9eb616008de5 100644 --- a/tests/ui/proc-macro/issue-42708.rs +++ b/tests/ui/proc-macro/issue-42708.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:issue-42708.rs +//@ proc-macro: issue-42708.rs #![feature(decl_macro)] #![allow(unused)] diff --git a/tests/ui/proc-macro/issue-50061.rs b/tests/ui/proc-macro/issue-50061.rs index 34999bb50702..8a660c2f3506 100644 --- a/tests/ui/proc-macro/issue-50061.rs +++ b/tests/ui/proc-macro/issue-50061.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(path_statements)] -//@ aux-build:issue-50061.rs +//@ proc-macro: issue-50061.rs #![feature(decl_macro)] diff --git a/tests/ui/proc-macro/issue-50493.rs b/tests/ui/proc-macro/issue-50493.rs index 5456eddb78d0..e23f1f7c7d87 100644 --- a/tests/ui/proc-macro/issue-50493.rs +++ b/tests/ui/proc-macro/issue-50493.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-50493.rs +//@ proc-macro: issue-50493.rs #[macro_use] extern crate issue_50493; diff --git a/tests/ui/proc-macro/issue-53481.rs b/tests/ui/proc-macro/issue-53481.rs index 636b8e0c0ae5..11e11e2e6b6d 100644 --- a/tests/ui/proc-macro/issue-53481.rs +++ b/tests/ui/proc-macro/issue-53481.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs index 24e3be0ed2e4..c1b55fd99dfa 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -2,7 +2,7 @@ // `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`. //@ edition:2018 -//@ aux-crate:issue_59191=issue-59191.rs +//@ proc-macro: issue-59191.rs //@ error-pattern: requires `sized` lang_item #![feature(custom_inner_attributes)] diff --git a/tests/ui/proc-macro/issue-66286.rs b/tests/ui/proc-macro/issue-66286.rs index 3ca064768b2d..57d1af26e934 100644 --- a/tests/ui/proc-macro/issue-66286.rs +++ b/tests/ui/proc-macro/issue-66286.rs @@ -1,4 +1,4 @@ -//@ aux-build:issue-66286.rs +//@ proc-macro: issue-66286.rs // Regression test for #66286. diff --git a/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs b/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs index 8f07cd34cc9e..3421d13f4d9d 100644 --- a/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs +++ b/tests/ui/proc-macro/issue-73933-procedural-masquerade.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass #[macro_use] diff --git a/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout index 5e39c01ab5e2..83a3f5809583 100644 --- a/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout +++ b/tests/ui/proc-macro/issue-73933-procedural-masquerade.stdout @@ -2,20 +2,20 @@ PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", - span: #0 bytes(102..106), + span: #0 bytes(104..108), }, Ident { ident: "ProceduralMasqueradeDummyType", - span: #0 bytes(107..136), + span: #0 bytes(109..138), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "Input", - span: #0 bytes(143..148), + span: #0 bytes(145..150), }, ], - span: #0 bytes(137..150), + span: #0 bytes(139..152), }, ] diff --git a/tests/ui/proc-macro/issue-75734-pp-paren.rs b/tests/ui/proc-macro/issue-75734-pp-paren.rs index ab0f4f72e62d..d084c4a2873b 100644 --- a/tests/ui/proc-macro/issue-75734-pp-paren.rs +++ b/tests/ui/proc-macro/issue-75734-pp-paren.rs @@ -3,7 +3,7 @@ // normally insert extra parentheses. //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/issue-75801.rs b/tests/ui/proc-macro/issue-75801.rs index f0a1940cb5c1..feda5e60b0d4 100644 --- a/tests/ui/proc-macro/issue-75801.rs +++ b/tests/ui/proc-macro/issue-75801.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-75801.rs +//@ proc-macro: issue-75801.rs // Regression test for #75801. diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.rs b/tests/ui/proc-macro/issue-75930-derive-cfg.rs index f480de24e3e4..376a8ea42783 100644 --- a/tests/ui/proc-macro/issue-75930-derive-cfg.rs +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Regression test for issue #75930 // Tests that we cfg-strip all targets before invoking diff --git a/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs b/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs index dc40a1715a68..218debf3e7ce 100644 --- a/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs +++ b/tests/ui/proc-macro/issue-76182-leading-vert-pat.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug // // Regression test for issue #76182 diff --git a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs index 001a09fc5523..2a003c30bf9f 100644 --- a/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs +++ b/tests/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs @@ -1,4 +1,4 @@ -//@ aux-build:proc-macro-panic.rs +//@ proc-macro: proc-macro-panic.rs //@ edition:2018 //@ needs-unwind proc macro panics to report errors diff --git a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs index d3716b22729f..63e8af310272 100644 --- a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs +++ b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/issue-79148.rs b/tests/ui/proc-macro/issue-79148.rs index 96ee5e033e16..b2248759b5f8 100644 --- a/tests/ui/proc-macro/issue-79148.rs +++ b/tests/ui/proc-macro/issue-79148.rs @@ -1,4 +1,4 @@ -//@ aux-build:re-export.rs +//@ proc-macro: re-export.rs //@ edition:2018 extern crate re_export; diff --git a/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs b/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs index d0c14d8b5d09..3306bc21e3a9 100644 --- a/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs +++ b/tests/ui/proc-macro/issue-79242-slow-retokenize-check.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-79242.rs +//@ proc-macro: issue-79242.rs // Regression test for issue #79242 // Tests that compilation time doesn't blow up for a proc-macro diff --git a/tests/ui/proc-macro/issue-79825.rs b/tests/ui/proc-macro/issue-79825.rs index f846bb404864..67b79172bb3b 100644 --- a/tests/ui/proc-macro/issue-79825.rs +++ b/tests/ui/proc-macro/issue-79825.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-79825.rs +//@ proc-macro: issue-79825.rs #![feature(trait_alias)] extern crate issue_79825; diff --git a/tests/ui/proc-macro/issue-80760-empty-stmt.rs b/tests/ui/proc-macro/issue-80760-empty-stmt.rs index 59244e12eb8d..b940da6778a0 100644 --- a/tests/ui/proc-macro/issue-80760-empty-stmt.rs +++ b/tests/ui/proc-macro/issue-80760-empty-stmt.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/issue-81007-item-attrs.rs b/tests/ui/proc-macro/issue-81007-item-attrs.rs index ab47c9df0817..f3b8aa8c7c5a 100644 --- a/tests/ui/proc-macro/issue-81007-item-attrs.rs +++ b/tests/ui/proc-macro/issue-81007-item-attrs.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] diff --git a/tests/ui/proc-macro/issue-81543-item-parse-err.rs b/tests/ui/proc-macro/issue-81543-item-parse-err.rs index f3c307318a0b..6cd8c0d6c40a 100644 --- a/tests/ui/proc-macro/issue-81543-item-parse-err.rs +++ b/tests/ui/proc-macro/issue-81543-item-parse-err.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Regression test for issue #81543 // Tests that we emit a properly spanned error diff --git a/tests/ui/proc-macro/issue-81555.rs b/tests/ui/proc-macro/issue-81555.rs index 7a61a31952f4..bbc7542cb24a 100644 --- a/tests/ui/proc-macro/issue-81555.rs +++ b/tests/ui/proc-macro/issue-81555.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(stmt_expr_attributes, proc_macro_hygiene)] extern crate test_macros; diff --git a/tests/ui/proc-macro/issue-83510.rs b/tests/ui/proc-macro/issue-83510.rs index ea8a334f57c5..67469511fc36 100644 --- a/tests/ui/proc-macro/issue-83510.rs +++ b/tests/ui/proc-macro/issue-83510.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-83510.rs +//@ proc-macro: issue-83510.rs extern crate issue_83510; diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed index 367ad66a1a62..b8b3e6f3f7e3 100644 --- a/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.fixed @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ run-rustfix #[macro_use] diff --git a/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs b/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs index c49619ef2ac7..ce1a0da6cad7 100644 --- a/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs +++ b/tests/ui/proc-macro/issue-86781-bad-inner-doc.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ run-rustfix #[macro_use] diff --git a/tests/ui/proc-macro/issue-91800.rs b/tests/ui/proc-macro/issue-91800.rs index b69fce4cf773..bc78bcacfd0f 100644 --- a/tests/ui/proc-macro/issue-91800.rs +++ b/tests/ui/proc-macro/issue-91800.rs @@ -1,4 +1,4 @@ -//@ aux-build: issue-91800-macro.rs +//@ proc-macro: issue-91800-macro.rs #[macro_use] extern crate issue_91800_macro; diff --git a/tests/ui/proc-macro/item-error.rs b/tests/ui/proc-macro/item-error.rs index f3e3eafcd8d1..5f798faf436a 100644 --- a/tests/ui/proc-macro/item-error.rs +++ b/tests/ui/proc-macro/item-error.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-b.rs +//@ proc-macro: derive-b.rs #![allow(warnings)] diff --git a/tests/ui/proc-macro/keep-expr-tokens.rs b/tests/ui/proc-macro/keep-expr-tokens.rs index ced7fad47b92..2bd66da90e27 100644 --- a/tests/ui/proc-macro/keep-expr-tokens.rs +++ b/tests/ui/proc-macro/keep-expr-tokens.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/lifetimes-rpass.rs b/tests/ui/proc-macro/lifetimes-rpass.rs index a6b1f46a5d1a..c462b27722f7 100644 --- a/tests/ui/proc-macro/lifetimes-rpass.rs +++ b/tests/ui/proc-macro/lifetimes-rpass.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(unused_variables)] -//@ aux-build:lifetimes-rpass.rs +//@ proc-macro: lifetimes-rpass.rs extern crate lifetimes_rpass as lifetimes; use lifetimes::*; diff --git a/tests/ui/proc-macro/lifetimes.rs b/tests/ui/proc-macro/lifetimes.rs index 0c5d3e2f72fa..cfff3cb1785d 100644 --- a/tests/ui/proc-macro/lifetimes.rs +++ b/tests/ui/proc-macro/lifetimes.rs @@ -1,4 +1,4 @@ -//@ aux-build:lifetimes.rs +//@ proc-macro: lifetimes.rs extern crate lifetimes; diff --git a/tests/ui/proc-macro/lints_in_proc_macros.rs b/tests/ui/proc-macro/lints_in_proc_macros.rs index 13ae7239a143..6714b8b6e1d5 100644 --- a/tests/ui/proc-macro/lints_in_proc_macros.rs +++ b/tests/ui/proc-macro/lints_in_proc_macros.rs @@ -1,4 +1,4 @@ -//@ aux-build:bang_proc_macro2.rs +//@ proc-macro: bang_proc_macro2.rs extern crate bang_proc_macro2; diff --git a/tests/ui/proc-macro/literal-to-string.rs b/tests/ui/proc-macro/literal-to-string.rs index e87315fe1449..7a56e08109c5 100644 --- a/tests/ui/proc-macro/literal-to-string.rs +++ b/tests/ui/proc-macro/literal-to-string.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition: 2021 -//@ aux-build: print-tokens.rs +//@ proc-macro: print-tokens.rs extern crate print_tokens; fn main() { diff --git a/tests/ui/proc-macro/literal-to-string.stdout b/tests/ui/proc-macro/literal-to-string.stdout index c3114265e0a8..18c0c20dde4e 100644 --- a/tests/ui/proc-macro/literal-to-string.stdout +++ b/tests/ui/proc-macro/literal-to-string.stdout @@ -3,91 +3,91 @@ TokenStream [ kind: Integer, symbol: "1", suffix: None, - span: #0 bytes(147..148), + span: #0 bytes(148..149), }, Literal { kind: Integer, symbol: "17", suffix: Some("u8"), - span: #0 bytes(157..161), + span: #0 bytes(158..162), }, Literal { kind: Float, symbol: "42.", suffix: None, - span: #0 bytes(170..173), + span: #0 bytes(171..174), }, Literal { kind: Float, symbol: "3.14", suffix: Some("f32"), - span: #0 bytes(182..189), + span: #0 bytes(183..190), }, Literal { kind: Byte, symbol: "a", suffix: None, - span: #0 bytes(198..202), + span: #0 bytes(199..203), }, Literal { kind: Byte, symbol: "\xFF", suffix: None, - span: #0 bytes(211..218), + span: #0 bytes(212..219), }, Literal { kind: Char, symbol: "c", suffix: None, - span: #0 bytes(227..230), + span: #0 bytes(228..231), }, Literal { kind: Char, symbol: "\x32", suffix: None, - span: #0 bytes(239..245), + span: #0 bytes(240..246), }, Literal { kind: Str, symbol: "\\"str\\"", suffix: None, - span: #0 bytes(254..263), + span: #0 bytes(255..264), }, Literal { kind: StrRaw(1), symbol: "\"raw\" str", suffix: None, - span: #0 bytes(272..286), + span: #0 bytes(273..287), }, Literal { kind: StrRaw(3), symbol: "very ##\"raw\"## str", suffix: None, - span: #0 bytes(295..322), + span: #0 bytes(296..323), }, Literal { kind: ByteStr, symbol: "\\"byte\\" str", suffix: None, - span: #0 bytes(331..346), + span: #0 bytes(332..347), }, Literal { kind: ByteStrRaw(1), symbol: "\"raw\" \"byte\" str", suffix: None, - span: #0 bytes(355..377), + span: #0 bytes(356..378), }, Literal { kind: CStr, symbol: "\\"c\\" str", suffix: None, - span: #0 bytes(386..398), + span: #0 bytes(387..399), }, Literal { kind: CStrRaw(1), symbol: "\"raw\" \"c\" str", suffix: None, - span: #0 bytes(407..426), + span: #0 bytes(408..427), }, ] 1 diff --git a/tests/ui/proc-macro/load-panic-backtrace.rs b/tests/ui/proc-macro/load-panic-backtrace.rs index 15badedef973..302bcaea75e6 100644 --- a/tests/ui/proc-macro/load-panic-backtrace.rs +++ b/tests/ui/proc-macro/load-panic-backtrace.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z proc-macro-backtrace //@ rustc-env:RUST_BACKTRACE=0 //@ normalize-stderr-test: "thread '.*' panicked " -> "" diff --git a/tests/ui/proc-macro/load-panic-backtrace.stderr b/tests/ui/proc-macro/load-panic-backtrace.stderr index 18f513586726..0f3db6c831e1 100644 --- a/tests/ui/proc-macro/load-panic-backtrace.stderr +++ b/tests/ui/proc-macro/load-panic-backtrace.stderr @@ -1,4 +1,4 @@ -at $DIR/auxiliary/test-macros.rs:43:5: +at $DIR/auxiliary/test-macros.rs:38:5: panic-derive error: proc-macro derive panicked --> $DIR/load-panic-backtrace.rs:11:10 diff --git a/tests/ui/proc-macro/load-panic.rs b/tests/ui/proc-macro/load-panic.rs index 50475a34226b..18bfb71050b3 100644 --- a/tests/ui/proc-macro/load-panic.rs +++ b/tests/ui/proc-macro/load-panic.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ needs-unwind proc macro panics to report errors #[macro_use] diff --git a/tests/ui/proc-macro/load-two.rs b/tests/ui/proc-macro/load-two.rs index 44fcdb056dd6..608379949e66 100644 --- a/tests/ui/proc-macro/load-two.rs +++ b/tests/ui/proc-macro/load-two.rs @@ -2,8 +2,8 @@ #![allow(path_statements)] #![allow(dead_code)] -//@ aux-build:derive-atob.rs -//@ aux-build:derive-ctod.rs +//@ proc-macro: derive-atob.rs +//@ proc-macro: derive-ctod.rs #[macro_use] extern crate derive_atob; diff --git a/tests/ui/proc-macro/macro-brackets.rs b/tests/ui/proc-macro/macro-brackets.rs index 91bd652d37b8..70686eed0bd6 100644 --- a/tests/ui/proc-macro/macro-brackets.rs +++ b/tests/ui/proc-macro/macro-brackets.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macro-crate-multi-decorator.rs b/tests/ui/proc-macro/macro-crate-multi-decorator.rs index 26a2d1592aba..c4f02e7adfcb 100644 --- a/tests/ui/proc-macro/macro-crate-multi-decorator.rs +++ b/tests/ui/proc-macro/macro-crate-multi-decorator.rs @@ -1,7 +1,7 @@ // The duplicate macro will create a copy of the item with the given identifier. //@ check-pass -//@ aux-build:duplicate.rs +//@ proc-macro: duplicate.rs #[macro_use] extern crate duplicate; diff --git a/tests/ui/proc-macro/macro-quote-cond.rs b/tests/ui/proc-macro/macro-quote-cond.rs index 3658e2a28f2a..062511eec9bc 100644 --- a/tests/ui/proc-macro/macro-quote-cond.rs +++ b/tests/ui/proc-macro/macro-quote-cond.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:cond_plugin.rs +//@ proc-macro: cond_plugin.rs #![allow(unused_parens)] diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.rs b/tests/ui/proc-macro/macro-rules-derive-cfg.rs index c34f1695761c..ab504bc63a29 100644 --- a/tests/ui/proc-macro/macro-rules-derive-cfg.rs +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/macro-rules-derive.rs b/tests/ui/proc-macro/macro-rules-derive.rs index 4023a9a044aa..c4e906fb5ede 100644 --- a/tests/ui/proc-macro/macro-rules-derive.rs +++ b/tests/ui/proc-macro/macro-rules-derive.rs @@ -1,4 +1,4 @@ -//@ aux-build:first-second.rs +//@ proc-macro: first-second.rs extern crate first_second; use first_second::*; diff --git a/tests/ui/proc-macro/macro-use-attr.rs b/tests/ui/proc-macro/macro-use-attr.rs index fe071b263838..b2d4b9e6ffa6 100644 --- a/tests/ui/proc-macro/macro-use-attr.rs +++ b/tests/ui/proc-macro/macro-use-attr.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macro-use-bang.rs b/tests/ui/proc-macro/macro-use-bang.rs index f8ccba6b0941..9397baff1d67 100644 --- a/tests/ui/proc-macro/macro-use-bang.rs +++ b/tests/ui/proc-macro/macro-use-bang.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macro_rules_edition_from_pm.rs b/tests/ui/proc-macro/macro_rules_edition_from_pm.rs index 3ba80f5177a9..57ed54fd1dfb 100644 --- a/tests/ui/proc-macro/macro_rules_edition_from_pm.rs +++ b/tests/ui/proc-macro/macro_rules_edition_from_pm.rs @@ -2,7 +2,7 @@ // proc-macro. // See https://github.com/rust-lang/rust/issues/132906 -//@ aux-crate: macro_rules_edition_pm=macro_rules_edition_pm.rs +//@ proc-macro: macro_rules_edition_pm.rs //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 diff --git a/tests/ui/proc-macro/macros-in-extern.rs b/tests/ui/proc-macro/macros-in-extern.rs index da384d1b141e..f39322d126e0 100644 --- a/tests/ui/proc-macro/macros-in-extern.rs +++ b/tests/ui/proc-macro/macros-in-extern.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/macros-in-type.rs b/tests/ui/proc-macro/macros-in-type.rs index 4db7cf273f70..1874bb80db35 100644 --- a/tests/ui/proc-macro/macros-in-type.rs +++ b/tests/ui/proc-macro/macros-in-type.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/meta-macro-hygiene.rs b/tests/ui/proc-macro/meta-macro-hygiene.rs index 98496d5a4c60..9fbe9763b44d 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.rs +++ b/tests/ui/proc-macro/meta-macro-hygiene.rs @@ -1,5 +1,5 @@ //@ aux-build:make-macro.rs -//@ aux-build:meta-macro.rs +//@ proc-macro: meta-macro.rs //@ edition:2018 //@ compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no //@ check-pass diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index 3c6ec6fbdd4b..ae02b24e1d0e 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -3,7 +3,7 @@ Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:26 Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4) }] #![feature /* 0#0 */(prelude_import)] //@ aux-build:make-macro.rs -//@ aux-build:meta-macro.rs +//@ proc-macro: meta-macro.rs //@ edition:2018 //@ compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no //@ check-pass diff --git a/tests/ui/proc-macro/meta-macro.rs b/tests/ui/proc-macro/meta-macro.rs index abe63c60fb8d..02ef45c0c21f 100644 --- a/tests/ui/proc-macro/meta-macro.rs +++ b/tests/ui/proc-macro/meta-macro.rs @@ -1,5 +1,5 @@ //@ aux-build:make-macro.rs -//@ aux-build:meta-macro.rs +//@ proc-macro: meta-macro.rs //@ edition:2018 //@ compile-flags: -Z span-debug //@ run-pass diff --git a/tests/ui/proc-macro/mixed-site-span.rs b/tests/ui/proc-macro/mixed-site-span.rs index bab76a8c4331..2b5d97570438 100644 --- a/tests/ui/proc-macro/mixed-site-span.rs +++ b/tests/ui/proc-macro/mixed-site-span.rs @@ -1,6 +1,6 @@ // Proc macros using `mixed_site` spans exhibit usual properties of `macro_rules` hygiene. -//@ aux-build:mixed-site-span.rs +//@ proc-macro: mixed-site-span.rs #[macro_use] extern crate mixed_site_span; diff --git a/tests/ui/proc-macro/modify-ast.rs b/tests/ui/proc-macro/modify-ast.rs index 4c125c1c6e8f..9e890f3ebaad 100644 --- a/tests/ui/proc-macro/modify-ast.rs +++ b/tests/ui/proc-macro/modify-ast.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:modify-ast.rs +//@ proc-macro: modify-ast.rs extern crate modify_ast; diff --git a/tests/ui/proc-macro/multispan.rs b/tests/ui/proc-macro/multispan.rs index 60f67c8c67c0..e06aa9f7c5ad 100644 --- a/tests/ui/proc-macro/multispan.rs +++ b/tests/ui/proc-macro/multispan.rs @@ -1,4 +1,4 @@ -//@ aux-build:multispan.rs +//@ proc-macro: multispan.rs extern crate multispan; diff --git a/tests/ui/proc-macro/negative-token.rs b/tests/ui/proc-macro/negative-token.rs index 32408e0d9367..8c6fa9ca6893 100644 --- a/tests/ui/proc-macro/negative-token.rs +++ b/tests/ui/proc-macro/negative-token.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:negative-token.rs +//@ proc-macro: negative-token.rs extern crate negative_token; diff --git a/tests/ui/proc-macro/nested-derive-cfg.rs b/tests/ui/proc-macro/nested-derive-cfg.rs index 696a5024ec2a..bd8f231ac2c2 100644 --- a/tests/ui/proc-macro/nested-derive-cfg.rs +++ b/tests/ui/proc-macro/nested-derive-cfg.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z span-debug --error-format human -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/nested-item-spans.rs b/tests/ui/proc-macro/nested-item-spans.rs index c19af0f9796a..f7e2365586d5 100644 --- a/tests/ui/proc-macro/nested-item-spans.rs +++ b/tests/ui/proc-macro/nested-item-spans.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/nested-macro-rules.rs b/tests/ui/proc-macro/nested-macro-rules.rs index 2f0d85c4bbf8..95a38e4c1b6a 100644 --- a/tests/ui/proc-macro/nested-macro-rules.rs +++ b/tests/ui/proc-macro/nested-macro-rules.rs @@ -1,6 +1,6 @@ //@ run-pass //@ aux-build:nested-macro-rules.rs -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug -Z macro-backtrace //@ edition:2018 diff --git a/tests/ui/proc-macro/nested-nonterminal-tokens.rs b/tests/ui/proc-macro/nested-nonterminal-tokens.rs index 6e28cabd2fe6..630e33dbd83c 100644 --- a/tests/ui/proc-macro/nested-nonterminal-tokens.rs +++ b/tests/ui/proc-macro/nested-nonterminal-tokens.rs @@ -1,7 +1,7 @@ //@ check-pass //@ edition:2018 //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // Tests that we properly pass tokens to proc-macro when nested // nonterminals are involved. diff --git a/tests/ui/proc-macro/no-macro-use-attr.rs b/tests/ui/proc-macro/no-macro-use-attr.rs index ae507a31ba78..d44f51bfd8d4 100644 --- a/tests/ui/proc-macro/no-macro-use-attr.rs +++ b/tests/ui/proc-macro/no-macro-use-attr.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(rustc_attrs)] #![warn(unused_extern_crates)] diff --git a/tests/ui/proc-macro/nodelim-groups.rs b/tests/ui/proc-macro/nodelim-groups.rs index f13d97aaff57..9acdc7023c08 100644 --- a/tests/ui/proc-macro/nodelim-groups.rs +++ b/tests/ui/proc-macro/nodelim-groups.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ edition:2018 // diff --git a/tests/ui/proc-macro/nonterminal-expansion.rs b/tests/ui/proc-macro/nonterminal-expansion.rs index 96ea4aef85b4..99a68996c309 100644 --- a/tests/ui/proc-macro/nonterminal-expansion.rs +++ b/tests/ui/proc-macro/nonterminal-expansion.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/nonterminal-recollect-attr.rs index 7d922bafdcdb..3f3348b18c1f 100644 --- a/tests/ui/proc-macro/nonterminal-recollect-attr.rs +++ b/tests/ui/proc-macro/nonterminal-recollect-attr.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Z span-debug -//@ aux-build:nonterminal-recollect-attr.rs +//@ proc-macro: nonterminal-recollect-attr.rs #![no_std] // Don't load unnecessary hygiene information from std extern crate std; diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.rs b/tests/ui/proc-macro/nonterminal-token-hygiene.rs index 6a4406b053d5..76c71441c808 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.rs +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.rs @@ -7,7 +7,7 @@ //@ normalize-stdout-test: "\d+#" -> "0#" //@ normalize-stdout-test: "expn\d{3,}" -> "expnNNN" //@ normalize-stdout-test: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */" -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(decl_macro)] #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index de3265e92814..1ad140590281 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -31,7 +31,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ //@ normalize-stdout-test: "\d+#" -> "0#" //@ normalize-stdout-test: "expn\d{3,}" -> "expnNNN" //@ normalize-stdout-test: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */" -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature /* 0#0 */(decl_macro)] #![no_std /* 0#0 */] diff --git a/tests/ui/proc-macro/not-joint.rs b/tests/ui/proc-macro/not-joint.rs index 16b89bc6e819..c585e7e33dc3 100644 --- a/tests/ui/proc-macro/not-joint.rs +++ b/tests/ui/proc-macro/not-joint.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:not-joint.rs +//@ proc-macro: not-joint.rs extern crate not_joint as bar; use bar::{tokens, nothing}; diff --git a/tests/ui/proc-macro/out-of-line-mod.rs b/tests/ui/proc-macro/out-of-line-mod.rs index 2a4fb16a09ad..efe9588bef66 100644 --- a/tests/ui/proc-macro/out-of-line-mod.rs +++ b/tests/ui/proc-macro/out-of-line-mod.rs @@ -1,7 +1,7 @@ // Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818). //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/parent-source-spans.rs b/tests/ui/proc-macro/parent-source-spans.rs index 12a1ab1a43d5..cc3ac795f7f1 100644 --- a/tests/ui/proc-macro/parent-source-spans.rs +++ b/tests/ui/proc-macro/parent-source-spans.rs @@ -1,4 +1,4 @@ -//@ aux-build:parent-source-spans.rs +//@ proc-macro: parent-source-spans.rs #![feature(decl_macro)] diff --git a/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs index 3d5af5fee217..2dc322024653 100644 --- a/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs +++ b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs @@ -1,4 +1,4 @@ -//@ aux-build:parse-invis-delim-issue-128895.rs +//@ proc-macro: parse-invis-delim-issue-128895.rs //@ check-pass #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/pretty-print-hack-hide.rs b/tests/ui/proc-macro/pretty-print-hack-hide.rs index 26db43341ab7..fd98f16a780e 100644 --- a/tests/ui/proc-macro/pretty-print-hack-hide.rs +++ b/tests/ui/proc-macro/pretty-print-hack-hide.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ check-pass diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs index 1b6794ae6986..de6453c6a821 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.rs +++ b/tests/ui/proc-macro/pretty-print-hack-show.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug //@ revisions: local remapped // [local] no-remap-src-base: The hack should work regardless of remapping. diff --git a/tests/ui/proc-macro/pretty-print-tts.rs b/tests/ui/proc-macro/pretty-print-tts.rs index e3240e27c2a0..b1b4f278e2a3 100644 --- a/tests/ui/proc-macro/pretty-print-tts.rs +++ b/tests/ui/proc-macro/pretty-print-tts.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![feature(rustc_attrs)] diff --git a/tests/ui/proc-macro/proc-macro-attributes.rs b/tests/ui/proc-macro/proc-macro-attributes.rs index 6d5e7b67c782..455fcc56e58b 100644 --- a/tests/ui/proc-macro/proc-macro-attributes.rs +++ b/tests/ui/proc-macro/proc-macro-attributes.rs @@ -1,4 +1,4 @@ -//@ aux-build:derive-b.rs +//@ proc-macro: derive-b.rs #[macro_use] extern crate derive_b; diff --git a/tests/ui/proc-macro/proc-macro-gates.rs b/tests/ui/proc-macro/proc-macro-gates.rs index 585d9a3c9be3..bf384bc479b5 100644 --- a/tests/ui/proc-macro/proc-macro-gates.rs +++ b/tests/ui/proc-macro/proc-macro-gates.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs // gate-test-proc_macro_hygiene #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/proc-macro-gates2.rs b/tests/ui/proc-macro/proc-macro-gates2.rs index 76d8036d8a44..450f64982b01 100644 --- a/tests/ui/proc-macro/proc-macro-gates2.rs +++ b/tests/ui/proc-macro/proc-macro-gates2.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![feature(stmt_expr_attributes)] diff --git a/tests/ui/proc-macro/raw-ident.rs b/tests/ui/proc-macro/raw-ident.rs index 2ea2d3079dc0..95ada295f5c0 100644 --- a/tests/ui/proc-macro/raw-ident.rs +++ b/tests/ui/proc-macro/raw-ident.rs @@ -1,4 +1,4 @@ -//@ aux-build:raw-ident.rs +//@ proc-macro: raw-ident.rs #[macro_use] extern crate raw_ident; diff --git a/tests/ui/proc-macro/resolve-error.rs b/tests/ui/proc-macro/resolve-error.rs index 2670d8884ae7..0ca250194f01 100644 --- a/tests/ui/proc-macro/resolve-error.rs +++ b/tests/ui/proc-macro/resolve-error.rs @@ -1,6 +1,6 @@ -//@ aux-build:derive-foo.rs -//@ aux-build:derive-clona.rs -//@ aux-build:test-macros.rs +//@ proc-macro: derive-foo.rs +//@ proc-macro: derive-clona.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate derive_foo; diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr index e7639f474c75..963298311ef5 100644 --- a/tests/ui/proc-macro/resolve-error.stderr +++ b/tests/ui/proc-macro/resolve-error.stderr @@ -4,7 +4,7 @@ error: cannot find macro `bang_proc_macrp` in this scope LL | bang_proc_macrp!(); | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro` | - ::: $DIR/auxiliary/test-macros.rs:15:1 + ::: $DIR/auxiliary/test-macros.rs:10:1 | LL | pub fn empty(_: TokenStream) -> TokenStream { | ------------------------------------------- similarly named macro `bang_proc_macro` defined here @@ -53,7 +53,7 @@ error: cannot find derive macro `Dlona` in this scope LL | #[derive(Dlona)] | ^^^^^ help: a derive macro with a similar name exists: `Clona` | - ::: $DIR/auxiliary/derive-clona.rs:11:1 + ::: $DIR/auxiliary/derive-clona.rs:6:1 | LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { | ------------------------------------------------------- similarly named derive macro `Clona` defined here @@ -64,7 +64,7 @@ error: cannot find derive macro `Dlona` in this scope LL | #[derive(Dlona)] | ^^^^^ help: a derive macro with a similar name exists: `Clona` | - ::: $DIR/auxiliary/derive-clona.rs:11:1 + ::: $DIR/auxiliary/derive-clona.rs:6:1 | LL | pub fn derive_clonea(input: TokenStream) -> TokenStream { | ------------------------------------------------------- similarly named derive macro `Clona` defined here @@ -103,7 +103,7 @@ error: cannot find attribute `attr_proc_macra` in this scope LL | #[attr_proc_macra] | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro` | - ::: $DIR/auxiliary/test-macros.rs:20:1 + ::: $DIR/auxiliary/test-macros.rs:15:1 | LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here @@ -114,7 +114,7 @@ error: cannot find derive macro `FooWithLongNan` in this scope LL | #[derive(FooWithLongNan)] | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` | - ::: $DIR/auxiliary/derive-foo.rs:11:1 + ::: $DIR/auxiliary/derive-foo.rs:6:1 | LL | pub fn derive_foo(input: TokenStream) -> TokenStream { | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here @@ -125,7 +125,7 @@ error: cannot find derive macro `FooWithLongNan` in this scope LL | #[derive(FooWithLongNan)] | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName` | - ::: $DIR/auxiliary/derive-foo.rs:11:1 + ::: $DIR/auxiliary/derive-foo.rs:6:1 | LL | pub fn derive_foo(input: TokenStream) -> TokenStream { | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here diff --git a/tests/ui/proc-macro/resolved-located-at.rs b/tests/ui/proc-macro/resolved-located-at.rs index 2f906d91e6b2..c932c4018968 100644 --- a/tests/ui/proc-macro/resolved-located-at.rs +++ b/tests/ui/proc-macro/resolved-located-at.rs @@ -1,4 +1,4 @@ -//@ aux-build:resolved-located-at.rs +//@ proc-macro: resolved-located-at.rs #[macro_use] extern crate resolved_located_at; diff --git a/tests/ui/proc-macro/shadow.rs b/tests/ui/proc-macro/shadow.rs index 22aecb7c05fc..bcb38f97dbfa 100644 --- a/tests/ui/proc-macro/shadow.rs +++ b/tests/ui/proc-macro/shadow.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/smoke.rs b/tests/ui/proc-macro/smoke.rs index dc32adb2e27a..667112837c19 100644 --- a/tests/ui/proc-macro/smoke.rs +++ b/tests/ui/proc-macro/smoke.rs @@ -2,7 +2,7 @@ #![allow(unused_must_use)] #![allow(path_statements)] -//@ aux-build:derive-a.rs +//@ proc-macro: derive-a.rs #[macro_use] extern crate derive_a; diff --git a/tests/ui/proc-macro/span-absolute-posititions.rs b/tests/ui/proc-macro/span-absolute-posititions.rs index ddbc5902d6b0..fc9f06a9e9fc 100644 --- a/tests/ui/proc-macro/span-absolute-posititions.rs +++ b/tests/ui/proc-macro/span-absolute-posititions.rs @@ -1,4 +1,4 @@ -//@ aux-build:assert-span-pos.rs +//@ proc-macro: assert-span-pos.rs // ignore-tidy-tab extern crate assert_span_pos; diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs index 1e00f3ad7ac6..ac42a7ea611a 100644 --- a/tests/ui/proc-macro/span-api-tests.rs +++ b/tests/ui/proc-macro/span-api-tests.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:span-api-tests.rs +//@ proc-macro: span-api-tests.rs //@ aux-build:span-test-macros.rs //@ compile-flags: -Ztranslate-remapped-path-to-local-path=yes diff --git a/tests/ui/proc-macro/span-from-proc-macro.rs b/tests/ui/proc-macro/span-from-proc-macro.rs index 9d851d62d126..4e12a695a5c0 100644 --- a/tests/ui/proc-macro/span-from-proc-macro.rs +++ b/tests/ui/proc-macro/span-from-proc-macro.rs @@ -1,5 +1,5 @@ -//@ aux-build:custom-quote.rs -//@ aux-build:span-from-proc-macro.rs +//@ proc-macro: custom-quote.rs +//@ proc-macro: span-from-proc-macro.rs //@ compile-flags: -Z macro-backtrace #[macro_use] diff --git a/tests/ui/proc-macro/span-from-proc-macro.stderr b/tests/ui/proc-macro/span-from-proc-macro.stderr index 7beed505a7ef..452c04df8779 100644 --- a/tests/ui/proc-macro/span-from-proc-macro.stderr +++ b/tests/ui/proc-macro/span-from-proc-macro.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `MissingType` in this scope - --> $DIR/auxiliary/span-from-proc-macro.rs:37:20 + --> $DIR/auxiliary/span-from-proc-macro.rs:33:20 | LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]` @@ -13,7 +13,7 @@ LL | #[error_from_attribute] | ----------------------- in this procedural macro expansion error[E0412]: cannot find type `OtherMissingType` in this scope - --> $DIR/auxiliary/span-from-proc-macro.rs:46:21 + --> $DIR/auxiliary/span-from-proc-macro.rs:42:21 | LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream { | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]` @@ -27,7 +27,7 @@ LL | #[derive(ErrorFromDerive)] | --------------- in this derive macro expansion error[E0425]: cannot find value `my_ident` in this scope - --> $DIR/auxiliary/span-from-proc-macro.rs:29:9 + --> $DIR/auxiliary/span-from-proc-macro.rs:25:9 | LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream { | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!` @@ -41,7 +41,7 @@ LL | other_error_from_bang!(); | ------------------------ in this macro invocation error[E0308]: mismatched types - --> $DIR/auxiliary/span-from-proc-macro.rs:16:36 + --> $DIR/auxiliary/span-from-proc-macro.rs:12:36 | LL | let bang_error: bool = 25; | ---- ^^ expected `bool`, found integer diff --git a/tests/ui/proc-macro/span-preservation.rs b/tests/ui/proc-macro/span-preservation.rs index 25a44505c772..fc9148656786 100644 --- a/tests/ui/proc-macro/span-preservation.rs +++ b/tests/ui/proc-macro/span-preservation.rs @@ -1,7 +1,7 @@ // For each of these, we should get the appropriate type mismatch error message, // and the function should be echoed. -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #[macro_use] extern crate test_macros; diff --git a/tests/ui/proc-macro/struct-field-macro.rs b/tests/ui/proc-macro/struct-field-macro.rs index b2c3dd49de94..9b1ddcaf2745 100644 --- a/tests/ui/proc-macro/struct-field-macro.rs +++ b/tests/ui/proc-macro/struct-field-macro.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:derive-nothing.rs +//@ proc-macro: derive-nothing.rs #[macro_use] extern crate derive_nothing; diff --git a/tests/ui/proc-macro/subspan.rs b/tests/ui/proc-macro/subspan.rs index 78804cba342d..a87b11f3288a 100644 --- a/tests/ui/proc-macro/subspan.rs +++ b/tests/ui/proc-macro/subspan.rs @@ -1,4 +1,4 @@ -//@ aux-build:subspan.rs +//@ proc-macro: subspan.rs extern crate subspan; diff --git a/tests/ui/proc-macro/test.rs b/tests/ui/proc-macro/test.rs index 9e76deab9ce4..b36910a414b1 100644 --- a/tests/ui/proc-macro/test.rs +++ b/tests/ui/proc-macro/test.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:api/mod.rs +//@ proc-macro: api/proc_macro_api_tests.rs //@ edition: 2021 //! This is for everything that *would* be a #[test] inside of libproc_macro, diff --git a/tests/ui/proc-macro/three-equals.rs b/tests/ui/proc-macro/three-equals.rs index d16fc55656ce..ad528e144b03 100644 --- a/tests/ui/proc-macro/three-equals.rs +++ b/tests/ui/proc-macro/three-equals.rs @@ -1,4 +1,4 @@ -//@ aux-build:three-equals.rs +//@ proc-macro: three-equals.rs extern crate three_equals; diff --git a/tests/ui/proc-macro/trailing-plus.rs b/tests/ui/proc-macro/trailing-plus.rs index 875225c15cae..a69ec510bed6 100644 --- a/tests/ui/proc-macro/trailing-plus.rs +++ b/tests/ui/proc-macro/trailing-plus.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ compile-flags: -Z span-debug #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/trait-fn-args-2015.rs b/tests/ui/proc-macro/trait-fn-args-2015.rs index 389bb5b6a92f..c25bd768efe7 100644 --- a/tests/ui/proc-macro/trait-fn-args-2015.rs +++ b/tests/ui/proc-macro/trait-fn-args-2015.rs @@ -1,7 +1,7 @@ // Unnamed arguments in trait functions can be passed through proc macros on 2015 edition. //@ check-pass -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs #![allow(anonymous_parameters)] diff --git a/tests/ui/proc-macro/unsafe-foreign-mod.rs b/tests/ui/proc-macro/unsafe-foreign-mod.rs index b863b0fc1140..e1e4ce96f1ff 100644 --- a/tests/ui/proc-macro/unsafe-foreign-mod.rs +++ b/tests/ui/proc-macro/unsafe-foreign-mod.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-only-syntax.rs +//@ proc-macro: macro-only-syntax.rs extern crate macro_only_syntax; diff --git a/tests/ui/proc-macro/unsafe-mod.rs b/tests/ui/proc-macro/unsafe-mod.rs index 00ea388af932..f8453c2f62cd 100644 --- a/tests/ui/proc-macro/unsafe-mod.rs +++ b/tests/ui/proc-macro/unsafe-mod.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ aux-build:macro-only-syntax.rs +//@ proc-macro: macro-only-syntax.rs #![feature(proc_macro_hygiene)] diff --git a/tests/ui/proc-macro/weird-braces.rs b/tests/ui/proc-macro/weird-braces.rs index b17b90742b50..1197156f6b03 100644 --- a/tests/ui/proc-macro/weird-braces.rs +++ b/tests/ui/proc-macro/weird-braces.rs @@ -1,4 +1,4 @@ -//@ aux-build:test-macros.rs +//@ proc-macro: test-macros.rs //@ check-pass //@ compile-flags: -Z span-debug diff --git a/tests/ui/proc-macro/weird-hygiene.rs b/tests/ui/proc-macro/weird-hygiene.rs index 8b35898a4d20..de55484109ae 100644 --- a/tests/ui/proc-macro/weird-hygiene.rs +++ b/tests/ui/proc-macro/weird-hygiene.rs @@ -1,4 +1,4 @@ -//@ aux-build:weird-hygiene.rs +//@ proc-macro: weird-hygiene.rs #![feature(stmt_expr_attributes)] #![feature(proc_macro_hygiene)] diff --git a/tests/ui/resolve/auxiliary/issue-112831-aux.rs b/tests/ui/resolve/auxiliary/issue-112831-aux.rs index e5c1486d8ae7..7d258299c186 100644 --- a/tests/ui/resolve/auxiliary/issue-112831-aux.rs +++ b/tests/ui/resolve/auxiliary/issue-112831-aux.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; struct Zeroable; diff --git a/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs index c0b24706dcba..9a9e0eb3ff75 100644 --- a/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs +++ b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -//@ compile-flags: --crate-type proc-macro - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/resolve/derive-macro-1.rs b/tests/ui/resolve/derive-macro-1.rs index f4fbb1d2c7c1..d39eeba2e6c8 100644 --- a/tests/ui/resolve/derive-macro-1.rs +++ b/tests/ui/resolve/derive-macro-1.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-112831-aux.rs +//@ proc-macro: issue-112831-aux.rs mod z { pub trait Zeroable {} diff --git a/tests/ui/resolve/derive-macro-2.rs b/tests/ui/resolve/derive-macro-2.rs index 126f5ae107ff..71d791eaef8d 100644 --- a/tests/ui/resolve/derive-macro-2.rs +++ b/tests/ui/resolve/derive-macro-2.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:issue-112831-aux.rs +//@ proc-macro: issue-112831-aux.rs extern crate issue_112831_aux; use issue_112831_aux::Zeroable; diff --git a/tests/ui/resolve/proc_macro_generated_packed.rs b/tests/ui/resolve/proc_macro_generated_packed.rs index e8d04f808d03..8459fb79f1ed 100644 --- a/tests/ui/resolve/proc_macro_generated_packed.rs +++ b/tests/ui/resolve/proc_macro_generated_packed.rs @@ -1,7 +1,7 @@ //! This test ICEs because the `repr(packed)` attribute //! was generated by a proc macro, so `#[derive]` didn't see it. -//@aux-build: proc_macro_generate_packed.rs +//@proc-macro: proc_macro_generate_packed.rs //@known-bug: #120873 //@ failure-status: 101 //@ normalize-stderr-test: "note: .*\n\n" -> "" diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs index 93c2901fe66c..176ba837043b 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/ident-mac.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs index c427cf7af6d6..9a813666c331 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs b/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs index 17b59009bb84..cd97587bf033 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs @@ -1,4 +1,4 @@ -//@ aux-build:param-attrs.rs +//@ proc-macro: param-attrs.rs //@ check-pass diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs index 6ed2d4fad0ee..89864348eda0 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-pretty.rs @@ -1,4 +1,4 @@ -//@ aux-build:param-attrs.rs +//@ proc-macro: param-attrs.rs //@ check-pass diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs index c1e6a92e3174..049c5b32cb36 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -1,4 +1,4 @@ -//@ aux-build:ident-mac.rs +//@ proc-macro: ident-mac.rs #![feature(c_variadic)] #![allow(anonymous_parameters)] diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs index e7c560a2c351..aebf8d1e0fca 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs @@ -1,7 +1,4 @@ -//@ force-host //@ edition: 2018 -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs index 57c1ba055608..414d5518e1fb 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs @@ -6,7 +6,7 @@ //@ edition: 2021 //@ check-pass -//@ aux-build: count.rs +//@ proc-macro: count.rs extern crate count; const _: () = { diff --git a/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs index d8e5eb884cfc..bccde8e8de7f 100644 --- a/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs +++ b/tests/ui/rust-2018/auxiliary/suggestions-not-always-applicable.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed index f94bf2d66d38..e3070ba150b6 100644 --- a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed +++ b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed @@ -1,4 +1,4 @@ -//@ aux-build:suggestions-not-always-applicable.rs +//@ proc-macro: suggestions-not-always-applicable.rs //@ edition:2015 //@ run-rustfix //@ rustfix-only-machine-applicable diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/suggestions-not-always-applicable.rs index f94bf2d66d38..e3070ba150b6 100644 --- a/tests/ui/rust-2018/suggestions-not-always-applicable.rs +++ b/tests/ui/rust-2018/suggestions-not-always-applicable.rs @@ -1,4 +1,4 @@ -//@ aux-build:suggestions-not-always-applicable.rs +//@ proc-macro: suggestions-not-always-applicable.rs //@ edition:2015 //@ run-rustfix //@ rustfix-only-machine-applicable diff --git a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs index 1273969c4af3..469c2e7f8d9e 100644 --- a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs +++ b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2018.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2018 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs index b68701a51652..cfc39d5208ba 100644 --- a/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs +++ b/tests/ui/rust-2021/auxiliary/reserved-prefixes-macro-2021.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2021 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs index b64761b55e98..6c0c7b38c014 100644 --- a/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro-2.rs @@ -1,6 +1,6 @@ //@ edition:2018 -//@ aux-build:reserved-prefixes-macro-2018.rs -//@ aux-build:reserved-prefixes-macro-2021.rs +//@ proc-macro: reserved-prefixes-macro-2018.rs +//@ proc-macro: reserved-prefixes-macro-2021.rs extern crate reserved_prefixes_macro_2018 as m2018; extern crate reserved_prefixes_macro_2021 as m2021; diff --git a/tests/ui/rust-2021/reserved-prefixes-via-macro.rs b/tests/ui/rust-2021/reserved-prefixes-via-macro.rs index 85f894d7f797..eec1b859c203 100644 --- a/tests/ui/rust-2021/reserved-prefixes-via-macro.rs +++ b/tests/ui/rust-2021/reserved-prefixes-via-macro.rs @@ -1,6 +1,6 @@ //@ run-pass //@ edition:2021 -//@ aux-build:reserved-prefixes-macro-2018.rs +//@ proc-macro: reserved-prefixes-macro-2018.rs extern crate reserved_prefixes_macro_2018 as m2018; diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs index 81080fcdce30..ab23e63c0da9 100644 --- a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2021 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs index aa655942150a..0fa908411f5f 100644 --- a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs @@ -1,8 +1,4 @@ -//@ force-host //@ edition:2024 -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] extern crate proc_macro; diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs index 3f9f373ba227..6b0103d4a500 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs @@ -1,6 +1,6 @@ //@ edition:2021 -//@ aux-build:reserved-guarded-strings-macro-2021.rs -//@ aux-build:reserved-guarded-strings-macro-2024.rs +//@ proc-macro: reserved-guarded-strings-macro-2021.rs +//@ proc-macro: reserved-guarded-strings-macro-2024.rs extern crate reserved_guarded_strings_macro_2021 as m2021; extern crate reserved_guarded_strings_macro_2024 as m2024; diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs index 882f52c48a62..ead2ab40b77a 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs @@ -1,6 +1,6 @@ //@ run-pass //@ edition:2024 -//@ aux-build:reserved-guarded-strings-macro-2021.rs +//@ proc-macro: reserved-guarded-strings-macro-2021.rs extern crate reserved_guarded_strings_macro_2021 as m2021; diff --git a/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs b/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs index 557731d82d38..cab6af57cb1f 100644 --- a/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs +++ b/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm.rs @@ -1,7 +1,4 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] +//@ edition: 2018 extern crate proc_macro; diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs index 782a39422362..4f369a8305bc 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs @@ -6,7 +6,7 @@ //@[edition2021] edition:2021 //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -//@ aux-crate: unsafe_attributes_pm=unsafe-attributes-pm.rs +//@ proc-macro: unsafe-attributes-pm.rs unsafe_attributes_pm::missing_unsafe!(); diff --git a/tests/ui/suggestions/auxiliary/issue-61963-1.rs b/tests/ui/suggestions/auxiliary/issue-61963-1.rs index 33e5f9db2c38..2e7b0dbef198 100644 --- a/tests/ui/suggestions/auxiliary/issue-61963-1.rs +++ b/tests/ui/suggestions/auxiliary/issue-61963-1.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Group, TokenStream, TokenTree}; diff --git a/tests/ui/suggestions/auxiliary/issue-61963.rs b/tests/ui/suggestions/auxiliary/issue-61963.rs index bfea8061c4b3..07e6f319585b 100644 --- a/tests/ui/suggestions/auxiliary/issue-61963.rs +++ b/tests/ui/suggestions/auxiliary/issue-61963.rs @@ -1,7 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::{Group, Spacing, Punct, TokenTree, TokenStream}; diff --git a/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs index aebc5a6aaa9b..2930b87d1bbe 100644 --- a/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs +++ b/tests/ui/suggestions/auxiliary/proc-macro-type-error.rs @@ -1,6 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic -#![crate_type = "proc-macro"] #![feature(proc_macro_quote)] extern crate proc_macro; diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs index de82700d7e4b..2fafe629db97 100644 --- a/tests/ui/suggestions/issue-61963.rs +++ b/tests/ui/suggestions/issue-61963.rs @@ -1,5 +1,5 @@ -//@ aux-build:issue-61963.rs -//@ aux-build:issue-61963-1.rs +//@ proc-macro: issue-61963.rs +//@ proc-macro: issue-61963-1.rs #![deny(bare_trait_objects)] #[macro_use] diff --git a/tests/ui/suggestions/suggest-ref-macro.rs b/tests/ui/suggestions/suggest-ref-macro.rs index e5084e541152..2f31af33782c 100644 --- a/tests/ui/suggestions/suggest-ref-macro.rs +++ b/tests/ui/suggestions/suggest-ref-macro.rs @@ -1,5 +1,5 @@ // run-check -//@ aux-build:proc-macro-type-error.rs +//@ proc-macro: proc-macro-type-error.rs extern crate proc_macro_type_error; diff --git a/tests/ui/underscore-imports/auxiliary/duplicate.rs b/tests/ui/underscore-imports/auxiliary/duplicate.rs index 61613d24b9e9..b346522b7215 100644 --- a/tests/ui/underscore-imports/auxiliary/duplicate.rs +++ b/tests/ui/underscore-imports/auxiliary/duplicate.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::*; diff --git a/tests/ui/underscore-imports/duplicate.rs b/tests/ui/underscore-imports/duplicate.rs index 4afad77ee4f0..125ccdf52b01 100644 --- a/tests/ui/underscore-imports/duplicate.rs +++ b/tests/ui/underscore-imports/duplicate.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ aux-build:duplicate.rs +//@ proc-macro: duplicate.rs extern crate duplicate; From 583e26c5ddf86809be386fbc614226f91428a1c0 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 27 Nov 2024 15:25:08 +0000 Subject: [PATCH 123/330] clippy lints --- src/bootstrap/src/bin/main.rs | 2 +- src/bootstrap/src/core/build_steps/compile.rs | 2 +- src/bootstrap/src/core/build_steps/format.rs | 7 ++---- src/bootstrap/src/core/config/config.rs | 2 +- src/bootstrap/src/core/download.rs | 2 +- src/bootstrap/src/core/sanity.rs | 22 ++++++++----------- src/bootstrap/src/utils/helpers.rs | 2 +- 7 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 409a644b9be1..ee813de1c9e2 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -99,7 +99,7 @@ fn main() { // HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not. // We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime. // Instead, look for this comment, which is almost certainly not in any custom hook. - if fs::read_to_string(pre_commit).map_or(false, |contents| { + if fs::read_to_string(pre_commit).is_ok_and(|contents| { contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570") }) { println!( diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 8e088682f92d..cc6eb1ec4a9f 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1655,7 +1655,7 @@ impl Step for Sysroot { let mut add_filtered_files = |suffix, contents| { for path in contents { let path = Path::new(&path); - if path.parent().map_or(false, |parent| parent.ends_with(suffix)) { + if path.parent().is_some_and(|parent| parent.ends_with(suffix)) { filtered_files.push(path.file_name().unwrap().to_owned()); } } diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 5ca4321d8555..29a96f776728 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -56,10 +56,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> { let stamp_file = build.out.join("rustfmt.stamp"); - let mut cmd = command(match build.initial_rustfmt() { - Some(p) => p, - None => return None, - }); + let mut cmd = command(build.initial_rustfmt()?); cmd.arg("--version"); let output = cmd.allow_failure().run_capture(build); @@ -279,7 +276,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { Box::new(move |entry| { let cwd = std::env::current_dir(); let entry = t!(entry); - if entry.file_type().map_or(false, |t| t.is_file()) { + if entry.file_type().is_some_and(|t| t.is_file()) { formatted_paths_ref.lock().unwrap().push({ // `into_path` produces an absolute path. Try to strip `cwd` to get a shorter // relative path. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9b2d49e76202..35f80b6b98e9 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1665,7 +1665,7 @@ impl Config { } config.llvm_assertions = - toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false)); + toml.llvm.as_ref().is_some_and(|llvm| llvm.assertions.unwrap_or(false)); // Store off these values as options because if they're not provided // we'll infer default values for them later diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index db1f5b083382..124e38500314 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -830,7 +830,7 @@ download-rustc = false fn path_is_dylib(path: &Path) -> bool { // The .so is not necessarily the extension, it might be libLLVM.so.18.1 - path.to_str().map_or(false, |path| path.contains(".so")) + path.to_str().is_some_and(|path| path.contains(".so")) } /// Checks whether the CI rustc is available for the given target triple. diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index fabb4f2b13bc..dcf68cbeeda7 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -135,19 +135,15 @@ pub fn check(build: &mut Build) { // We need cmake, but only if we're actually building LLVM or sanitizers. let building_llvm = !build.config.llvm_from_ci - && build - .hosts - .iter() - .map(|host| { - build.config.llvm_enabled(*host) - && build - .config - .target_config - .get(host) - .map(|config| config.llvm_config.is_none()) - .unwrap_or(true) - }) - .any(|build_llvm_ourselves| build_llvm_ourselves); + && build.hosts.iter().any(|host| { + build.config.llvm_enabled(*host) + && build + .config + .target_config + .get(host) + .map(|config| config.llvm_config.is_none()) + .unwrap_or(true) + }); let need_cmake = building_llvm || build.config.any_sanitizers_to_build(); if need_cmake && cmd_finder.maybe_have("cmake").is_none() { diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 079213e8c3da..923cc2dfc28c 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -55,7 +55,7 @@ pub fn exe(name: &str, target: TargetSelection) -> String { /// Returns `true` if the file name given looks like a dynamic library. pub fn is_dylib(path: &Path) -> bool { - path.extension().and_then(|ext| ext.to_str()).map_or(false, |ext| { + path.extension().and_then(|ext| ext.to_str()).is_some_and(|ext| { ext == "dylib" || ext == "so" || ext == "dll" || (ext == "a" && is_aix_shared_archive(path)) }) } From 527b6065ba684f0f2702bb7f1066f76bf691a69c Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Wed, 27 Nov 2024 12:02:02 -0500 Subject: [PATCH 124/330] fmt --- library/std/src/sys/cmath.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index 829042381a24..ee36127cfdf1 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -70,7 +70,7 @@ pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { cfg_if::cfg_if! { if #[cfg(all(target_os = "windows", target_env = "msvc", target_arch = "x86"))] { #[inline] - pub unsafe fn acosf(n: f32) -> f32 { + pub unsafe fn acosf(n: f32) -> f32 { f64::acos(n as f64) as f32 } From b0f8bd7438362e3160de47381dfd1da5b8cf4449 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 14 Nov 2024 14:45:38 -0800 Subject: [PATCH 125/330] Add `BTreeSet` entry APIs to match `HashSet` * `fn get_or_insert(&mut self, value: T) -> &T` * `fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T` * `fn entry(&mut self, value: T) -> Entry<'_, T, A>` (+ `Entry` APIs) --- library/alloc/src/collections/btree/map.rs | 29 +- .../alloc/src/collections/btree/map/entry.rs | 5 + library/alloc/src/collections/btree/set.rs | 80 +++- .../alloc/src/collections/btree/set/entry.rs | 388 ++++++++++++++++++ 4 files changed, 500 insertions(+), 2 deletions(-) create mode 100644 library/alloc/src/collections/btree/set/entry.rs diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 213924d1d020..d1ce4e215ed9 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -308,11 +308,38 @@ impl BTreeMap { alloc: (*map.alloc).clone(), _marker: PhantomData, } - .insert(SetValZST::default()); + .insert(SetValZST); None } } } + + pub(super) fn get_or_insert_with(&mut self, q: &Q, f: F) -> &K + where + K: Borrow + Ord, + Q: Ord, + F: FnOnce(&Q) -> K, + { + let (map, dormant_map) = DormantMutRef::new(self); + let root_node = + map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut(); + match root_node.search_tree(q) { + Found(handle) => handle.into_kv_mut().0, + GoDown(handle) => { + let key = f(q); + assert!(*key.borrow() == *q, "new value is not equal"); + VacantEntry { + key, + handle: Some(handle), + dormant_map, + alloc: (*map.alloc).clone(), + _marker: PhantomData, + } + .insert_entry(SetValZST) + .into_key() + } + } + } } /// An iterator over the entries of a `BTreeMap`. diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 0da6af54bc22..ea8fa363c380 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -449,6 +449,11 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { self.handle.reborrow().into_kv().0 } + /// Converts the entry into a reference to its key. + pub(crate) fn into_key(self) -> &'a K { + self.handle.into_kv_mut().0 + } + /// Take ownership of the key and value from the map. /// /// # Examples diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 8daee6030c27..9b7c345e0c31 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -7,12 +7,17 @@ use core::iter::{FusedIterator, Peekable}; use core::mem::ManuallyDrop; use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub}; -use super::map::{BTreeMap, Keys}; +use super::map::{self, BTreeMap, Keys}; use super::merge_iter::MergeIterInner; use super::set_val::SetValZST; use crate::alloc::{Allocator, Global}; use crate::vec::Vec; +mod entry; + +#[unstable(feature = "btree_set_entry", issue = "none")] +pub use self::entry::{Entry, OccupiedEntry, VacantEntry}; + /// An ordered set based on a B-Tree. /// /// See [`BTreeMap`]'s documentation for a detailed discussion of this collection's performance @@ -928,6 +933,79 @@ impl BTreeSet { self.map.replace(value) } + /// Inserts the given `value` into the set if it is not present, then + /// returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::from([1, 2, 3]); + /// assert_eq!(set.len(), 3); + /// assert_eq!(set.get_or_insert(2), &2); + /// assert_eq!(set.get_or_insert(100), &100); + /// assert_eq!(set.len(), 4); // 100 was inserted + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn get_or_insert(&mut self, value: T) -> &T + where + T: Ord, + { + self.map.entry(value).insert_entry(SetValZST).into_key() + } + + /// Inserts a value computed from `f` into the set if the given `value` is + /// not present, then returns a reference to the value in the set. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set: BTreeSet = ["cat", "dog", "horse"] + /// .iter().map(|&pet| pet.to_owned()).collect(); + /// + /// assert_eq!(set.len(), 3); + /// for &pet in &["cat", "dog", "fish"] { + /// let value = set.get_or_insert_with(pet, str::to_owned); + /// assert_eq!(value, pet); + /// } + /// assert_eq!(set.len(), 4); // a new "fish" was inserted + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T + where + T: Borrow + Ord, + Q: Ord, + F: FnOnce(&Q) -> T, + { + self.map.get_or_insert_with(value, f) + } + + /// Gets the given value's corresponding entry in the set for in-place manipulation. + /// + /// # Examples + /// + /// TODO + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn entry(&mut self, value: T) -> Entry<'_, T, A> + where + T: Ord, + { + match self.map.entry(value) { + map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }), + map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }), + } + } + /// If the set contains an element equal to the value, removes it from the /// set and drops it. Returns whether such an element was present. /// diff --git a/library/alloc/src/collections/btree/set/entry.rs b/library/alloc/src/collections/btree/set/entry.rs new file mode 100644 index 000000000000..4f2b0282a2da --- /dev/null +++ b/library/alloc/src/collections/btree/set/entry.rs @@ -0,0 +1,388 @@ +use core::fmt::{self, Debug}; + +use Entry::*; + +use super::{SetValZST, map}; +use crate::alloc::{Allocator, Global}; + +/// A view into a single entry in a set, which may either be vacant or occupied. +/// +/// This `enum` is constructed from the [`entry`] method on [`BTreeSet`]. +/// +/// [`BTreeSet`]: super::BTreeSet +/// [`entry`]: super::BTreeSet::entry +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::BTreeSet; +/// +/// let mut set = BTreeSet::new(); +/// set.extend(["a", "b", "c"]); +/// assert_eq!(set.len(), 3); +/// +/// // Existing value (insert) +/// let entry = set.entry("a"); +/// let _raw_o = entry.insert(); +/// assert_eq!(set.len(), 3); +/// // Nonexistent value (insert) +/// set.entry("d").insert(); +/// +/// // Existing value (or_insert) +/// set.entry("b").or_insert(); +/// // Nonexistent value (or_insert) +/// set.entry("e").or_insert(); +/// +/// println!("Our BTreeSet: {:?}", set); +/// assert!(set.iter().eq(&["a", "b", "c", "d", "e"])); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "none")] +pub enum Entry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + /// An occupied entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::from(["a", "b"]); + /// + /// match set.entry("a") { + /// Entry::Vacant(_) => unreachable!(), + /// Entry::Occupied(_) => { } + /// } + /// ``` + #[unstable(feature = "btree_set_entry", issue = "none")] + Occupied(OccupiedEntry<'a, T, A>), + + /// A vacant entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// + /// match set.entry("a") { + /// Entry::Occupied(_) => unreachable!(), + /// Entry::Vacant(_) => { } + /// } + /// ``` + #[unstable(feature = "btree_set_entry", issue = "none")] + Vacant(VacantEntry<'a, T, A>), +} + +#[unstable(feature = "btree_set_entry", issue = "none")] +impl Debug for Entry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), + Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), + } + } +} + +/// A view into an occupied entry in a `BTreeSet`. +/// It is part of the [`Entry`] enum. +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::{Entry, BTreeSet}; +/// +/// let mut set = BTreeSet::new(); +/// set.extend(["a", "b", "c"]); +/// +/// let _entry_o = set.entry("a").insert(); +/// assert_eq!(set.len(), 3); +/// +/// // Existing key +/// match set.entry("a") { +/// Entry::Vacant(_) => unreachable!(), +/// Entry::Occupied(view) => { +/// assert_eq!(view.get(), &"a"); +/// } +/// } +/// +/// assert_eq!(set.len(), 3); +/// +/// // Existing key (take) +/// match set.entry("c") { +/// Entry::Vacant(_) => unreachable!(), +/// Entry::Occupied(view) => { +/// assert_eq!(view.remove(), "c"); +/// } +/// } +/// assert_eq!(set.get(&"c"), None); +/// assert_eq!(set.len(), 2); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "none")] +pub struct OccupiedEntry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) inner: map::OccupiedEntry<'a, T, SetValZST, A>, +} + +#[unstable(feature = "btree_set_entry", issue = "none")] +impl Debug for OccupiedEntry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OccupiedEntry").field("value", self.get()).finish() + } +} + +/// A view into a vacant entry in a `BTreeSet`. +/// It is part of the [`Entry`] enum. +/// +/// # Examples +/// +/// ``` +/// #![feature(btree_set_entry)] +/// +/// use std::collections::btree_set::{Entry, BTreeSet}; +/// +/// let mut set = BTreeSet::<&str>::new(); +/// +/// let entry_v = match set.entry("a") { +/// Entry::Vacant(view) => view, +/// Entry::Occupied(_) => unreachable!(), +/// }; +/// entry_v.insert(); +/// assert!(set.contains("a") && set.len() == 1); +/// +/// // Nonexistent key (insert) +/// match set.entry("b") { +/// Entry::Vacant(view) => view.insert(), +/// Entry::Occupied(_) => unreachable!(), +/// } +/// assert!(set.contains("b") && set.len() == 2); +/// ``` +#[unstable(feature = "btree_set_entry", issue = "none")] +pub struct VacantEntry< + 'a, + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, +> { + pub(super) inner: map::VacantEntry<'a, T, SetValZST, A>, +} + +#[unstable(feature = "btree_set_entry", issue = "none")] +impl Debug for VacantEntry<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("VacantEntry").field(self.get()).finish() + } +} + +impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> { + /// Sets the value of the entry, and returns an `OccupiedEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// let entry = set.entry("horseyland").insert(); + /// + /// assert_eq!(entry.get(), &"horseyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn insert(self) -> OccupiedEntry<'a, T, A> { + match self { + Occupied(entry) => entry, + Vacant(entry) => entry.insert_entry(), + } + } + + /// Ensures a value is in the entry by inserting if it was vacant. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// + /// // nonexistent key + /// set.entry("poneyland").or_insert(); + /// assert!(set.contains("poneyland")); + /// + /// // existing key + /// set.entry("poneyland").or_insert(); + /// assert!(set.contains("poneyland")); + /// assert_eq!(set.len(), 1); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn or_insert(self) { + if let Vacant(entry) = self { + entry.insert(); + } + } + + /// Returns a reference to this entry's value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// // existing key + /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); + /// // nonexistent key + /// assert_eq!(set.entry("horseland").get(), &"horseland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn get(&self) -> &T { + match *self { + Occupied(ref entry) => entry.get(), + Vacant(ref entry) => entry.get(), + } + } +} + +impl<'a, T: Ord, A: Allocator + Clone> OccupiedEntry<'a, T, A> { + /// Gets a reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// match set.entry("poneyland") { + /// Entry::Vacant(_) => panic!(), + /// Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"), + /// } + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn get(&self) -> &T { + self.inner.key() + } + + /// Takes the value out of the entry, and returns it. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry; + /// + /// let mut set = BTreeSet::new(); + /// set.entry("poneyland").or_insert(); + /// + /// if let Entry::Occupied(o) = set.entry("poneyland") { + /// assert_eq!(o.remove(), "poneyland"); + /// } + /// + /// assert_eq!(set.contains("poneyland"), false); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn remove(self) -> T { + self.inner.remove_entry().0 + } +} + +impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> { + /// Gets a reference to the value that would be used when inserting + /// through the `VacantEntry`. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// + /// let mut set = BTreeSet::new(); + /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn get(&self) -> &T { + self.inner.key() + } + + /// Take ownership of the value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::btree_set::{Entry, BTreeSet}; + /// + /// let mut set = BTreeSet::new(); + /// + /// match set.entry("poneyland") { + /// Entry::Occupied(_) => panic!(), + /// Entry::Vacant(v) => assert_eq!(v.into_value(), "poneyland"), + /// } + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn into_value(self) -> T { + self.inner.into_key() + } + + /// Sets the value of the entry with the VacantEntry's value. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry; + /// + /// let mut set = BTreeSet::new(); + /// + /// if let Entry::Vacant(o) = set.entry("poneyland") { + /// o.insert(); + /// } + /// assert!(set.contains("poneyland")); + /// ``` + #[inline] + #[unstable(feature = "btree_set_entry", issue = "none")] + pub fn insert(self) { + self.inner.insert(SetValZST); + } + + #[inline] + fn insert_entry(self) -> OccupiedEntry<'a, T, A> { + OccupiedEntry { inner: self.inner.insert_entry(SetValZST) } + } +} From e37ac2a66f9ee845c2c6fdd2834748fc106a2eb8 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 27 Nov 2024 11:23:25 -0800 Subject: [PATCH 126/330] rustc_span: Replace a `HashMap<_, ()>` with `HashSet` Now that `HashSet::entry()` exists, we don't need to fake it with a map. --- compiler/rustc_span/src/hygiene.rs | 11 ++++++----- compiler/rustc_span/src/lib.rs | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index a9ca5dbe5094..a5826137181d 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -26,6 +26,7 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; +use std::collections::hash_set::Entry as SetEntry; use std::fmt; use std::hash::Hash; @@ -1270,7 +1271,7 @@ pub struct HygieneDecodeContext { inner: Lock, /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread. - local_in_progress: WorkerLocal>>, + local_in_progress: WorkerLocal>>, } /// Register an expansion which has been decoded from the on-disk-cache for the local crate. @@ -1364,14 +1365,14 @@ pub fn decode_syntax_context SyntaxContext match inner.decoding.entry(raw_id) { Entry::Occupied(ctxt_entry) => { match context.local_in_progress.borrow_mut().entry(raw_id) { - Entry::Occupied(..) => { + SetEntry::Occupied(..) => { // We're decoding this already on the current thread. Return here // and let the function higher up the stack finish decoding to handle // recursive cases. return *ctxt_entry.get(); } - Entry::Vacant(entry) => { - entry.insert(()); + SetEntry::Vacant(entry) => { + entry.insert(); // Some other thread is current decoding this. Race with it. *ctxt_entry.get() @@ -1380,7 +1381,7 @@ pub fn decode_syntax_context SyntaxContext } Entry::Vacant(entry) => { // We are the first thread to start decoding. Mark the current thread as being progress. - context.local_in_progress.borrow_mut().insert(raw_id, ()); + context.local_in_progress.borrow_mut().insert(raw_id); // Allocate and store SyntaxContext id *before* calling the decoder function, // as the SyntaxContextData may reference itself. diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 1481e1cbd918..57c645bfaba5 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -22,6 +22,7 @@ #![feature(array_windows)] #![feature(cfg_match)] #![feature(core_io_borrowed_buf)] +#![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] From 82b8ea8a7a63ccc9be8e6c557fc4b2fb2cd14145 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 27 Nov 2024 11:43:05 -0800 Subject: [PATCH 127/330] Add a tracking issue for `btree_set_entry` --- library/alloc/src/collections/btree/set.rs | 8 ++--- .../alloc/src/collections/btree/set/entry.rs | 32 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 9b7c345e0c31..a9c64fd41d52 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -15,7 +15,7 @@ use crate::vec::Vec; mod entry; -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] pub use self::entry::{Entry, OccupiedEntry, VacantEntry}; /// An ordered set based on a B-Tree. @@ -950,7 +950,7 @@ impl BTreeSet { /// assert_eq!(set.len(), 4); // 100 was inserted /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn get_or_insert(&mut self, value: T) -> &T where T: Ord, @@ -979,7 +979,7 @@ impl BTreeSet { /// assert_eq!(set.len(), 4); // a new "fish" was inserted /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T where T: Borrow + Ord, @@ -995,7 +995,7 @@ impl BTreeSet { /// /// TODO #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn entry(&mut self, value: T) -> Entry<'_, T, A> where T: Ord, diff --git a/library/alloc/src/collections/btree/set/entry.rs b/library/alloc/src/collections/btree/set/entry.rs index 4f2b0282a2da..a60d22f9ece7 100644 --- a/library/alloc/src/collections/btree/set/entry.rs +++ b/library/alloc/src/collections/btree/set/entry.rs @@ -38,7 +38,7 @@ use crate::alloc::{Allocator, Global}; /// println!("Our BTreeSet: {:?}", set); /// assert!(set.iter().eq(&["a", "b", "c", "d", "e"])); /// ``` -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] pub enum Entry< 'a, T, @@ -60,7 +60,7 @@ pub enum Entry< /// Entry::Occupied(_) => { } /// } /// ``` - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] Occupied(OccupiedEntry<'a, T, A>), /// A vacant entry. @@ -79,11 +79,11 @@ pub enum Entry< /// Entry::Vacant(_) => { } /// } /// ``` - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] Vacant(VacantEntry<'a, T, A>), } -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] impl Debug for Entry<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -129,7 +129,7 @@ impl Debug for Entry<'_, T, A> { /// assert_eq!(set.get(&"c"), None); /// assert_eq!(set.len(), 2); /// ``` -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] pub struct OccupiedEntry< 'a, T, @@ -138,7 +138,7 @@ pub struct OccupiedEntry< pub(super) inner: map::OccupiedEntry<'a, T, SetValZST, A>, } -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] impl Debug for OccupiedEntry<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedEntry").field("value", self.get()).finish() @@ -171,7 +171,7 @@ impl Debug for OccupiedEntry<'_, T, A> { /// } /// assert!(set.contains("b") && set.len() == 2); /// ``` -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] pub struct VacantEntry< 'a, T, @@ -180,7 +180,7 @@ pub struct VacantEntry< pub(super) inner: map::VacantEntry<'a, T, SetValZST, A>, } -#[unstable(feature = "btree_set_entry", issue = "none")] +#[unstable(feature = "btree_set_entry", issue = "133549")] impl Debug for VacantEntry<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("VacantEntry").field(self.get()).finish() @@ -203,7 +203,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> { /// assert_eq!(entry.get(), &"horseyland"); /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn insert(self) -> OccupiedEntry<'a, T, A> { match self { Occupied(entry) => entry, @@ -232,7 +232,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> { /// assert_eq!(set.len(), 1); /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn or_insert(self) { if let Vacant(entry) = self { entry.insert(); @@ -257,7 +257,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Entry<'a, T, A> { /// assert_eq!(set.entry("horseland").get(), &"horseland"); /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn get(&self) -> &T { match *self { Occupied(ref entry) => entry.get(), @@ -285,7 +285,7 @@ impl<'a, T: Ord, A: Allocator + Clone> OccupiedEntry<'a, T, A> { /// } /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn get(&self) -> &T { self.inner.key() } @@ -310,7 +310,7 @@ impl<'a, T: Ord, A: Allocator + Clone> OccupiedEntry<'a, T, A> { /// assert_eq!(set.contains("poneyland"), false); /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn remove(self) -> T { self.inner.remove_entry().0 } @@ -331,7 +331,7 @@ impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> { /// assert_eq!(set.entry("poneyland").get(), &"poneyland"); /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn get(&self) -> &T { self.inner.key() } @@ -353,7 +353,7 @@ impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> { /// } /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn into_value(self) -> T { self.inner.into_key() } @@ -376,7 +376,7 @@ impl<'a, T: Ord, A: Allocator + Clone> VacantEntry<'a, T, A> { /// assert!(set.contains("poneyland")); /// ``` #[inline] - #[unstable(feature = "btree_set_entry", issue = "none")] + #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn insert(self) { self.inner.insert(SetValZST); } From e11cfebf4ef135414eb60536b063e8f987258f72 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 27 Nov 2024 22:57:53 +0300 Subject: [PATCH 128/330] print generated doc paths Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index e6902bb8cee5..945a7b7366f4 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1523,15 +1523,19 @@ impl<'a> Builder<'a> { pub(crate) fn maybe_open_in_browser(&self, path: impl AsRef) { if self.was_invoked_explicitly::(Kind::Doc) { self.open_in_browser(path); + } else { + self.info(&format!("Doc path: {}", path.as_ref().display())); } } pub(crate) fn open_in_browser(&self, path: impl AsRef) { + let path = path.as_ref(); + if self.config.dry_run() || !self.config.cmd.open() { + self.info(&format!("Doc path: {}", path.display())); return; } - let path = path.as_ref(); self.info(&format!("Opening doc {}", path.display())); if let Err(err) = opener::open(path) { self.info(&format!("{err}\n")); From 21b1ab1779a6f58f4a77bad0e1d3a21efcd9bc47 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 27 Nov 2024 12:22:21 -0800 Subject: [PATCH 129/330] Fill in a `BTreeSet::entry` example --- library/alloc/src/collections/btree/set.rs | 32 +++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index a9c64fd41d52..6f8c3b2d152b 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -993,7 +993,37 @@ impl BTreeSet { /// /// # Examples /// - /// TODO + /// ``` + /// #![feature(btree_set_entry)] + /// + /// use std::collections::BTreeSet; + /// use std::collections::btree_set::Entry::*; + /// + /// let mut singles = BTreeSet::new(); + /// let mut dupes = BTreeSet::new(); + /// + /// for ch in "a short treatise on fungi".chars() { + /// if let Vacant(dupe_entry) = dupes.entry(ch) { + /// // We haven't already seen a duplicate, so + /// // check if we've at least seen it once. + /// match singles.entry(ch) { + /// Vacant(single_entry) => { + /// // We found a new character for the first time. + /// single_entry.insert() + /// } + /// Occupied(single_entry) => { + /// // We've already seen this once, "move" it to dupes. + /// single_entry.remove(); + /// dupe_entry.insert(); + /// } + /// } + /// } + /// } + /// + /// assert!(!singles.contains(&'t') && dupes.contains(&'t')); + /// assert!(singles.contains(&'u') && !dupes.contains(&'u')); + /// assert!(!singles.contains(&'v') && !dupes.contains(&'v')); + /// ``` #[inline] #[unstable(feature = "btree_set_entry", issue = "133549")] pub fn entry(&mut self, value: T) -> Entry<'_, T, A> From 87c045e2b383ff281458d7b4a2e1c151dc46cbfc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 22 Oct 2024 17:59:26 +0000 Subject: [PATCH 130/330] Robustify and genericize RTN resolution in RBV --- .../src/collect/resolve_bound_vars.rs | 119 +++++++++++++----- compiler/rustc_hir_analysis/src/lib.rs | 2 + .../all-generics-lookup.rs | 31 +++++ 3 files changed, 119 insertions(+), 33 deletions(-) create mode 100644 tests/ui/associated-type-bounds/all-generics-lookup.rs diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 74729ebe4882..2887f42c2494 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2060,46 +2060,30 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; match path.res { Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => { - // Get the generics of this type's hir owner. This is *different* - // from the generics of the parameter's definition, since we want - // to be able to resolve an RTN path on a nested body (e.g. method - // inside an impl) using the where clauses on the method. - // FIXME(return_type_notation): Think of some better way of doing this. - let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics() - else { - return; - }; - - // Look for the first bound that contains an associated type that - // matches the segment that we're looking for. We ignore any subsequent - // bounds since we'll be emitting a hard error in HIR lowering, so this - // is purely speculative. - let one_bound = generics.predicates.iter().find_map(|predicate| { - let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind - else { - return None; - }; - let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = - predicate.bounded_ty.kind - else { - return None; - }; - if bounded_path.res != path.res { - return None; - } - predicate.bounds.iter().find_map(|bound| { - let hir::GenericBound::Trait(trait_) = bound else { - return None; - }; + let mut bounds = + self.for_each_in_scope_predicate(path.res).filter_map(|trait_| { BoundVarContext::supertrait_hrtb_vars( self.tcx, trait_.trait_ref.trait_def_id()?, item_segment.ident, ty::AssocKind::Fn, ) - }) - }); + }); + + let one_bound = bounds.next(); + let second_bound = bounds.next(); + + if second_bound.is_some() { + self.tcx + .dcx() + .span_delayed_bug(path.span, "ambiguous resolution for RTN path"); + return; + } + let Some((bound_vars, assoc_item)) = one_bound else { + self.tcx + .dcx() + .span_delayed_bug(path.span, "no resolution for RTN path"); return; }; (bound_vars, assoc_item.def_id, item_segment) @@ -2167,6 +2151,75 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { existing_bound_vars.extend(bound_vars); self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); } + + /// Walk the generics of the item for a trait-ref whose self type + /// corresponds to the expected res. + fn for_each_in_scope_predicate( + &self, + expected_res: Res, + ) -> impl Iterator> + use<'tcx, '_> { + std::iter::from_coroutine( + #[coroutine] + move || { + let mut next_scope = Some(self.scope); + while let Some(current_scope) = next_scope { + next_scope = None; + let hir_id = match *current_scope { + Scope::Binder { s, hir_id, .. } => { + next_scope = Some(s); + hir_id + } + Scope::Body { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s } + | Scope::LateBoundary { s, .. } => { + next_scope = Some(s); + continue; + } + Scope::Root { opt_parent_item } => { + if let Some(parent_id) = opt_parent_item { + self.tcx.local_def_id_to_hir_id(parent_id) + } else { + continue; + } + } + }; + let node = self.tcx.hir_node(hir_id); + if let Some(generics) = node.generics() { + for pred in generics.predicates { + let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else { + continue; + }; + let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = + pred.bounded_ty.kind + else { + continue; + }; + // Match the expected res. + if bounded_path.res != expected_res { + continue; + } + yield pred.bounds; + } + } + // Also consider supertraits for `Self` res... + if let Res::SelfTyParam { trait_: _ } = expected_res + && let hir::Node::Item(item) = node + && let hir::ItemKind::Trait(_, _, _, supertraits, _) = item.kind + { + yield supertraits; + } + } + }, + ) + .flatten() + .filter_map(|pred| match pred { + hir::GenericBound::Trait(poly_trait_ref) => Some(poly_trait_ref), + hir::GenericBound::Outlives(_) | hir::GenericBound::Use(_, _) => None, + }) + .fuse() + } } /// Detects late-bound lifetimes and inserts them into diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 0a26b6776bbd..58223c868c9b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -62,7 +62,9 @@ This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(coroutines)] #![feature(if_let_guard)] +#![feature(iter_from_coroutine)] #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] diff --git a/tests/ui/associated-type-bounds/all-generics-lookup.rs b/tests/ui/associated-type-bounds/all-generics-lookup.rs new file mode 100644 index 000000000000..c5940c14f440 --- /dev/null +++ b/tests/ui/associated-type-bounds/all-generics-lookup.rs @@ -0,0 +1,31 @@ +//@ check-pass + +#![feature(return_type_notation)] + +trait Trait { + fn method(&self) -> impl Sized; +} + +impl Trait for () { + fn method(&self) -> impl Sized {} +} + +struct Struct(T); + +// This test used to fail a debug assertion since we weren't resolving the item +// for `T::method(..)` correctly, leading to two bound vars being given the +// index 0. The solution is to look at both generics of `test` and its parent impl. + +impl Struct +where + T: Trait, +{ + fn test() + where + T::method(..): Send + {} +} + +fn main() { + Struct::<()>::test(); +} From 959801ff2eaf2b3fd76bfc78e4e311be6ce11f9c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 7 Nov 2024 22:41:59 +0000 Subject: [PATCH 131/330] Handle bounds that come from the trait itself --- .../src/collect/resolve_bound_vars.rs | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 2887f42c2494..8265108513ab 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2061,23 +2061,27 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { match path.res { Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => { let mut bounds = - self.for_each_in_scope_predicate(path.res).filter_map(|trait_| { + self.for_each_trait_bound_on_res(path.res).filter_map(|trait_def_id| { BoundVarContext::supertrait_hrtb_vars( self.tcx, - trait_.trait_ref.trait_def_id()?, + trait_def_id, item_segment.ident, ty::AssocKind::Fn, ) }); let one_bound = bounds.next(); - let second_bound = bounds.next(); - if second_bound.is_some() { - self.tcx - .dcx() - .span_delayed_bug(path.span, "ambiguous resolution for RTN path"); - return; + // Don't bail if we have identical bounds, which may be collected from + // something like `T: Bound + Bound`, or via elaborating supertraits. + for second_bound in bounds { + if Some(&second_bound) != one_bound.as_ref() { + self.tcx.dcx().span_delayed_bug( + path.span, + "ambiguous resolution for RTN path", + ); + return; + } } let Some((bound_vars, assoc_item)) = one_bound else { @@ -2086,6 +2090,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { .span_delayed_bug(path.span, "no resolution for RTN path"); return; }; + (bound_vars, assoc_item.def_id, item_segment) } // If we have a self type alias (in an impl), try to resolve an @@ -2152,12 +2157,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); } - /// Walk the generics of the item for a trait-ref whose self type - /// corresponds to the expected res. - fn for_each_in_scope_predicate( + /// Walk the generics of the item for a trait bound whose self type + /// corresponds to the expected res, and return the trait def id. + fn for_each_trait_bound_on_res( &self, expected_res: Res, - ) -> impl Iterator> + use<'tcx, '_> { + ) -> impl Iterator + use<'tcx, '_> { std::iter::from_coroutine( #[coroutine] move || { @@ -2173,7 +2178,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s } - | Scope::LateBoundary { s, .. } => { + | Scope::LateBoundary { s, .. } + | Scope::Opaque { s, .. } => { next_scope = Some(s); continue; } @@ -2186,7 +2192,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } }; let node = self.tcx.hir_node(hir_id); - if let Some(generics) = node.generics() { + // If this is a `Self` bound in a trait, yield the trait itself. + // Specifically, we don't need to look at any supertraits since + // we already do that in `BoundVarContext::supertrait_hrtb_vars`. + if let Res::SelfTyParam { trait_: _ } = expected_res + && let hir::Node::Item(item) = node + && let hir::ItemKind::Trait(..) = item.kind + { + // Yield the trait's def id. Supertraits will be + // elaborated from that. + yield item.owner_id.def_id.to_def_id(); + } else if let Some(generics) = node.generics() { for pred in generics.predicates { let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else { continue; @@ -2200,24 +2216,24 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if bounded_path.res != expected_res { continue; } - yield pred.bounds; + for pred in pred.bounds { + match pred { + hir::GenericBound::Trait(poly_trait_ref) => { + if let Some(def_id) = + poly_trait_ref.trait_ref.trait_def_id() + { + yield def_id; + } + } + hir::GenericBound::Outlives(_) + | hir::GenericBound::Use(_, _) => {} + } + } } } - // Also consider supertraits for `Self` res... - if let Res::SelfTyParam { trait_: _ } = expected_res - && let hir::Node::Item(item) = node - && let hir::ItemKind::Trait(_, _, _, supertraits, _) = item.kind - { - yield supertraits; - } } }, ) - .flatten() - .filter_map(|pred| match pred { - hir::GenericBound::Trait(poly_trait_ref) => Some(poly_trait_ref), - hir::GenericBound::Outlives(_) | hir::GenericBound::Use(_, _) => None, - }) .fuse() } } From 0f5759a00536ac7172090226538bd6870df4b07f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 26 Nov 2024 00:54:59 +0000 Subject: [PATCH 132/330] Address review comments --- .../src/collect/resolve_bound_vars.rs | 142 +++++++++--------- 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 8265108513ab..74f381d26611 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2070,12 +2070,19 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { ) }); - let one_bound = bounds.next(); + let Some((bound_vars, assoc_item)) = bounds.next() else { + // This will error in HIR lowering. + self.tcx + .dcx() + .span_delayed_bug(path.span, "no resolution for RTN path"); + return; + }; // Don't bail if we have identical bounds, which may be collected from // something like `T: Bound + Bound`, or via elaborating supertraits. - for second_bound in bounds { - if Some(&second_bound) != one_bound.as_ref() { + for (second_vars, second_assoc_item) in bounds { + if second_vars != bound_vars || second_assoc_item != assoc_item { + // This will error in HIR lowering. self.tcx.dcx().span_delayed_bug( path.span, "ambiguous resolution for RTN path", @@ -2084,13 +2091,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - let Some((bound_vars, assoc_item)) = one_bound else { - self.tcx - .dcx() - .span_delayed_bug(path.span, "no resolution for RTN path"); - return; - }; - (bound_vars, assoc_item.def_id, item_segment) } // If we have a self type alias (in an impl), try to resolve an @@ -2166,75 +2166,81 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { std::iter::from_coroutine( #[coroutine] move || { - let mut next_scope = Some(self.scope); - while let Some(current_scope) = next_scope { - next_scope = None; - let hir_id = match *current_scope { - Scope::Binder { s, hir_id, .. } => { - next_scope = Some(s); - hir_id + let mut scope = self.scope; + loop { + let hir_id = match *scope { + Scope::Binder { hir_id, .. } => Some(hir_id), + Scope::Root { opt_parent_item: Some(parent_def_id) } => { + Some(self.tcx.local_def_id_to_hir_id(parent_def_id)) } - Scope::Body { s, .. } + Scope::Body { .. } + | Scope::ObjectLifetimeDefault { .. } + | Scope::Supertrait { .. } + | Scope::TraitRefBoundary { .. } + | Scope::LateBoundary { .. } + | Scope::Opaque { .. } + | Scope::Root { opt_parent_item: None } => None, + }; + + if let Some(hir_id) = hir_id { + let node = self.tcx.hir_node(hir_id); + // If this is a `Self` bound in a trait, yield the trait itself. + // Specifically, we don't need to look at any supertraits since + // we already do that in `BoundVarContext::supertrait_hrtb_vars`. + if let Res::SelfTyParam { trait_: _ } = expected_res + && let hir::Node::Item(item) = node + && let hir::ItemKind::Trait(..) = item.kind + { + // Yield the trait's def id. Supertraits will be + // elaborated from that. + yield item.owner_id.def_id.to_def_id(); + } else if let Some(generics) = node.generics() { + for pred in generics.predicates { + let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind + else { + continue; + }; + let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = + pred.bounded_ty.kind + else { + continue; + }; + // Match the expected res. + if bounded_path.res != expected_res { + continue; + } + for pred in pred.bounds { + match pred { + hir::GenericBound::Trait(poly_trait_ref) => { + if let Some(def_id) = + poly_trait_ref.trait_ref.trait_def_id() + { + yield def_id; + } + } + hir::GenericBound::Outlives(_) + | hir::GenericBound::Use(_, _) => {} + } + } + } + } + } + + match *scope { + Scope::Binder { s, .. } + | Scope::Body { s, .. } | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s } | Scope::LateBoundary { s, .. } | Scope::Opaque { s, .. } => { - next_scope = Some(s); - continue; - } - Scope::Root { opt_parent_item } => { - if let Some(parent_id) = opt_parent_item { - self.tcx.local_def_id_to_hir_id(parent_id) - } else { - continue; - } - } - }; - let node = self.tcx.hir_node(hir_id); - // If this is a `Self` bound in a trait, yield the trait itself. - // Specifically, we don't need to look at any supertraits since - // we already do that in `BoundVarContext::supertrait_hrtb_vars`. - if let Res::SelfTyParam { trait_: _ } = expected_res - && let hir::Node::Item(item) = node - && let hir::ItemKind::Trait(..) = item.kind - { - // Yield the trait's def id. Supertraits will be - // elaborated from that. - yield item.owner_id.def_id.to_def_id(); - } else if let Some(generics) = node.generics() { - for pred in generics.predicates { - let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else { - continue; - }; - let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = - pred.bounded_ty.kind - else { - continue; - }; - // Match the expected res. - if bounded_path.res != expected_res { - continue; - } - for pred in pred.bounds { - match pred { - hir::GenericBound::Trait(poly_trait_ref) => { - if let Some(def_id) = - poly_trait_ref.trait_ref.trait_def_id() - { - yield def_id; - } - } - hir::GenericBound::Outlives(_) - | hir::GenericBound::Use(_, _) => {} - } - } + scope = s; } + Scope::Root { .. } => break, } } }, ) - .fuse() } } From 26c77742c3af8e80b0e62b73939d6a112b4b7043 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 27 Nov 2024 02:50:57 +0000 Subject: [PATCH 133/330] Structurally resolve before applying projection in borrowck --- .../src/type_check/canonical.rs | 36 +++++++++++++++++++ compiler/rustc_borrowck/src/type_check/mod.rs | 6 ++-- ...-normalize-in-borrowck-field-projection.rs | 32 +++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 68b843d4d0d7..585d0eabf5b9 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast}; use rustc_span::Span; use rustc_span::def_id::DefId; +use rustc_trait_selection::solve::NoSolution; use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; @@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if self.infcx.next_trait_solver() { let body = self.body; let param_env = self.infcx.param_env; + // FIXME: Make this into a real type op? self.fully_perform_op( location.to_locations(), ConstraintCategory::Boring, @@ -213,6 +215,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + #[instrument(skip(self), level = "debug")] + pub(super) fn structurally_resolve( + &mut self, + ty: Ty<'tcx>, + location: impl NormalizeLocation, + ) -> Ty<'tcx> { + if self.infcx.next_trait_solver() { + let body = self.body; + let param_env = self.infcx.param_env; + // FIXME: Make this into a real type op? + self.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + CustomTypeOp::new( + |ocx| { + ocx.structurally_normalize( + &ObligationCause::misc( + location.to_locations().span(body), + body.source.def_id().expect_local(), + ), + param_env, + ty, + ) + .map_err(|_| NoSolution) + }, + "normalizing struct tail", + ), + ) + .unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar)) + } else { + self.normalize(ty, location) + } + } + #[instrument(skip(self), level = "debug")] pub(super) fn ascribe_user_type( &mut self, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3a7ed711f681..b4763acbefa0 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1064,7 +1064,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.infcx.tcx; for proj in &user_ty.projs { - if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() { + if !self.infcx.next_trait_solver() + && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() + { // There is nothing that we can compare here if we go through an opaque type. // We're always in its defining scope as we can otherwise not project through // it, so we're constraining it anyways. @@ -1075,7 +1077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { proj, |this, field, ()| { let ty = this.field_ty(tcx, field); - self.normalize(ty, locations) + self.structurally_resolve(ty, locations) }, |_, _| unreachable!(), ); diff --git a/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs new file mode 100644 index 000000000000..d2d68128fde5 --- /dev/null +++ b/tests/ui/traits/next-solver/structurally-normalize-in-borrowck-field-projection.rs @@ -0,0 +1,32 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +trait Interner: Sized { + type Value; +} + +enum Kind { + Value(I::Value), +} + +struct Intern; + +impl Interner for Intern { + type Value = Wrap; +} + +struct Wrap(T); + +type KindAlias = Kind; + +trait PrettyPrinter: Sized { + fn hello(c: KindAlias) { + match c { + KindAlias::Value(Wrap(v)) => { + println!("{v:?}"); + } + } + } +} + +fn main() {} From 4120fdbeab225daddec7436755074e688c8087c3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 27 Nov 2024 02:44:24 +0000 Subject: [PATCH 134/330] Check xform_ret_ty for WF in the new solver to improve method winnowing --- compiler/rustc_hir_typeck/src/method/probe.rs | 22 +++++++++ tests/ui/traits/next-solver/non-wf-ret.rs | 47 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/ui/traits/next-solver/non-wf-ret.rs diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 640729576fcc..5aaad3636a2a 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1642,6 +1642,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + // FIXME(-Znext-solver): See the linked issue below. + // + // + // In the new solver, check the well-formedness of the return type. + // This emulates, in a way, the predicates that fall out of + // normalizing the return type in the old solver. + // + // We alternatively could check the predicates of the method itself hold, + // but we intentionally do not do this in the old solver b/c of cycles, + // and doing it in the new solver would be stronger. This should be fixed + // in the future, since it likely leads to much better method winnowing. + if let Some(xform_ret_ty) = xform_ret_ty + && self.infcx.next_trait_solver() + { + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause.clone(), + self.param_env, + ty::ClauseKind::WellFormed(xform_ret_ty.into()), + )); + } + // Evaluate those obligations to see if they might possibly hold. for error in ocx.select_where_possible() { result = ProbeResult::NoMatch; diff --git a/tests/ui/traits/next-solver/non-wf-ret.rs b/tests/ui/traits/next-solver/non-wf-ret.rs new file mode 100644 index 000000000000..c54d61c895d2 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-ret.rs @@ -0,0 +1,47 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +use std::ops::Deref; + +pub struct List { + skel: [T], +} + +impl<'a, T: Copy> IntoIterator for &'a List { + type Item = T; + type IntoIter = std::iter::Copied<<&'a [T] as IntoIterator>::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + todo!() + } +} + +impl Deref for List { + type Target = [T]; + + fn deref(&self) -> &[T] { + todo!() + } +} + +impl List { + fn iter(&self) -> <&Self as IntoIterator>::IntoIter + where + T: Copy, + { + todo!() + } +} + +fn test(t: &List) { + // Checking that `<&List as IntoIterator>::IntoIter` is WF + // will disqualify the inherent method, since normalizing it + // requires `Q: Copy` which does not hold. and allow us to fall + // through to the deref'd `<[Q]>::iter` method which works. + // + // In the old solver, the same behavior is achieved by just + // eagerly normalizing the return type. + t.iter(); +} + +fn main() {} From 37d3c6186ef54c37195e6f08df6d2ee4a23aa6a1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 27 Nov 2024 15:21:34 +0100 Subject: [PATCH 135/330] extend group-forbid-always-trumps-cli test --- ...-always-trumps-cli.allow-first-group.stderr} | 2 +- ...id-always-trumps-cli.allow-first-lint.stderr | 10 ++++++++++ ...id-always-trumps-cli.allow-first-mix1.stderr | 10 ++++++++++ ...id-always-trumps-cli.allow-first-mix2.stderr | 10 ++++++++++ ...-always-trumps-cli.forbid-first-group.stderr | 10 ++++++++++ ...d-always-trumps-cli.forbid-first-lint.stderr | 10 ++++++++++ ...d-always-trumps-cli.forbid-first-mix1.stderr | 10 ++++++++++ ...d-always-trumps-cli.forbid-first-mix2.stderr | 10 ++++++++++ tests/ui/lint/forbid-always-trumps-cli.rs | 17 +++++++++++++++++ tests/ui/lint/group-forbid-always-trumps-cli.rs | 6 ------ 10 files changed, 88 insertions(+), 7 deletions(-) rename tests/ui/lint/{group-forbid-always-trumps-cli.stderr => forbid-always-trumps-cli.allow-first-group.stderr} (82%) create mode 100644 tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr create mode 100644 tests/ui/lint/forbid-always-trumps-cli.rs delete mode 100644 tests/ui/lint/group-forbid-always-trumps-cli.rs diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr similarity index 82% rename from tests/ui/lint/group-forbid-always-trumps-cli.stderr rename to tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr index ed1242eacfce..07773ee4ddfe 100644 --- a/tests/ui/lint/group-forbid-always-trumps-cli.stderr +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-group.stderr @@ -1,5 +1,5 @@ error: unused variable: `x` - --> $DIR/group-forbid-always-trumps-cli.rs:4:9 + --> $DIR/forbid-always-trumps-cli.rs:15:9 | LL | let x = 1; | ^ help: if this is intentional, prefix it with an underscore: `_x` diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr new file mode 100644 index 000000000000..cf357ef8ca8f --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-lint.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr new file mode 100644 index 000000000000..07773ee4ddfe --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix1.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr new file mode 100644 index 000000000000..cf357ef8ca8f --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.allow-first-mix2.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr new file mode 100644 index 000000000000..07773ee4ddfe --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-group.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr new file mode 100644 index 000000000000..cf357ef8ca8f --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-lint.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr new file mode 100644 index 000000000000..07773ee4ddfe --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix1.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `-F unused-variables` implied by `-F unused` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr new file mode 100644 index 000000000000..cf357ef8ca8f --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.forbid-first-mix2.stderr @@ -0,0 +1,10 @@ +error: unused variable: `x` + --> $DIR/forbid-always-trumps-cli.rs:15:9 + | +LL | let x = 1; + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: requested on the command line with `-F unused-variables` + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/forbid-always-trumps-cli.rs b/tests/ui/lint/forbid-always-trumps-cli.rs new file mode 100644 index 000000000000..d94cc2e8efef --- /dev/null +++ b/tests/ui/lint/forbid-always-trumps-cli.rs @@ -0,0 +1,17 @@ +//! Ensure that "forbid" always trumps" allow" in CLI arguments, no matter the order +//! and no matter whether it is used with a lint group vs an individual lint. +// ignore-tidy-linelength +//@ revisions: forbid-first-group allow-first-group forbid-first-lint allow-first-lint forbid-first-mix1 allow-first-mix1 forbid-first-mix2 allow-first-mix2 +//@[forbid-first-group] compile-flags: -F unused -A unused +//@[allow-first-group] compile-flags: -A unused -F unused +//@[forbid-first-lint] compile-flags: -F unused_variables -A unused_variables +//@[allow-first-lint] compile-flags: -A unused_variables -F unused_variables +//@[forbid-first-mix1] compile-flags: -F unused -A unused_variables +//@[allow-first-mix1] compile-flags: -A unused_variables -F unused +//@[forbid-first-mix2] compile-flags: -F unused_variables -A unused +//@[allow-first-mix2] compile-flags: -A unused -F unused_variables + +fn main() { + let x = 1; + //~^ ERROR unused variable: `x` +} diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.rs b/tests/ui/lint/group-forbid-always-trumps-cli.rs deleted file mode 100644 index 4b63452bf5d4..000000000000 --- a/tests/ui/lint/group-forbid-always-trumps-cli.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ compile-flags: -F unused -A unused - -fn main() { - let x = 1; - //~^ ERROR unused variable: `x` -} From 871cfc9dff54ad64929e75c19c9dc8cbd5e300e2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Nov 2024 23:08:19 +0000 Subject: [PATCH 136/330] Further simplifications --- .../src/check/compare_impl_item.rs | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index dd1062558901..1ae71d807cd5 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -702,8 +702,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let mut remapped_types = DefIdMap::default(); for (def_id, (ty, args)) in collected_types { - match infcx.fully_resolve((ty, args)) { - Ok((ty, args)) => { + match infcx.fully_resolve(ty) { + Ok(ty) => { // `ty` contains free regions that we created earlier while liberating the // trait fn signature. However, projection normalization expects `ty` to // contains `def_id`'s early-bound regions. @@ -883,33 +883,27 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { self.tcx } - fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { - if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() { - let mut mapped_args = Vec::with_capacity(args.len()); - for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) { - mapped_args.push(match (arg.unpack(), v) { - // Skip uncaptured opaque args - (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg, - _ => arg.try_fold_with(self)?, - }); - } - Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args))) - } else { - t.try_super_fold_with(self) - } - } - fn try_fold_region( &mut self, region: ty::Region<'tcx>, ) -> Result, Self::Error> { match region.kind() { - // Remap late-bound regions from the function. + // Never remap bound regions or `'static` + ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region), + // We always remap liberated late-bound regions from the function. ty::ReLateParam(_) => {} // Remap early-bound regions as long as they don't come from the `impl` itself, // in which case we don't really need to renumber them. - ty::ReEarlyParam(ebr) if ebr.index as usize >= self.num_impl_args => {} - _ => return Ok(region), + ty::ReEarlyParam(ebr) => { + if ebr.index as usize >= self.num_impl_args { + // Remap + } else { + return Ok(region); + } + } + ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!( + "should not have leaked vars or placeholders into hidden type of RPITIT" + ), } let e = if let Some(id_region) = self.map.get(®ion) { From 685f189b4307435b83d625fea397ef36dff4e955 Mon Sep 17 00:00:00 2001 From: Soveu Date: Tue, 23 Apr 2024 22:14:41 +0200 Subject: [PATCH 137/330] Stabilize `extended_varargs_abi_support` --- compiler/rustc_feature/src/accepted.rs | 3 ++ compiler/rustc_feature/src/unstable.rs | 3 -- compiler/rustc_hir_analysis/messages.ftl | 2 +- compiler/rustc_hir_analysis/src/errors.rs | 3 +- compiler/rustc_hir_analysis/src/lib.rs | 31 +---------- library/std/src/lib.rs | 1 - .../extended-varargs-abi-support.md | 10 ---- ...ature-gate-extended_varargs_abi_support.rs | 19 ------- ...e-gate-extended_varargs_abi_support.stderr | 52 ------------------- tests/ui/c-variadic/variadic-ffi-1.stderr | 2 +- tests/ui/c-variadic/variadic-ffi-2-arm.rs | 1 - tests/ui/c-variadic/variadic-ffi-2.rs | 1 - tests/ui/c-variadic/variadic-ffi-2.stderr | 2 +- .../cmse-nonsecure-call/generics.rs | 2 +- .../cmse-nonsecure-call/generics.stderr | 2 +- tests/ui/error-codes/E0045.stderr | 2 +- 16 files changed, 12 insertions(+), 124 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md delete mode 100644 tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs delete mode 100644 tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e910415c3457..e1678a70f38b 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -193,6 +193,9 @@ declare_features! ( (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), + /// Allows using `efiapi`, `aapcs`, `sysv64` and `win64` as calling + /// convention for functions with varargs. + (accepted, extended_varargs_abi_support, "CURRENT_RUSTC_VERSION", Some(100189)), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660)), /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cf0f2a7e48c9..229e97831fe2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -471,9 +471,6 @@ declare_features! ( (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), - /// Allows using `efiapi`, `sysv64` and `win64` as calling convention - /// for functions with varargs. - (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), /// Allows defining `extern type`s. (unstable, extern_types, "1.23.0", Some(43467)), /// Allow using 128-bit (quad precision) floating point numbers. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index f5ccf8c9dffe..6f495b8920eb 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -587,7 +587,7 @@ hir_analysis_value_of_associated_struct_already_specified = .label = re-bound here .previous_bound_label = `{$item_name}` bound here first -hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions} +hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` .label = C-variadic function must have a compatible calling convention hir_analysis_variances_of = {$variances} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f5ca3c49475b..d348fd2d250e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -672,11 +672,10 @@ pub(crate) struct MainFunctionGenericParameters { #[derive(Diagnostic)] #[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)] -pub(crate) struct VariadicFunctionCompatibleConvention<'a> { +pub(crate) struct VariadicFunctionCompatibleConvention { #[primary_span] #[label] pub span: Span, - pub conventions: &'a str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 0a26b6776bbd..b25acfb30077 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -98,9 +98,7 @@ use rustc_middle::middle; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; -use rustc_session::parse::feature_err; use rustc_span::Span; -use rustc_span::symbol::sym; use rustc_trait_selection::traits; use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; @@ -113,34 +111,9 @@ fn require_c_abi_if_c_variadic( abi: ExternAbi, span: Span, ) { - const CONVENTIONS_UNSTABLE: &str = - "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; - const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; - const UNSTABLE_EXPLAIN: &str = - "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; - - if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { - return; + if decl.c_variadic && !abi.supports_varargs() { + tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span }); } - - let extended_abi_support = tcx.features().extended_varargs_abi_support(); - let conventions = match (extended_abi_support, abi.supports_varargs()) { - // User enabled additional ABI support for varargs and function ABI matches those ones. - (true, true) => return, - - // Using this ABI would be ok, if the feature for additional ABI support was enabled. - // Return CONVENTIONS_STABLE, because we want the other error to look the same. - (false, true) => { - feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN) - .emit(); - CONVENTIONS_STABLE - } - - (false, false) => CONVENTIONS_STABLE, - (true, false) => CONVENTIONS_UNSTABLE, - }; - - tcx.dcx().emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions }); } pub fn provide(providers: &mut Providers) { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b6723c6dfa59..ceaac4a88da4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -295,7 +295,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(extended_varargs_abi_support)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] diff --git a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md b/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md deleted file mode 100644 index b20c30ec8f1c..000000000000 --- a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md +++ /dev/null @@ -1,10 +0,0 @@ -# `extended_varargs_abi_support` - -The tracking issue for this feature is: [#100189] - -[#100189]: https://github.com/rust-lang/rust/issues/100189 - ------------------------- - -This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling -conventions on functions with varargs. diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs deleted file mode 100644 index d47a8e085fd3..000000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ only-x86_64 - -fn efiapi(f: extern "efiapi" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - f(22, 44); -} -fn sysv(f: extern "sysv64" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - f(22, 44); -} -fn win(f: extern "win64" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - //~^^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - f(22, 44); -} - -fn main() {} diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr deleted file mode 100644 index 41be37842454..000000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr +++ /dev/null @@ -1,52 +0,0 @@ -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 - | -LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 for more information - = help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 - | -LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention - -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12 - | -LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 for more information - = help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:8:12 - | -LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention - -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11 - | -LL | fn win(f: extern "win64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 for more information - = help: add `#![feature(extended_varargs_abi_support)]` 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[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/feature-gate-extended_varargs_abi_support.rs:13:11 - | -LL | fn win(f: extern "win64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention - -error: aborting due to 6 previous errors - -Some errors have detailed explanations: E0045, E0658. -For more information about an error, try `rustc --explain E0045`. diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr index 72d60a1439af..ed5ff042a659 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.stderr +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/variadic-ffi-1.rs:9:5 | LL | fn printf(_: *const u8, ...); diff --git a/tests/ui/c-variadic/variadic-ffi-2-arm.rs b/tests/ui/c-variadic/variadic-ffi-2-arm.rs index 3b0a71007a0e..82f9df5053c1 100644 --- a/tests/ui/c-variadic/variadic-ffi-2-arm.rs +++ b/tests/ui/c-variadic/variadic-ffi-2-arm.rs @@ -1,6 +1,5 @@ //@ only-arm //@ build-pass -#![feature(extended_varargs_abi_support)] fn aapcs(f: extern "aapcs" fn(usize, ...)) { f(22, 44); diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs index bafb7e2b20cc..17a1065279f4 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.rs +++ b/tests/ui/c-variadic/variadic-ffi-2.rs @@ -1,5 +1,4 @@ //@ ignore-arm stdcall isn't supported -#![feature(extended_varargs_abi_support)] #[allow(unsupported_fn_ptr_calling_conventions)] fn baz(f: extern "stdcall" fn(usize, ...)) { diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr index e52de93a9264..fbf273b1f1db 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.stderr +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -1,5 +1,5 @@ error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` - --> $DIR/variadic-ffi-2.rs:5:11 + --> $DIR/variadic-ffi-2.rs:4:11 | LL | fn baz(f: extern "stdcall" fn(usize, ...)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs index 9e0ffa75c229..da1327dace5d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs @@ -39,4 +39,4 @@ type WithTransparentTraitObject = //~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); -//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045] +//~^ ERROR C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` [E0045] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr index 7cb8e135ea31..f20e67e3d943 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr @@ -68,7 +68,7 @@ LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTranspa = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/generics.rs:41:20 | LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); diff --git a/tests/ui/error-codes/E0045.stderr b/tests/ui/error-codes/E0045.stderr index 25b2f2654da1..b8ee31a40495 100644 --- a/tests/ui/error-codes/E0045.stderr +++ b/tests/ui/error-codes/E0045.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` +error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` --> $DIR/E0045.rs:1:17 | LL | extern "Rust" { fn foo(x: u8, ...); } From 52684a4c52d34ca01e266219d276759ec1580754 Mon Sep 17 00:00:00 2001 From: Monadic Cat Date: Wed, 27 Nov 2024 18:26:08 -0600 Subject: [PATCH 138/330] update comment (codegen_backend -> codegen_crate) use intra-doc links so there'll be a doc gen fail next time this becomes wrong --- compiler/rustc_codegen_ssa/src/traits/backend.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index cbf214763b42..805f6c594e49 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -71,11 +71,11 @@ pub trait CodegenBackend { need_metadata_module: bool, ) -> Box; - /// This is called on the returned `Box` from `codegen_backend` + /// This is called on the returned `Box` from [`codegen_crate`](Self::codegen_crate) /// /// # Panics /// - /// Panics when the passed `Box` was not returned by `codegen_backend`. + /// Panics when the passed `Box` was not returned by [`codegen_crate`](Self::codegen_crate). fn join_codegen( &self, ongoing_codegen: Box, From ca55eeeaf36b059dad6d2a170a37d1544682168d Mon Sep 17 00:00:00 2001 From: Monadic Cat Date: Wed, 27 Nov 2024 18:42:14 -0600 Subject: [PATCH 139/330] use intra-doc links for CodegenBackend::link --- compiler/rustc_codegen_ssa/src/traits/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 805f6c594e49..7eab889edf05 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -83,7 +83,7 @@ pub trait CodegenBackend { outputs: &OutputFilenames, ) -> (CodegenResults, FxIndexMap); - /// This is called on the returned `CodegenResults` from `join_codegen` + /// This is called on the returned [`CodegenResults`] from [`join_codegen`](Self::join_codegen). fn link( &self, sess: &Session, From c3c68c5cb1a6a00ed90f2443d3a387dbe437d6b0 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 28 Nov 2024 01:35:36 +0000 Subject: [PATCH 140/330] Trim extra space in 'repeated `mut`' diagnostic --- compiler/rustc_parse/src/errors.rs | 3 ++- compiler/rustc_parse/src/parser/pat.rs | 4 ++- tests/ui/parser/mut-patterns.rs | 4 +++ tests/ui/parser/mut-patterns.stderr | 36 +++++++++++++++++--------- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 9bdb99dc0007..315173050d70 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2611,8 +2611,9 @@ pub(crate) enum InvalidMutInPattern { #[diag(parse_repeated_mut_in_pattern)] pub(crate) struct RepeatedMutInPattern { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] pub span: Span, + #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 004b5b348136..bb976e092bf4 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1089,7 +1089,9 @@ impl<'a> Parser<'a> { return; } - self.dcx().emit_err(RepeatedMutInPattern { span: lo.to(self.prev_token.span) }); + let span = lo.to(self.prev_token.span); + let suggestion = span.with_hi(self.token.span.lo()); + self.dcx().emit_err(RepeatedMutInPattern { span, suggestion }); } /// Parse macro invocation diff --git a/tests/ui/parser/mut-patterns.rs b/tests/ui/parser/mut-patterns.rs index b8610c4e1905..45968a516e3d 100644 --- a/tests/ui/parser/mut-patterns.rs +++ b/tests/ui/parser/mut-patterns.rs @@ -15,6 +15,10 @@ pub fn main() { //~^ ERROR `mut` on a binding may not be repeated //~| remove the additional `mut`s + let mut mut mut mut mut x = 0; + //~^ ERROR `mut` on a binding may not be repeated + //~| remove the additional `mut`s + struct Foo { x: isize } let mut Foo { x: x } = Foo { x: 3 }; //~^ ERROR `mut` must be attached to each individual binding diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr index f4f11b88d361..ad19a60af34e 100644 --- a/tests/ui/parser/mut-patterns.stderr +++ b/tests/ui/parser/mut-patterns.stderr @@ -45,11 +45,23 @@ LL | let mut mut x = 0; help: remove the additional `mut`s | LL - let mut mut x = 0; -LL + let mut x = 0; +LL + let mut x = 0; + | + +error: `mut` on a binding may not be repeated + --> $DIR/mut-patterns.rs:18:13 + | +LL | let mut mut mut mut mut x = 0; + | ^^^^^^^^^^^^^^^ + | +help: remove the additional `mut`s + | +LL - let mut mut mut mut mut x = 0; +LL + let mut x = 0; | error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:19:9 + --> $DIR/mut-patterns.rs:23:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; | ^^^^^^^^^^^^^^^^ @@ -61,7 +73,7 @@ LL | let Foo { x: mut x } = Foo { x: 3 }; | ~~~~~~~~~~~~~~~~ error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:23:9 + --> $DIR/mut-patterns.rs:27:9 | LL | let mut Foo { x } = Foo { x: 3 }; | ^^^^^^^^^^^^^ @@ -73,7 +85,7 @@ LL | let Foo { mut x } = Foo { x: 3 }; | ~~~~~~~~~~~~~ error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:28:13 + --> $DIR/mut-patterns.rs:32:13 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^ @@ -81,11 +93,11 @@ LL | let mut mut yield(become, await) = r#yield(0, 0); help: remove the additional `mut`s | LL - let mut mut yield(become, await) = r#yield(0, 0); -LL + let mut yield(become, await) = r#yield(0, 0); +LL + let mut yield(become, await) = r#yield(0, 0); | error: expected identifier, found reserved keyword `yield` - --> $DIR/mut-patterns.rs:28:17 + --> $DIR/mut-patterns.rs:32:17 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -96,7 +108,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0); | ++ error: expected identifier, found reserved keyword `become` - --> $DIR/mut-patterns.rs:28:23 + --> $DIR/mut-patterns.rs:32:23 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^ expected identifier, found reserved keyword @@ -107,7 +119,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0); | ++ error: expected identifier, found keyword `await` - --> $DIR/mut-patterns.rs:28:31 + --> $DIR/mut-patterns.rs:32:31 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found keyword @@ -118,7 +130,7 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0); | ++ error: `mut` must be followed by a named binding - --> $DIR/mut-patterns.rs:28:9 + --> $DIR/mut-patterns.rs:32:9 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^^^ @@ -131,7 +143,7 @@ LL + let yield(become, await) = r#yield(0, 0); | error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:37:9 + --> $DIR/mut-patterns.rs:41:9 | LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,7 +155,7 @@ LL | let W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f })))) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: expected identifier, found `x` - --> $DIR/mut-patterns.rs:44:21 + --> $DIR/mut-patterns.rs:48:21 | LL | let mut $p = 0; | ^^ expected identifier @@ -153,5 +165,5 @@ LL | foo!(x); | = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors From f0c301ffe47470caf3f809ee8fc0119e4cb49317 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Nov 2024 15:44:10 +0100 Subject: [PATCH 141/330] Fix new clippy lints --- src/librustdoc/clean/cfg.rs | 2 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 18 ++- src/librustdoc/clean/types.rs | 30 +++-- src/librustdoc/config.rs | 4 +- src/librustdoc/doctest.rs | 2 +- src/librustdoc/doctest/rust.rs | 2 +- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/html/escape.rs | 6 +- src/librustdoc/html/format.rs | 31 +++-- src/librustdoc/html/highlight.rs | 6 +- src/librustdoc/html/layout.rs | 2 +- src/librustdoc/html/length_limit.rs | 17 ++- src/librustdoc/html/markdown.rs | 33 +++-- src/librustdoc/html/markdown/footnotes.rs | 2 +- src/librustdoc/html/render/context.rs | 8 +- src/librustdoc/html/render/mod.rs | 22 ++-- src/librustdoc/html/render/ordered_json.rs | 2 +- src/librustdoc/html/render/print_item.rs | 22 ++-- src/librustdoc/html/render/search_index.rs | 56 ++++---- .../html/render/search_index/encode.rs | 12 +- src/librustdoc/html/render/sidebar.rs | 6 +- src/librustdoc/html/render/sorted_template.rs | 2 +- src/librustdoc/html/render/span_map.rs | 2 +- src/librustdoc/html/render/write_shared.rs | 56 ++++---- src/librustdoc/html/sources.rs | 6 +- src/librustdoc/html/static_files.rs | 2 +- src/librustdoc/json/mod.rs | 8 +- src/librustdoc/lint.rs | 2 +- .../passes/calculate_doc_coverage.rs | 4 +- .../passes/check_doc_test_visibility.rs | 4 +- .../passes/collect_intra_doc_links.rs | 52 ++++---- src/librustdoc/passes/collect_trait_impls.rs | 6 +- src/librustdoc/passes/lint.rs | 4 +- src/librustdoc/passes/lint/bare_urls.rs | 6 +- .../passes/lint/check_code_block_syntax.rs | 2 +- src/librustdoc/passes/lint/html_tags.rs | 16 +-- .../passes/lint/redundant_explicit_links.rs | 122 ++++++++---------- .../passes/lint/unescaped_backticks.rs | 32 ++--- .../passes/lint/unportable_markdown.rs | 14 +- src/librustdoc/passes/propagate_doc_cfg.rs | 4 +- src/librustdoc/passes/propagate_stability.rs | 2 +- .../passes/strip_aliased_non_local.rs | 6 +- src/librustdoc/passes/strip_hidden.rs | 4 +- src/librustdoc/passes/stripper.rs | 12 +- src/librustdoc/theme.rs | 2 +- src/librustdoc/visit.rs | 2 +- src/librustdoc/visit_ast.rs | 8 +- 48 files changed, 327 insertions(+), 342 deletions(-) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 9255242611af..0dfb8a52ebab 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -391,7 +391,7 @@ fn write_with_opt_paren( Ok(()) } -impl<'a> fmt::Display for Display<'a> { +impl fmt::Display for Display<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.0 { Cfg::Not(ref child) => match **child { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5ddd6188c2d8..d81c47886d2d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -367,7 +367,7 @@ pub(crate) fn build_impls( let tcx = cx.tcx; // for each implementation of an item represented by `did`, build the clean::Item for that impl - for &did in tcx.inherent_impls(did).into_iter() { + for &did in tcx.inherent_impls(did).iter() { cx.with_param_env(did, |cx| { build_impl(cx, did, attrs, ret); }); @@ -382,7 +382,7 @@ pub(crate) fn build_impls( if tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; - for &did in tcx.incoherent_impls(type_).into_iter() { + for &did in tcx.incoherent_impls(type_).iter() { cx.with_param_env(did, |cx| { build_impl(cx, did, attrs, ret); }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 97a2c3310126..093f216accbe 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2509,16 +2509,14 @@ fn clean_generic_args<'tcx>( let args = generic_args .args .iter() - .filter_map(|arg| { - Some(match arg { - hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { - GenericArg::Lifetime(clean_lifetime(lt, cx)) - } - hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), - hir::GenericArg::Infer(_inf) => GenericArg::Infer, - }) + .map(|arg| match arg { + hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { + GenericArg::Lifetime(clean_lifetime(lt, cx)) + } + hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), + hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), + hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), + hir::GenericArg::Infer(_inf) => GenericArg::Infer, }) .collect::>() .into(); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a10a6a92bf57..01d2661f73ed 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -264,17 +264,19 @@ impl ExternalCrate { // rendering by delegating everything to a hash map. let as_primitive = |res: Res| { let Res::Def(DefKind::Mod, def_id) = res else { return None }; - tcx.get_attrs(def_id, sym::rustc_doc_primitive).find_map(|attr| { - let attr_value = attr.value_str().expect("syntax should already be validated"); - let Some(prim) = PrimitiveType::from_symbol(attr_value) else { - span_bug!( - attr.span, - "primitive `{attr_value}` is not a member of `PrimitiveType`" - ); - }; + tcx.get_attrs(def_id, sym::rustc_doc_primitive) + .map(|attr| { + let attr_value = attr.value_str().expect("syntax should already be validated"); + let Some(prim) = PrimitiveType::from_symbol(attr_value) else { + span_bug!( + attr.span, + "primitive `{attr_value}` is not a member of `PrimitiveType`" + ); + }; - Some((def_id, prim)) - }) + (def_id, prim) + }) + .next() }; if root.is_local() { @@ -339,7 +341,7 @@ pub(crate) struct ItemInner { impl std::ops::Deref for Item { type Target = ItemInner; fn deref(&self) -> &ItemInner { - &*self.inner + &self.inner } } @@ -412,7 +414,7 @@ impl Item { pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { let kind = match &self.kind { - ItemKind::StrippedItem(k) => &*k, + ItemKind::StrippedItem(k) => k, _ => &self.kind, }; match kind { @@ -1870,7 +1872,7 @@ impl PrimitiveType { .get(self) .into_iter() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter()) + .flat_map(move |&simp| tcx.incoherent_impls(simp).iter()) .copied() } @@ -1878,7 +1880,7 @@ impl PrimitiveType { Self::simplified_types() .values() .flatten() - .flat_map(move |&simp| tcx.incoherent_impls(simp).into_iter()) + .flat_map(move |&simp| tcx.incoherent_impls(simp).iter()) .copied() } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 5071ed1c47fa..34c91e33db70 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -178,7 +178,7 @@ impl fmt::Debug for Options { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { struct FmtExterns<'a>(&'a Externs); - impl<'a> fmt::Debug for FmtExterns<'a> { + impl fmt::Debug for FmtExterns<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.0.iter()).finish() } @@ -508,7 +508,7 @@ impl Options { }; let parts_out_dir = - match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() { + match matches.opt_str("parts-out-dir").map(PathToParts::from_flag).transpose() { Ok(parts_out_dir) => parts_out_dir, Err(e) => dcx.fatal(e), }; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 25e576e9e63a..da1316a19cc3 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -700,7 +700,7 @@ impl IndividualTestOptions { fn new(options: &RustdocOptions, test_id: &Option, test_path: PathBuf) -> Self { let outdir = if let Some(ref path) = options.persist_doctests { let mut path = path.clone(); - path.push(&test_id.as_deref().unwrap_or("")); + path.push(test_id.as_deref().unwrap_or("")); if let Err(err) = std::fs::create_dir_all(&path) { eprintln!("Couldn't create directory for doctest executables: {err}"); diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 27d0be133fea..dc68f48f635b 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -88,7 +88,7 @@ impl<'tcx> HirCollector<'tcx> { } } -impl<'tcx> HirCollector<'tcx> { +impl HirCollector<'_> { fn visit_testable( &mut self, name: String, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index ff0d537b19f7..e387eb010beb 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -203,7 +203,7 @@ impl Cache { } } -impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { +impl DocFolder for CacheBuilder<'_, '_> { fn fold_item(&mut self, item: clean::Item) -> Option { if item.item_id.is_local() { debug!( diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 31a2701f06a5..48771571f8ff 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -11,7 +11,7 @@ use unicode_segmentation::UnicodeSegmentation; /// string when passed to a format string. pub(crate) struct Escape<'a>(pub &'a str); -impl<'a> fmt::Display for Escape<'a> { +impl fmt::Display for Escape<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -49,7 +49,7 @@ impl<'a> fmt::Display for Escape<'a> { /// difference, use [`Escape`]. pub(crate) struct EscapeBodyText<'a>(pub &'a str); -impl<'a> fmt::Display for EscapeBodyText<'a> { +impl fmt::Display for EscapeBodyText<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Because the internet is always right, turns out there's not that many // characters to escape: http://stackoverflow.com/questions/7381974 @@ -86,7 +86,7 @@ impl<'a> fmt::Display for EscapeBodyText<'a> { /// difference, use [`Escape`]. pub(crate) struct EscapeBodyTextWithWbr<'a>(pub &'a str); -impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { +impl fmt::Display for EscapeBodyTextWithWbr<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let EscapeBodyTextWithWbr(text) = *self; if text.len() < 8 { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 46bc2915d0a3..0a563b1df262 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -9,6 +9,7 @@ use std::borrow::Cow; use std::cell::Cell; +use std::cmp::Ordering; use std::fmt::{self, Display, Write}; use std::iter::{self, once}; @@ -785,16 +786,20 @@ pub(crate) fn href_relative_parts<'fqp>( ); } } - // e.g. linking to std::sync::atomic from std::sync - if relative_to_fqp.len() < fqp.len() { - Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied()) - // e.g. linking to std::sync from std::sync::atomic - } else if fqp.len() < relative_to_fqp.len() { - let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); - Box::new(iter::repeat(sym::dotdot).take(dissimilar_part_count)) - // linking to the same module - } else { - Box::new(iter::empty()) + match relative_to_fqp.len().cmp(&fqp.len()) { + Ordering::Less => { + // e.g. linking to std::sync::atomic from std::sync + Box::new(fqp[relative_to_fqp.len()..fqp.len()].iter().copied()) + } + Ordering::Greater => { + // e.g. linking to std::sync from std::sync::atomic + let dissimilar_part_count = relative_to_fqp.len() - fqp.len(); + Box::new(iter::repeat(sym::dotdot).take(dissimilar_part_count)) + } + Ordering::Equal => { + // linking to the same module + Box::new(iter::empty()) + } } } @@ -1384,7 +1389,7 @@ impl clean::Impl { write!(f, ">")?; } } else { - fmt_type(&type_, f, use_absolute, cx)?; + fmt_type(type_, f, use_absolute, cx)?; } Ok(()) } @@ -1531,14 +1536,14 @@ impl clean::FnDecl { (None, Some(last_i)) if i != last_i => write!(f, ", ")?, (None, Some(_)) => (), (Some(n), Some(last_i)) if i != last_i => write!(f, ",\n{}", Indent(n + 4))?, - (Some(_), Some(_)) => write!(f, ",\n")?, + (Some(_), Some(_)) => writeln!(f, ",")?, } } if self.c_variadic { match line_wrapping_indent { None => write!(f, ", ...")?, - Some(n) => write!(f, "{}...\n", Indent(n + 4))?, + Some(n) => writeln!(f, "{}...", Indent(n + 4))?, }; } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index b2fc1a47f78f..48a537ad5e7a 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -144,7 +144,7 @@ struct TokenHandler<'a, 'tcx, F: Write> { href_context: Option>, } -impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { +impl TokenHandler<'_, '_, F> { fn handle_exit_span(&mut self) { // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is // being used in `write_pending_elems`. @@ -207,7 +207,7 @@ impl<'a, 'tcx, F: Write> TokenHandler<'a, 'tcx, F> { } } -impl<'a, 'tcx, F: Write> Drop for TokenHandler<'a, 'tcx, F> { +impl Drop for TokenHandler<'_, '_, F> { /// When leaving, we need to flush all pending data to not have missing content. fn drop(&mut self) { if self.pending_exit_span.is_some() { @@ -1017,7 +1017,7 @@ fn string_without_closing_tag( .ok() .map(|(url, _, _)| url), LinkFromSrc::Doc(def_id) => { - format::href_with_root_path(*def_id, context, Some(&href_context.root_path)) + format::href_with_root_path(*def_id, context, Some(href_context.root_path)) .ok() .map(|(doc_link, _, _)| doc_link) } diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 31ccfeb38738..b4bc0b80d6c6 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -33,7 +33,7 @@ pub(crate) struct Page<'a> { pub(crate) rust_logo: bool, } -impl<'a> Page<'a> { +impl Page<'_> { pub(crate) fn get_static_root_path(&self) -> String { match self.static_root_path { Some(s) => s.to_string(), diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs index 8562e103dc17..fdb1ddc1f531 100644 --- a/src/librustdoc/html/length_limit.rs +++ b/src/librustdoc/html/length_limit.rs @@ -77,7 +77,7 @@ impl HtmlWithLimit { /// This function will panic if called with a non-alphabetic `tag_name`. pub(super) fn open_tag(&mut self, tag_name: &'static str) { assert!( - tag_name.chars().all(|c| ('a'..='z').contains(&c)), + tag_name.chars().all(|c: char| c.is_ascii_lowercase()), "tag_name contained non-alphabetic chars: {tag_name:?}", ); self.queued_tags.push(tag_name); @@ -85,16 +85,15 @@ impl HtmlWithLimit { /// Close the most recently opened HTML tag. pub(super) fn close_tag(&mut self) { - match self.unclosed_tags.pop() { + if let Some(tag_name) = self.unclosed_tags.pop() { // Close the most recently opened tag. - Some(tag_name) => write!(self.buf, "").unwrap(), - // There are valid cases where `close_tag()` is called without - // there being any tags to close. For example, this occurs when - // a tag is opened after the length limit is exceeded; - // `flush_queue()` will never be called, and thus, the tag will - // not end up being added to `unclosed_tags`. - None => {} + write!(self.buf, "").unwrap() } + // There are valid cases where `close_tag()` is called without + // there being any tags to close. For example, this occurs when + // a tag is opened after the length limit is exceeded; + // `flush_queue()` will never be called, and thus, the tag will + // not end up being added to `unclosed_tags`. } /// Write all queued tags and add them to the `unclosed_tags` list. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 1d42ec8eec7c..b6829d5457ba 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -499,7 +499,7 @@ struct HeadingLinks<'a, 'b, 'ids, I> { heading_offset: HeadingOffset, } -impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { +impl<'b, 'ids, I> HeadingLinks<'_, 'b, 'ids, I> { fn new( iter: I, toc: Option<&'b mut TocBuilder>, @@ -510,9 +510,7 @@ impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> { } } -impl<'a, 'b, 'ids, I: Iterator>> Iterator - for HeadingLinks<'a, 'b, 'ids, I> -{ +impl<'a, I: Iterator>> Iterator for HeadingLinks<'a, '_, '_, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { @@ -908,7 +906,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } fn parse_string(&mut self, start: usize) -> Option { - while let Some((pos, c)) = self.inner.next() { + for (pos, c) in self.inner.by_ref() { if c == '"' { return Some(Indices { start: start + 1, end: pos }); } @@ -1032,7 +1030,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { /// Returns `false` if an error was emitted. fn skip_paren_block(&mut self) -> bool { - while let Some((_, c)) = self.inner.next() { + for (_, c) in self.inner.by_ref() { if c == ')' { return true; } @@ -1074,9 +1072,8 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { return Some(LangStringToken::LangToken(&self.data[start..pos])); } return self.next(); - } else if pos == start && is_leading_char(c) { - continue; - } else if pos != start && is_bareword_char(c) { + } else if (pos == start && is_leading_char(c)) || (pos != start && is_bareword_char(c)) + { continue; } else { self.emit_error(format!("unexpected character `{c}`")); @@ -1088,7 +1085,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> { } } -impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { +impl<'a> Iterator for TagIterator<'a, '_> { type Item = LangStringToken<'a>; fn next(&mut self) -> Option { @@ -1324,7 +1321,7 @@ impl Markdown<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1358,7 +1355,7 @@ impl MarkdownWithToc<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1428,7 +1425,7 @@ impl MarkdownSummaryLine<'_> { let mut replacer = |broken_link: BrokenLink<'_>| { links .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1475,7 +1472,7 @@ fn markdown_summary_with_limit( let mut replacer = |broken_link: BrokenLink<'_>| { link_names .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1556,7 +1553,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin let mut replacer = |broken_link: BrokenLink<'_>| { link_names .iter() - .find(|link| &*link.original_text == &*broken_link.reference) + .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; @@ -1751,7 +1748,7 @@ pub(crate) fn markdown_links<'md, R>( }; let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); - let mut event_iter = Parser::new_with_broken_link_callback( + let event_iter = Parser::new_with_broken_link_callback( md, main_body_opts(), Some(&mut broken_link_callback), @@ -1759,7 +1756,7 @@ pub(crate) fn markdown_links<'md, R>( .into_offset_iter(); let mut links = Vec::new(); - while let Some((event, span)) = event_iter.next() { + for (event, span) in event_iter { match event { Event::Start(Tag::Link { link_type, dest_url, .. }) if may_be_doc_link(link_type) => { let range = match link_type { @@ -1821,7 +1818,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec>> Footnotes<'a, 'b, I> { } } -impl<'a, 'b, I: Iterator>> Iterator for Footnotes<'a, 'b, I> { +impl<'a, I: Iterator>> Iterator for Footnotes<'a, '_, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5f255c18ec6a..3a8144621747 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -200,7 +200,7 @@ impl<'tcx> Context<'tcx> { }; title.push_str(" - Rust"); let tyname = it.type_(); - let desc = plain_text_summary(&it.doc_value(), &it.link_names(&self.cache())); + let desc = plain_text_summary(&it.doc_value(), &it.link_names(self.cache())); let desc = if !desc.is_empty() { desc } else if it.is_crate() { @@ -739,7 +739,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { &shared.layout, &page, "", - scrape_examples_help(&*shared), + scrape_examples_help(&shared), &shared.style_files, ); shared.fs.write(scrape_examples_help_file, v)?; @@ -779,7 +779,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.render_redirect_pages = item.is_stripped(); } let item_name = item.name.unwrap(); - self.dst.push(&*item_name.as_str()); + self.dst.push(item_name.as_str()); self.current.push(item_name); info!("Recursing into {}", self.dst.display()); @@ -812,7 +812,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { unreachable!() }; let items = self.build_sidebar_items(module); - let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix)); + let js_dst = self.dst.join(format!("sidebar-items{}.js", self.shared.resource_suffix)); let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap()); self.shared.fs.write(js_dst, v)?; } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f11356b44d88..7c5048cd164b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -151,13 +151,13 @@ impl RenderType { string.push('{'); write_optional_id(self.id, string); string.push('{'); - for generic in &self.generics.as_deref().unwrap_or_default()[..] { + for generic in self.generics.as_deref().unwrap_or_default() { generic.write_to_string(string); } string.push('}'); if self.bindings.is_some() { string.push('{'); - for binding in &self.bindings.as_deref().unwrap_or_default()[..] { + for binding in self.bindings.as_deref().unwrap_or_default() { string.push('{'); binding.0.write_to_string(string); string.push('{'); @@ -1963,7 +1963,7 @@ fn render_impl( w, "
{}
", Markdown { - content: &*dox, + content: dox, links: &i.impl_item.links(cx), ids: &mut cx.id_map, error_codes: cx.shared.codes, @@ -2093,9 +2093,7 @@ pub(crate) fn small_url_encode(s: String) -> String { // and https://url.spec.whatwg.org/#urlencoded-parsing // and https://url.spec.whatwg.org/#url-code-points fn dont_escape(c: u8) -> bool { - (b'a' <= c && c <= b'z') - || (b'A' <= c && c <= b'Z') - || (b'0' <= c && c <= b'9') + c.is_ascii_alphanumeric() || c == b'-' || c == b'_' || c == b'.' @@ -2150,7 +2148,7 @@ pub(crate) fn small_url_encode(s: String) -> String { } } -fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String { +fn get_id_for_impl(tcx: TyCtxt<'_>, impl_id: ItemId) -> String { use rustc_middle::ty::print::with_forced_trimmed_paths; let (type_, trait_) = match impl_id { ItemId::Auto { trait_, for_ } => { @@ -2381,7 +2379,7 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { let fqp = cache.exact_paths.get(&did).or_else(get_extern); if let Some(path) = fqp { - out.push(join_with_double_colon(&path)); + out.push(join_with_double_colon(path)); } }; @@ -2462,8 +2460,8 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c }; // Generate the HTML for a single example, being the title and code block - let write_example = |mut w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { - let contents = match fs::read_to_string(&path) { + let write_example = |w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { + let contents = match fs::read_to_string(path) { Ok(contents) => contents, Err(err) => { let span = item.span(tcx).map_or(DUMMY_SP, |span| span.inner()); @@ -2532,7 +2530,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c decoration_info.insert("highlight", byte_ranges); sources::print_src( - &mut w, + w, contents_subset, file_span, cx, @@ -2581,7 +2579,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c // An example may fail to write if its source can't be read for some reason, so this method // continues iterating until a write succeeds let write_and_skip_failure = |w: &mut W, it: &mut Peekable<_>| { - while let Some(example) = it.next() { + for example in it.by_ref() { if write_example(&mut *w, example) { break; } diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs index 7abe40eef3bd..d1dddfebc83a 100644 --- a/src/librustdoc/html/render/ordered_json.rs +++ b/src/librustdoc/html/render/ordered_json.rs @@ -23,7 +23,7 @@ impl OrderedJson { pub(crate) fn array_sorted, I: IntoIterator>(items: I) -> Self { let items = items .into_iter() - .sorted_unstable_by(|a, b| a.borrow().cmp(&b.borrow())) + .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow())) .format_with(",", |item, f| f(item.borrow())); Self(format!("[{}]", items)) } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index d247e90d298d..dc205252507c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -751,7 +751,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !required_methods.is_empty() { - write!(w, " // Required method{}\n", pluralize(required_methods.len())); + writeln!(w, " // Required method{}", pluralize(required_methods.len())); } for (pos, m) in required_methods.iter().enumerate() { render_assoc_item( @@ -773,7 +773,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !provided_methods.is_empty() { - write!(w, " // Provided method{}\n", pluralize(provided_methods.len())); + writeln!(w, " // Provided method{}", pluralize(provided_methods.len())); } for (pos, m) in provided_methods.iter().enumerate() { render_assoc_item( @@ -940,7 +940,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: "Dyn Compatibility", "dyn-compatibility", None, - &format!( + format!( "

This trait is not \ dyn compatible.

\

In older versions of Rust, dyn compatibility was called \"object safety\", \ @@ -1225,14 +1225,14 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c w, cx, Some(&t.generics), - &variants, + variants, variants_count, has_stripped_entries, *is_non_exhaustive, enum_def_id, ) }); - item_variants(w, cx, it, &variants, enum_def_id); + item_variants(w, cx, it, variants, enum_def_id); } clean::TypeAliasInnerType::Union { fields } => { wrap_item(w, |w| { @@ -1824,7 +1824,7 @@ fn item_constant( name = it.name.unwrap(), generics = generics.print(cx), typ = ty.print(cx), - where_clause = print_where_clause(&generics, cx, 0, Ending::NoNewline), + where_clause = print_where_clause(generics, cx, 0, Ending::NoNewline), ); // FIXME: The code below now prints @@ -2194,7 +2194,7 @@ fn render_union<'a, 'cx: 'a>( f.write_str(" ")?; } - write!(f, "{{\n")?; + writeln!(f, "{{")?; let count_fields = fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); @@ -2204,9 +2204,9 @@ fn render_union<'a, 'cx: 'a>( for field in fields { if let clean::StructFieldItem(ref ty) = field.kind { - write!( + writeln!( f, - " {}{}: {},\n", + " {}{}: {},", visibility_print_with_space(field, cx), field.name.unwrap(), ty.print(cx) @@ -2215,7 +2215,7 @@ fn render_union<'a, 'cx: 'a>( } if it.has_stripped_entries().unwrap() { - write!(f, " /* private fields */\n")?; + writeln!(f, " /* private fields */")?; } if toggle { toggle_close(&mut f); @@ -2355,7 +2355,7 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a { +fn document_non_exhaustive(item: &clean::Item) -> impl fmt::Display + '_ { display_fn(|f| { if item.is_non_exhaustive() { write!( diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index f91fdfa1fb5f..cfb62c3ca164 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -55,10 +55,10 @@ pub(crate) struct SerializedSearchIndex { const DESC_INDEX_SHARD_LEN: usize = 128 * 1024; /// Builds the search index from the collected metadata -pub(crate) fn build_index<'tcx>( +pub(crate) fn build_index( krate: &clean::Crate, cache: &mut Cache, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, ) -> SerializedSearchIndex { // Maps from ID to position in the `crate_paths` array. let mut itemid_to_pathid = FxHashMap::default(); @@ -126,7 +126,7 @@ pub(crate) fn build_index<'tcx>( let mut lastpathid = 0isize; // First, on function signatures - let mut search_index = std::mem::replace(&mut cache.search_index, Vec::new()); + let mut search_index = std::mem::take(&mut cache.search_index); for item in search_index.iter_mut() { fn insert_into_map( map: &mut FxHashMap, @@ -194,7 +194,7 @@ pub(crate) fn build_index<'tcx>( { let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)) + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)) // Re-exports only count if the name is exactly the same. // This is a size optimization, since it means we only need // to store the name once (and the path is re-used for everything @@ -298,7 +298,7 @@ pub(crate) fn build_index<'tcx>( true }); } - let Some(id) = ty.id.clone() else { + let Some(id) = ty.id else { assert!(ty.generics.is_some()); return; }; @@ -372,7 +372,7 @@ pub(crate) fn build_index<'tcx>( if let Some(&(ref fqp, short)) = paths.get(&defid) { let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)) + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)) .filter(|exact_fqp| { exact_fqp.last() == Some(&item.name) && *exact_fqp != fqp }); @@ -397,7 +397,7 @@ pub(crate) fn build_index<'tcx>( // Their parent carries the exact fqp instead. let exact_fqp = exact_paths .get(&defid) - .or_else(|| external_paths.get(&defid).map(|&(ref fqp, _)| fqp)); + .or_else(|| external_paths.get(&defid).map(|(fqp, _)| fqp)); item.exact_path = exact_fqp.and_then(|fqp| { // Re-exports only count if the name is exactly the same. // This is a size optimization, since it means we only need @@ -426,7 +426,7 @@ pub(crate) fn build_index<'tcx>( } // Omit the parent path if it is same to that of the prior item. - if lastpath == &item.path { + if lastpath == item.path { item.path.clear(); } else { lastpath = &item.path; @@ -512,7 +512,7 @@ pub(crate) fn build_index<'tcx>( } } - impl<'a> Serialize for CrateData<'a> { + impl Serialize for CrateData<'_> { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -640,7 +640,7 @@ pub(crate) fn build_index<'tcx>( let mut last_name = None; for (index, item) in self.items.iter().enumerate() { let n = item.ty as u8; - let c = char::try_from(n + b'A').expect("item types must fit in ASCII"); + let c = char::from(n + b'A'); assert!(c <= 'z', "item types must fit within ASCII printables"); types.push(c); @@ -741,22 +741,22 @@ pub(crate) fn build_index<'tcx>( let mut len: usize = 0; let mut item_index: u32 = 0; for desc in std::iter::once(&crate_doc).chain(crate_items.iter().map(|item| &item.desc)) { - if desc == "" { + if desc.is_empty() { empty_desc.push(item_index); item_index += 1; continue; } if set.len() >= DESC_INDEX_SHARD_LEN { - result.push((len, std::mem::replace(&mut set, String::new()))); + result.push((len, std::mem::take(&mut set))); len = 0; } else if len != 0 { set.push('\n'); } - set.push_str(&desc); + set.push_str(desc); len += 1; item_index += 1; } - result.push((len, std::mem::replace(&mut set, String::new()))); + result.push((len, std::mem::take(&mut set))); (empty_desc, result) }; @@ -792,9 +792,9 @@ pub(crate) fn build_index<'tcx>( SerializedSearchIndex { index, desc } } -pub(crate) fn get_function_type_for_search<'tcx>( +pub(crate) fn get_function_type_for_search( item: &clean::Item, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_generics: Option<&(clean::Type, clean::Generics)>, parent: Option, cache: &Cache, @@ -861,7 +861,7 @@ fn get_index_type_id( match *clean_type { clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())), clean::DynTrait(ref bounds, _) => { - bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id())) + bounds.first().map(|b| RenderTypeId::DefId(b.trait_.def_id())) } clean::Primitive(p) => Some(RenderTypeId::Primitive(p)), clean::BorrowedRef { .. } => Some(RenderTypeId::Primitive(clean::PrimitiveType::Reference)), @@ -953,7 +953,7 @@ fn simplify_fn_type<'a, 'tcx>( WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, _ => false, }) { - let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); + let bounds = where_pred.get_bounds().unwrap_or(&[]); for bound in bounds.iter() { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; @@ -1043,7 +1043,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1058,7 +1058,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1074,7 +1074,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &ty, + ty, tcx, recurse + 1, &mut ty_generics, @@ -1117,7 +1117,7 @@ fn simplify_fn_type<'a, 'tcx>( ); let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; res.push(RenderType { - id: get_index_type_id(&arg, rgen), + id: get_index_type_id(arg, rgen), bindings: Some(ty_bindings), generics: Some(ty_generics), }); @@ -1134,7 +1134,7 @@ fn simplify_fn_type<'a, 'tcx>( simplify_fn_type( self_, generics, - &type_, + type_, tcx, recurse + 1, &mut ty_generics, @@ -1249,7 +1249,7 @@ fn simplify_fn_type<'a, 'tcx>( } } } - let id = get_index_type_id(&arg, rgen); + let id = get_index_type_id(arg, rgen); if id.is_some() || !ty_generics.is_empty() { res.push(RenderType { id, @@ -1261,11 +1261,11 @@ fn simplify_fn_type<'a, 'tcx>( } } -fn simplify_fn_constraint<'a, 'tcx>( +fn simplify_fn_constraint<'a>( self_: Option<&'a Type>, generics: &Generics, constraint: &'a clean::AssocItemConstraint, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, recurse: usize, res: &mut Vec<(RenderTypeId, Vec)>, rgen: &mut FxIndexMap)>, @@ -1347,9 +1347,9 @@ fn simplify_fn_constraint<'a, 'tcx>( /// /// i.e. `fn foo>(x: u32, y: B)` will return /// `[u32, Display, Option]`. -fn get_fn_inputs_and_outputs<'tcx>( +fn get_fn_inputs_and_outputs( func: &Function, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>, cache: &Cache, ) -> (Vec, Vec, Vec, Vec>) { diff --git a/src/librustdoc/html/render/search_index/encode.rs b/src/librustdoc/html/render/search_index/encode.rs index 8d715814faad..8816ea650593 100644 --- a/src/librustdoc/html/render/search_index/encode.rs +++ b/src/librustdoc/html/render/search_index/encode.rs @@ -25,7 +25,7 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { break; } shift = shift.wrapping_sub(4); - mask = mask >> 4; + mask >>= 4; } // now write the rest while shift < 32 { @@ -33,7 +33,7 @@ pub(crate) fn write_vlqhex_to_string(n: i32, string: &mut String) { let hex = char::try_from(if shift == 0 { '`' } else { '@' } as u32 + hexit).unwrap(); string.push(hex); shift = shift.wrapping_sub(4); - mask = mask >> 4; + mask >>= 4; } } @@ -64,7 +64,7 @@ impl Container { Container::Array(array) => { array.push(value); if array.len() >= 4096 { - let array = std::mem::replace(array, Vec::new()); + let array = std::mem::take(array); *self = Container::Bits(Box::new([0; 1024])); for value in array { self.push(value); @@ -123,7 +123,7 @@ impl Container { if 2 + 4 * r >= 2 * array.len() + 2 { return false; } - let array = std::mem::replace(array, Vec::new()); + let array = std::mem::take(array); *self = Container::Run(Vec::new()); for value in array { self.push(value); @@ -145,7 +145,7 @@ pub(crate) fn write_bitmap_to_bytes( let mut keys = Vec::::new(); let mut containers = Vec::::new(); let mut key: u16; - let mut domain_iter = domain.into_iter().copied().peekable(); + let mut domain_iter = domain.iter().copied().peekable(); let mut has_run = false; while let Some(entry) = domain_iter.next() { key = (entry >> 16).try_into().expect("shifted off the top 16 bits, so it should fit"); @@ -236,7 +236,7 @@ pub(crate) fn write_bitmap_to_bytes( pub(crate) fn bitmap_to_string(domain: &[u32]) -> String { let mut buf = Vec::new(); let mut strbuf = String::new(); - write_bitmap_to_bytes(&domain, &mut buf).unwrap(); + write_bitmap_to_bytes(domain, &mut buf).unwrap(); BASE64_STANDARD.encode_string(&buf, &mut strbuf); strbuf } diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6df9486e6580..76de8d872311 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -44,7 +44,7 @@ pub(super) struct Sidebar<'a> { pub(super) path: String, } -impl<'a> Sidebar<'a> { +impl Sidebar<'_> { /// Only create a `

` if there are any blocks /// which should actually be rendered. pub fn should_render_blocks(&self) -> bool { @@ -564,9 +564,9 @@ pub(crate) fn sidebar_module_like( .filter(|sec| item_sections_in_use.contains(sec)) .map(|sec| Link::new(ids.derive(sec.id()), sec.name())) .collect(); - let header = if let Some(first_section) = item_sections.get(0) { + let header = if let Some(first_section) = item_sections.first() { Link::new( - first_section.href.to_owned(), + first_section.href.clone(), if module_like.is_crate() { "Crate Items" } else { "Module Items" }, ) } else { diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs index 28f7766d7c7a..dc894840f92a 100644 --- a/src/librustdoc/html/render/sorted_template.rs +++ b/src/librustdoc/html/render/sorted_template.rs @@ -84,7 +84,7 @@ impl FromStr for SortedTemplate { let offset = offset .strip_suffix(F::COMMENT_END) .ok_or(Error("last line expected to end with a comment"))?; - let offset: Offset = serde_json::from_str(&offset).map_err(|_| { + let offset: Offset = serde_json::from_str(offset).map_err(|_| { Error("could not find insertion location descriptor object on last line") })?; let (before, mut s) = diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index d4cca562d6c4..81d79a6be968 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -63,7 +63,7 @@ struct SpanMapVisitor<'tcx> { pub(crate) matches: FxHashMap, } -impl<'tcx> SpanMapVisitor<'tcx> { +impl SpanMapVisitor<'_> { /// This function is where we handle `hir::Path` elements and add them into the "span map". fn handle_path(&mut self, path: &rustc_hir::Path<'_>) { match path.res { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index c82f7e9aaf92..7c676469597d 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -68,8 +68,8 @@ pub(crate) fn write_shared( let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); let SerializedSearchIndex { index, desc } = - build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); - write_search_desc(cx, &krate, &desc)?; // does not need to be merged + build_index(krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); + write_search_desc(cx, krate, &desc)?; // does not need to be merged let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand @@ -80,7 +80,7 @@ pub(crate) fn write_shared( src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, - crates_index: CratesIndexPart::get(&crate_name, &external_crates)?, + crates_index: CratesIndexPart::get(crate_name, &external_crates)?, trait_impl: TraitAliasPart::get(cx, &crate_name_json)?, type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, }; @@ -112,7 +112,7 @@ pub(crate) fn write_shared( md_opts.output = cx.dst.clone(); md_opts.external_html = cx.shared.layout.external_html.clone(); try_err!( - crate::markdown::render_and_write(&index_page, md_opts, cx.shared.edition()), + crate::markdown::render_and_write(index_page, md_opts, cx.shared.edition()), &index_page ); } @@ -158,13 +158,13 @@ fn write_rendered_cross_crate_info( let m = &opt.should_merge; if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { if include_sources { - write_rendered_cci::(SourcesPart::blank, dst, &crates, m)?; + write_rendered_cci::(SourcesPart::blank, dst, crates, m)?; } - write_rendered_cci::(SearchIndexPart::blank, dst, &crates, m)?; - write_rendered_cci::(AllCratesPart::blank, dst, &crates, m)?; + write_rendered_cci::(SearchIndexPart::blank, dst, crates, m)?; + write_rendered_cci::(AllCratesPart::blank, dst, crates, m)?; } - write_rendered_cci::(TraitAliasPart::blank, dst, &crates, m)?; - write_rendered_cci::(TypeAliasPart::blank, dst, &crates, m)?; + write_rendered_cci::(TraitAliasPart::blank, dst, crates, m)?; + write_rendered_cci::(TypeAliasPart::blank, dst, crates, m)?; Ok(()) } @@ -234,7 +234,7 @@ fn write_search_desc( &cx.shared.resource_suffix, ); let path = path.join(filename); - let part = OrderedJson::serialize(&part).unwrap(); + let part = OrderedJson::serialize(part).unwrap(); let part = format!("searchState.loadedDescShard({encoded_crate_name}, {i}, {part})"); create_parents(&path)?; try_err!(fs::write(&path, part), &path); @@ -261,7 +261,7 @@ impl CrateInfo { .iter() .map(|parts_path| { let path = &parts_path.0; - let parts = try_err!(fs::read(&path), &path); + let parts = try_err!(fs::read(path), &path); let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path); Ok::<_, Error>(parts) }) @@ -439,7 +439,7 @@ impl CratesIndexPart { const DELIMITER: &str = "\u{FFFC}"; // users are being naughty if they have this let content = format!("

List of all crates

    {DELIMITER}
"); - let template = layout::render(layout, &page, "", content, &style_files); + let template = layout::render(layout, &page, "", content, style_files); match SortedTemplate::from_template(&template, DELIMITER) { Ok(template) => template, Err(e) => panic!( @@ -534,7 +534,7 @@ impl Hierarchy { } fn add_path(self: &Rc, path: &Path) { - let mut h = Rc::clone(&self); + let mut h = Rc::clone(self); let mut elems = path .components() .filter_map(|s| match s { @@ -606,7 +606,7 @@ impl TypeAliasPart { cache, cx, }; - DocVisitor::visit_crate(&mut type_impl_collector, &krate); + DocVisitor::visit_crate(&mut type_impl_collector, krate); let cx = type_impl_collector.cx; let aliased_types = type_impl_collector.aliased_types; for aliased_type in aliased_types.values() { @@ -623,7 +623,7 @@ impl TypeAliasPart { // render_impl will filter out "impossible-to-call" methods // to make that functionality work here, it needs to be called with // each type alias, and if it gives a different result, split the impl - for &(type_alias_fqp, ref type_alias_item) in type_aliases { + for &(type_alias_fqp, type_alias_item) in type_aliases { let mut buf = Buffer::html(); cx.id_map = Default::default(); cx.deref_id_map = Default::default(); @@ -643,8 +643,8 @@ impl TypeAliasPart { super::render_impl( &mut buf, cx, - *impl_, - &type_alias_item, + impl_, + type_alias_item, assoc_link, RenderMode::Normal, None, @@ -680,7 +680,7 @@ impl TypeAliasPart { path.push(component.as_str()); } let aliased_item_type = aliased_type.target_type; - path.push(&format!( + path.push(format!( "{aliased_item_type}.{}.js", aliased_type.target_fqp[aliased_type.target_fqp.len() - 1] )); @@ -781,7 +781,7 @@ impl TraitAliasPart { for component in &remote_path[..remote_path.len() - 1] { path.push(component.as_str()); } - path.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); + path.push(format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); let part = OrderedJson::array_sorted( implementors @@ -865,7 +865,7 @@ struct AliasedTypeImpl<'cache, 'item> { type_aliases: Vec<(&'cache [Symbol], &'item Item)>, } -impl<'cx, 'cache, 'item> DocVisitor<'item> for TypeImplCollector<'cx, 'cache, 'item> { +impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { fn visit_item(&mut self, it: &'item Item) { self.visit_item_recur(it); let cache = self.cache; @@ -963,15 +963,13 @@ fn get_path_parts( crates_info: &[CrateInfo], ) -> FxIndexMap> { let mut templates: FxIndexMap> = FxIndexMap::default(); - crates_info - .iter() - .map(|crate_info| T::from_crate_info(crate_info).parts.iter()) - .flatten() - .for_each(|(path, part)| { - let path = dst.join(&path); + crates_info.iter().flat_map(|crate_info| T::from_crate_info(crate_info).parts.iter()).for_each( + |(path, part)| { + let path = dst.join(path); let part = part.to_string(); templates.entry(path).or_default().push(part); - }); + }, + ); templates } @@ -994,10 +992,10 @@ where if !should_merge.read_rendered_cci { return Ok(make_blank()); } - match fs::read_to_string(&path) { + match fs::read_to_string(path) { Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)), Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()), - Err(e) => Err(Error::new(e, &path)), + Err(e) => Err(Error::new(e, path)), } } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index f4a0ef01c253..2fe9364c259c 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -35,8 +35,8 @@ pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), E Ok(()) } -pub(crate) fn collect_local_sources<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn collect_local_sources( + tcx: TyCtxt<'_>, src_root: &Path, krate: &clean::Crate, ) -> FxIndexMap { @@ -80,7 +80,7 @@ impl LocalSourcesCollector<'_, '_> { let href = RefCell::new(PathBuf::new()); clean_path( - &self.src_root, + self.src_root, &p, |component| { href.borrow_mut().push(component); diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index a4dc8cd1ed91..6457ac731cb7 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -57,7 +57,7 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { pub(crate) fn static_filename(filename: &str, sha256: &str) -> PathBuf { let filename = filename.rsplit('/').next().unwrap(); - suffix_path(filename, &sha256) + suffix_path(filename, sha256) } macro_rules! static_files { diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index df97c5ea2634..560ed872ef3a 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -73,7 +73,7 @@ impl<'tcx> JsonRenderer<'tcx> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - self.id_from_item(&item) + self.id_from_item(item) }) .collect() }) @@ -104,7 +104,7 @@ impl<'tcx> JsonRenderer<'tcx> { if item.item_id.is_local() || is_primitive_impl { self.item(item.clone()).unwrap(); - Some(self.id_from_item(&item)) + Some(self.id_from_item(item)) } else { None } @@ -223,7 +223,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::Macro(_) | types::ItemEnum::ProcMacro(_) => false, }; - let removed = self.index.borrow_mut().insert(new_item.id.clone(), new_item.clone()); + let removed = self.index.borrow_mut().insert(new_item.id, new_item.clone()); // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check // to make sure the items are unique. The main place this happens is when an item, is @@ -289,7 +289,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { format_version: types::FORMAT_VERSION, }; if let Some(ref out_dir) = self.out_dir { - try_err!(create_dir_all(&out_dir), out_dir); + try_err!(create_dir_all(out_dir), out_dir); let mut p = out_dir.clone(); p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap()); diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs index 2afb9e549d90..dcc27cd62e38 100644 --- a/src/librustdoc/lint.rs +++ b/src/librustdoc/lint.rs @@ -222,7 +222,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy> = Lazy::new(|| { }); pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) { - lint_store.register_lints(&**RUSTDOC_LINTS); + lint_store.register_lints(&RUSTDOC_LINTS); lint_store.register_group( true, "rustdoc::all", diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 9f9a093da8a3..135aa7990601 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -118,7 +118,7 @@ fn limit_filename_len(filename: String) -> String { } } -impl<'a, 'b> CoverageCalculator<'a, 'b> { +impl CoverageCalculator<'_, '_> { fn to_json(&self) -> String { serde_json::to_string( &self @@ -188,7 +188,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> { } } -impl<'a, 'b> DocVisitor<'_> for CoverageCalculator<'a, 'b> { +impl DocVisitor<'_> for CoverageCalculator<'_, '_> { fn visit_item(&mut self, i: &clean::Item) { if !i.item_id.is_local() { // non-local items are skipped because they can be out of the users control, diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 484bdb5627c3..bf851b278b82 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -34,7 +34,7 @@ pub(crate) fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) - krate } -impl<'a, 'tcx> DocVisitor<'_> for DocTestVisibilityLinter<'a, 'tcx> { +impl DocVisitor<'_> for DocTestVisibilityLinter<'_, '_> { fn visit_item(&mut self, item: &Item) { look_for_tests(self.cx, &item.doc_value(), item); @@ -106,7 +106,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - level != lint::Level::Allow || matches!(source, LintLevelSource::Default) } -pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) { +pub(crate) fn look_for_tests(cx: &DocContext<'_>, dox: &str, item: &Item) { let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { // If non-local, no need to check anything. return; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 140fda709188..c9d1ceb0a91a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -53,12 +53,12 @@ pub(crate) fn collect_intra_doc_links<'a, 'tcx>( (krate, collector) } -fn filter_assoc_items_by_name_and_namespace<'a>( - tcx: TyCtxt<'a>, +fn filter_assoc_items_by_name_and_namespace( + tcx: TyCtxt<'_>, assoc_items_of: DefId, ident: Ident, ns: Namespace, -) -> impl Iterator + 'a { +) -> impl Iterator + '_ { tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) @@ -232,7 +232,7 @@ impl UrlFragment { s.push_str(kind); s.push_str(tcx.item_name(def_id).as_str()); } - UrlFragment::UserWritten(raw) => s.push_str(&raw), + UrlFragment::UserWritten(raw) => s.push_str(raw), } } } @@ -307,7 +307,7 @@ pub(crate) struct AmbiguousLinks { resolved: Vec<(Res, Option)>, } -impl<'a, 'tcx> LinkCollector<'a, 'tcx> { +impl<'tcx> LinkCollector<'_, 'tcx> { /// Given a full link, parse it as an [enum struct variant]. /// /// In particular, this will return an error whenever there aren't three @@ -339,7 +339,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // If there's no third component, we saw `[a::b]` before and it failed to resolve. // So there's no partial res. let path = split.next().ok_or_else(no_res)?; - let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?; + let ty_res = self.resolve_path(path, TypeNS, item_id, module_id).ok_or_else(no_res)?; match ty_res { Res::Def(DefKind::Enum, did) => match tcx.type_of(did).instantiate_identity().kind() { @@ -628,7 +628,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .map(|item| (root_res, item.def_id)) .collect::>() }) - .unwrap_or(Vec::new()) + .unwrap_or_default() } } Res::Def(DefKind::TyAlias, did) => { @@ -693,7 +693,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // Checks if item_name belongs to `impl SomeItem` let mut assoc_items: Vec<_> = tcx .inherent_impls(did) - .into_iter() + .iter() .flat_map(|&imp| { filter_assoc_items_by_name_and_namespace( tcx, @@ -878,7 +878,7 @@ fn is_derive_trait_collision(ns: &PerNS, ResolutionFailu } } -impl<'a, 'tcx> DocVisitor<'_> for LinkCollector<'a, 'tcx> { +impl DocVisitor<'_> for LinkCollector<'_, '_> { fn visit_item(&mut self, item: &Item) { self.resolve_links(item); self.visit_item_recur(item) @@ -1152,7 +1152,7 @@ impl LinkCollector<'_, '_> { } cache.paths.get(&did).is_some() - || cache.external_paths.get(&did).is_some() + || cache.external_paths.contains_key(&did) || !did.is_local() } @@ -1271,7 +1271,7 @@ impl LinkCollector<'_, '_> { } res.def_id(self.cx.tcx).map(|page_id| ItemLink { - link: Box::::from(&*diag_info.ori_link), + link: Box::::from(diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1293,7 +1293,7 @@ impl LinkCollector<'_, '_> { let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id)); Some(ItemLink { - link: Box::::from(&*diag_info.ori_link), + link: Box::::from(diag_info.ori_link), link_text: link_text.clone(), page_id, fragment, @@ -1387,7 +1387,7 @@ impl LinkCollector<'_, '_> { ) .unwrap_or_else(|| item.attr_span(self.cx.tcx)); rustc_session::parse::feature_err( - &self.cx.tcx.sess, + self.cx.tcx.sess, sym::intra_doc_pointers, span, "linking to associated items of raw pointers is experimental", @@ -1414,7 +1414,7 @@ impl LinkCollector<'_, '_> { // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether. // However I'm not sure how to check that across crates. - if let Some(candidate) = candidates.get(0) + if let Some(candidate) = candidates.first() && candidate.0 == Res::Primitive(PrimitiveType::RawPointer) && key.path_str.contains("::") // We only want to check this if this is an associated item. @@ -1493,7 +1493,7 @@ impl LinkCollector<'_, '_> { } } resolution_failure(self, diag, path_str, disambiguator, smallvec![err]); - return vec![]; + vec![] } } } @@ -1509,15 +1509,12 @@ impl LinkCollector<'_, '_> { type_ns: candidate(TypeNS), value_ns: candidate(ValueNS).and_then(|v_res| { for (res, _) in v_res.iter() { - match res { - // Constructors are picked up in the type namespace. - Res::Def(DefKind::Ctor(..), _) => { - return Err(ResolutionFailure::WrongNamespace { - res: *res, - expected_ns: TypeNS, - }); - } - _ => {} + // Constructors are picked up in the type namespace. + if let Res::Def(DefKind::Ctor(..), _) = res { + return Err(ResolutionFailure::WrongNamespace { + res: *res, + expected_ns: TypeNS, + }); } } Ok(v_res) @@ -1536,7 +1533,7 @@ impl LinkCollector<'_, '_> { disambiguator, candidates.into_iter().filter_map(|res| res.err()).collect(), ); - return vec![]; + vec![] } else if len == 1 { candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::>() } else { @@ -1850,7 +1847,7 @@ fn report_diagnostic( (sp, MarkdownLinkRange::Destination(md_range)) } MarkdownLinkRange::WholeLink(md_range) => ( - source_span_for_markdown_range(tcx, dox, &md_range, &item.attrs.doc_strings), + source_span_for_markdown_range(tcx, dox, md_range, &item.attrs.doc_strings), link_range.clone(), ), }; @@ -1985,8 +1982,7 @@ fn resolution_failure( .tcx .resolutions(()) .all_macro_rules - .get(&Symbol::intern(path_str)) - .is_some() + .contains_key(&Symbol::intern(path_str)) { diag.note(format!( "`macro_rules` named `{path_str}` exists in this crate, \ diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index f35890803228..87f85c573152 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -229,7 +229,7 @@ struct SyntheticImplCollector<'a, 'tcx> { impls: Vec, } -impl<'a, 'tcx> DocVisitor<'_> for SyntheticImplCollector<'a, 'tcx> { +impl DocVisitor<'_> for SyntheticImplCollector<'_, '_> { fn visit_item(&mut self, i: &Item) { if i.is_struct() || i.is_enum() || i.is_union() { // FIXME(eddyb) is this `doc(hidden)` check needed? @@ -256,7 +256,7 @@ impl<'cache> ItemAndAliasCollector<'cache> { } } -impl<'cache> DocVisitor<'_> for ItemAndAliasCollector<'cache> { +impl DocVisitor<'_> for ItemAndAliasCollector<'_> { fn visit_item(&mut self, i: &Item) { self.items.insert(i.item_id); @@ -276,7 +276,7 @@ struct BadImplStripper<'a> { cache: &'a Cache, } -impl<'a> BadImplStripper<'a> { +impl BadImplStripper<'_> { fn keep_impl(&self, ty: &Type, is_deref: bool) -> bool { if let Generic(_) = ty { // keep impls made on generics diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index 35b62370abb2..1ecb53e61ac3 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -25,7 +25,7 @@ pub(crate) fn run_lints(krate: Crate, cx: &mut DocContext<'_>) -> Crate { krate } -impl<'a, 'tcx> DocVisitor<'_> for Linter<'a, 'tcx> { +impl DocVisitor<'_> for Linter<'_, '_> { fn visit_item(&mut self, item: &Item) { let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id) else { // If non-local, no need to check anything. @@ -34,7 +34,7 @@ impl<'a, 'tcx> DocVisitor<'_> for Linter<'a, 'tcx> { let dox = item.doc_value(); if !dox.is_empty() { let may_have_link = dox.contains(&[':', '['][..]); - let may_have_block_comment_or_html = dox.contains(&['<', '>']); + let may_have_block_comment_or_html = dox.contains(['<', '>']); // ~~~rust // // This is a real, supported commonmark syntax for block code // ~~~ diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 1397eadb2884..77d7cf5772d6 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -18,7 +18,7 @@ use crate::html::markdown::main_body_opts; pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range| { - let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) + let sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings) .unwrap_or_else(|| item.attr_span(cx.tcx)); cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { lint.primary_message(msg) @@ -34,14 +34,14 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & }); }; - let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); + let mut p = Parser::new_ext(dox, main_body_opts()).into_offset_iter(); while let Some((event, range)) = p.next() { match event { Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), // We don't want to check the text inside code blocks or links. Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { - while let Some((event, _)) = p.next() { + for (event, _) in p.by_ref() { match event { Event::End(end) if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index e0dc5b4c5133..20d65d8cd9f0 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -150,7 +150,7 @@ impl Translate for BufferEmitter { } fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { - &**self.fallback_bundle + &self.fallback_bundle } } diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 223174838ade..3fb154dc5154 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -15,7 +15,7 @@ use crate::html::markdown::main_body_opts; pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; let report_diag = |msg: String, range: &Range, is_open_tag: bool| { - let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) { + let sp = match source_span_for_markdown_range(tcx, dox, range, &item.attrs.doc_strings) { Some(sp) => sp, None => item.attr_span(tcx), }; @@ -30,7 +30,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & let mut generics_end = range.end; if let Some(Some(mut generics_start)) = (is_open_tag && dox[..generics_end].ends_with('>')) - .then(|| extract_path_backwards(&dox, range.start)) + .then(|| extract_path_backwards(dox, range.start)) { while generics_start != 0 && generics_end < dox.len() @@ -39,19 +39,19 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & { generics_end += 1; generics_start -= 1; - if let Some(new_start) = extract_path_backwards(&dox, generics_start) { + if let Some(new_start) = extract_path_backwards(dox, generics_start) { generics_start = new_start; } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { + if let Some(new_end) = extract_path_forward(dox, generics_end) { generics_end = new_end; } } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { + if let Some(new_end) = extract_path_forward(dox, generics_end) { generics_end = new_end; } let generics_sp = match source_span_for_markdown_range( tcx, - &dox, + dox, &(generics_start..generics_end), &item.attrs.doc_strings, ) { @@ -125,7 +125,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } }; - let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + let p = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer)) .into_offset_iter(); for (event, range) in p { @@ -233,7 +233,7 @@ fn extract_path_forward(text: &str, start_pos: usize) -> Option { break; } } - while let Some(c) = chars.next() { + for c in chars { if is_id_continue(c) { current_pos += c.len_utf8(); } else { diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index f3599688454b..6bc4374c06b1 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -35,12 +35,12 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { } } -fn check_redundant_explicit_link_for_did<'md>( +fn check_redundant_explicit_link_for_did( cx: &DocContext<'_>, item: &Item, did: DefId, hir_id: HirId, - doc: &'md str, + doc: &str, ) { let Some(local_item_id) = did.as_local() else { return; @@ -71,7 +71,7 @@ fn check_redundant_explicit_link_for_did<'md>( return; }; - check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions); + check_redundant_explicit_link(cx, item, hir_id, doc, resolutions); } fn check_redundant_explicit_link<'md>( @@ -90,60 +90,52 @@ fn check_redundant_explicit_link<'md>( .into_offset_iter(); while let Some((event, link_range)) = offset_iter.next() { - match event { - Event::Start(Tag::Link { link_type, dest_url, .. }) => { - let link_data = collect_link_data(&mut offset_iter); + if let Event::Start(Tag::Link { link_type, dest_url, .. }) = event { + let link_data = collect_link_data(&mut offset_iter); - if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { - if &link_data.display_link.replace('`', "") != resolvable_link { - // Skips if display link does not match to actual - // resolvable link, usually happens if display link - // has several segments, e.g. - // [this is just an `Option`](Option) - continue; - } - } - - let explicit_link = dest_url.to_string(); - let display_link = link_data.resolvable_link.clone()?; - - if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) - { - match link_type { - LinkType::Inline | LinkType::ReferenceUnknown => { - check_inline_or_reference_unknown_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - dest_url.to_string(), - link_data, - if link_type == LinkType::Inline { - (b'(', b')') - } else { - (b'[', b']') - }, - ); - } - LinkType::Reference => { - check_reference_redundancy( - cx, - item, - hir_id, - doc, - resolutions, - link_range, - &dest_url, - link_data, - ); - } - _ => {} - } + if let Some(resolvable_link) = link_data.resolvable_link.as_ref() { + if &link_data.display_link.replace('`', "") != resolvable_link { + // Skips if display link does not match to actual + // resolvable link, usually happens if display link + // has several segments, e.g. + // [this is just an `Option`](Option) + continue; + } + } + + let explicit_link = dest_url.to_string(); + let display_link = link_data.resolvable_link.clone()?; + + if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link) { + match link_type { + LinkType::Inline | LinkType::ReferenceUnknown => { + check_inline_or_reference_unknown_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + dest_url.to_string(), + link_data, + if link_type == LinkType::Inline { (b'(', b')') } else { (b'[', b']') }, + ); + } + LinkType::Reference => { + check_reference_redundancy( + cx, + item, + hir_id, + doc, + resolutions, + link_range, + &dest_url, + link_data, + ); + } + _ => {} } } - _ => {} } } @@ -169,18 +161,18 @@ fn check_inline_or_reference_unknown_redundancy( if dest_res == display_res { let link_span = - source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs.doc_strings) + source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) .unwrap_or(item.attr_span(cx.tcx)); let explicit_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_explicit_range(doc, link_range, open, close), &item.attrs.doc_strings, )?; let display_span = source_span_for_markdown_range( cx.tcx, - &doc, - &resolvable_link_range, + doc, + resolvable_link_range, &item.attrs.doc_strings, )?; @@ -210,27 +202,27 @@ fn check_reference_redundancy( let (resolvable_link, resolvable_link_range) = (&link_data.resolvable_link?, &link_data.resolvable_link_range?); let (dest_res, display_res) = - (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?); + (find_resolution(resolutions, dest)?, find_resolution(resolutions, resolvable_link)?); if dest_res == display_res { let link_span = - source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs.doc_strings) + source_span_for_markdown_range(cx.tcx, doc, &link_range, &item.attrs.doc_strings) .unwrap_or(item.attr_span(cx.tcx)); let explicit_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_explicit_range(doc, link_range.clone(), b'[', b']'), &item.attrs.doc_strings, )?; let display_span = source_span_for_markdown_range( cx.tcx, - &doc, - &resolvable_link_range, + doc, + resolvable_link_range, &item.attrs.doc_strings, )?; let def_span = source_span_for_markdown_range( cx.tcx, - &doc, + doc, &offset_reference_def_range(doc, dest, link_range), &item.attrs.doc_strings, )?; @@ -263,7 +255,7 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>( let mut display_link = String::new(); let mut is_resolvable = true; - while let Some((event, range)) = offset_iter.next() { + for (event, range) in offset_iter.by_ref() { match event { Event::Text(code) => { let code = code.to_string(); diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index d79f682a580f..88f4c3ac1cd7 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -22,7 +22,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & .find(|link| *link.original_text == *broken_link.reference) .map(|link| ((*link.href).into(), (*link.new_text).into())) }; - let parser = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + let parser = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer)) .into_offset_iter(); let mut element_stack = Vec::new(); @@ -44,7 +44,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // use the span of the entire attribute as a fallback. let span = source_span_for_markdown_range( tcx, - &dox, + dox, &(backtick_index..backtick_index + 1), &item.attrs.doc_strings, ) @@ -61,12 +61,12 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // "foo` `bar`" -> "`foo` `bar`" if let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -80,11 +80,11 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // Don't `clamp_end` here, because the suggestion is guaranteed to be inside // an inline code node and we intentionally "break" the inline code here. let suggest_index = guess; - if can_suggest_backtick(&dox, suggest_index) { + if can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -98,15 +98,15 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & if !element.prev_code_guess.is_confident() { // "`foo` bar`" -> "`foo` `bar`" if let Some(guess) = - guess_start_of_code(&dox, element.element_range.start..backtick_index) + guess_start_of_code(dox, element.element_range.start..backtick_index) && let Some(suggest_index) = clamp_start(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -120,16 +120,16 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & // if we already suggested opening backtick. For example: // "foo`." -> "`foo`." or "foo`s" -> "`foo`s". if let Some(guess) = - guess_end_of_code(&dox, backtick_index + 1..element.element_range.end) + guess_end_of_code(dox, backtick_index + 1..element.element_range.end) && let Some(suggest_index) = clamp_end(guess, &element.suggestible_ranges) - && can_suggest_backtick(&dox, suggest_index) + && can_suggest_backtick(dox, suggest_index) && (!help_emitted || suggest_index - backtick_index > 2) { suggest_insertion( cx, item, - &dox, + dox, lint, suggest_index, '`', @@ -148,7 +148,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & suggest_insertion( cx, item, - &dox, + dox, lint, backtick_index, '\\', @@ -177,13 +177,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & let is_confident = text_inside.starts_with(char::is_whitespace) || text_inside.ends_with(char::is_whitespace); - if let Some(guess) = guess_end_of_code(&dox, range_inside) { + if let Some(guess) = guess_end_of_code(dox, range_inside) { // Find earlier end of code. element.prev_code_guess = PrevCodeGuess::End { guess, is_confident }; } else { // Find alternate start of code. let range_before = element.element_range.start..event_range.start; - if let Some(guess) = guess_start_of_code(&dox, range_before) { + if let Some(guess) = guess_start_of_code(dox, range_before) { element.prev_code_guess = PrevCodeGuess::Start { guess, is_confident }; } } @@ -421,7 +421,7 @@ fn suggest_insertion( if let Some(span) = source_span_for_markdown_range( cx.tcx, - &dox, + dox, &(insert_index..insert_index), &item.attrs.doc_strings, ) { diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs index f8368a866c88..a3c3134f4c2c 100644 --- a/src/librustdoc/passes/lint/unportable_markdown.rs +++ b/src/librustdoc/passes/lint/unportable_markdown.rs @@ -49,8 +49,8 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & | cmarkn::Options::ENABLE_TASKLISTS | cmarkn::Options::ENABLE_SMART_PUNCTUATION } - let mut parser_new = cmarkn::Parser::new_ext(&dox, main_body_opts_new()).into_offset_iter(); - while let Some((event, span)) = parser_new.next() { + let parser_new = cmarkn::Parser::new_ext(dox, main_body_opts_new()).into_offset_iter(); + for (event, span) in parser_new { if let cmarkn::Event::Start(cmarkn::Tag::BlockQuote(_)) = event { if !dox[span.clone()].starts_with("> ") { spaceless_block_quotes.insert(span.start); @@ -71,8 +71,8 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & | cmarko::Options::ENABLE_TASKLISTS | cmarko::Options::ENABLE_SMART_PUNCTUATION } - let mut parser_old = cmarko::Parser::new_ext(&dox, main_body_opts_old()).into_offset_iter(); - while let Some((event, span)) = parser_old.next() { + let parser_old = cmarko::Parser::new_ext(dox, main_body_opts_old()).into_offset_iter(); + for (event, span) in parser_old { if let cmarko::Event::Start(cmarko::Tag::BlockQuote) = event { if !dox[span.clone()].starts_with("> ") { spaceless_block_quotes.remove(&span.start); @@ -88,13 +88,13 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & for start in spaceless_block_quotes { let (span, precise) = - source_span_for_markdown_range(tcx, &dox, &(start..start + 1), &item.attrs.doc_strings) + source_span_for_markdown_range(tcx, dox, &(start..start + 1), &item.attrs.doc_strings) .map(|span| (span, true)) .unwrap_or_else(|| (item.attr_span(tcx), false)); tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, span, |lint| { lint.primary_message("unportable markdown"); - lint.help(format!("confusing block quote with no space after the `>` marker")); + lint.help("confusing block quote with no space after the `>` marker".to_string()); if precise { lint.span_suggestion( span.shrink_to_hi(), @@ -113,7 +113,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } for (_caret, span) in missing_footnote_references { let (ref_span, precise) = - source_span_for_markdown_range(tcx, &dox, &span, &item.attrs.doc_strings) + source_span_for_markdown_range(tcx, dox, &span, &item.attrs.doc_strings) .map(|span| (span, true)) .unwrap_or_else(|| (item.attr_span(tcx), false)); diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 350be37f553d..572c9bf7552f 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -27,7 +27,7 @@ struct CfgPropagator<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { +impl CfgPropagator<'_, '_> { // Some items need to merge their attributes with their parents' otherwise a few of them // (mostly `cfg` ones) will be missing. fn merge_with_parent_attributes(&mut self, item: &mut Item) { @@ -65,7 +65,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for CfgPropagator<'a, 'tcx> { +impl DocFolder for CfgPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option { let old_parent_cfg = self.parent_cfg.clone(); diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index a28487cc79e5..a81b130a218b 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -30,7 +30,7 @@ struct StabilityPropagator<'a, 'tcx> { cx: &'a mut DocContext<'tcx>, } -impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> { +impl DocFolder for StabilityPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option { let parent_stability = self.parent_stability; diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index a078eec048ec..fa7737bc1438 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -21,7 +21,7 @@ struct AliasedNonLocalStripper<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> { +impl DocFolder for AliasedNonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option { Some(match i.kind { clean::TypeAliasItem(..) => { @@ -39,7 +39,7 @@ struct NonLocalStripper<'tcx> { tcx: TyCtxt<'tcx>, } -impl<'tcx> DocFolder for NonLocalStripper<'tcx> { +impl DocFolder for NonLocalStripper<'_> { fn fold_item(&mut self, i: Item) -> Option { // If not local, we want to respect the original visibility of // the field and not the one given by the user for the currrent crate. @@ -50,7 +50,7 @@ impl<'tcx> DocFolder for NonLocalStripper<'tcx> { { if i.is_doc_hidden() // Default to *not* stripping items with inherited visibility. - || i.visibility(self.tcx).map_or(false, |viz| viz != Visibility::Public) + || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public) { return Some(strip_item(i)); } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 4ef5f7f20a91..a71bb62e56c7 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -57,7 +57,7 @@ struct Stripper<'a, 'tcx> { last_reexport: Option, } -impl<'a, 'tcx> Stripper<'a, 'tcx> { +impl Stripper<'_, '_> { fn set_last_reexport_then_fold_item(&mut self, i: Item) -> Item { let prev_from_reexport = self.last_reexport; if i.inline_stmt_id.is_some() { @@ -86,7 +86,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> { } } -impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { +impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { let has_doc_hidden = i.is_doc_hidden(); let is_impl_or_exported_macro = match i.kind { diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 98b3446c26d2..60909754b333 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -37,7 +37,7 @@ fn is_item_reachable( } } -impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { +impl DocFolder for Stripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { match i.kind { clean::StrippedItem(..) => { @@ -171,7 +171,7 @@ pub(crate) struct ImplStripper<'a, 'tcx> { pub(crate) document_hidden: bool, } -impl<'a> ImplStripper<'a, '_> { +impl ImplStripper<'_, '_> { #[inline] fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool { if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) { @@ -193,7 +193,7 @@ impl<'a> ImplStripper<'a, '_> { } } -impl<'a> DocFolder for ImplStripper<'a, '_> { +impl DocFolder for ImplStripper<'_, '_> { fn fold_item(&mut self, i: Item) -> Option { if let clean::ImplItem(ref imp) = i.kind { // Impl blocks can be skipped if they are: empty; not a trait impl; and have no @@ -259,7 +259,7 @@ pub(crate) struct ImportStripper<'tcx> { pub(crate) document_hidden: bool, } -impl<'tcx> ImportStripper<'tcx> { +impl ImportStripper<'_> { fn import_should_be_hidden(&self, i: &Item, imp: &clean::Import) -> bool { if self.is_json_output { // FIXME: This should be handled the same way as for HTML output. @@ -270,11 +270,11 @@ impl<'tcx> ImportStripper<'tcx> { } } -impl<'tcx> DocFolder for ImportStripper<'tcx> { +impl DocFolder for ImportStripper<'_> { fn fold_item(&mut self, i: Item) -> Option { match &i.kind { clean::ImportItem(imp) - if !self.document_hidden && self.import_should_be_hidden(&i, &imp) => + if !self.document_hidden && self.import_should_be_hidden(&i, imp) => { None } diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 2c00bb7e1329..a49fb06bde35 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -54,7 +54,7 @@ fn skip_comment(iter: &mut Peekable>) { /// Skips a line comment (`//`). fn skip_line_comment(iter: &mut Peekable>) { - while let Some(c) = iter.next() { + for c in iter.by_ref() { if c == '\n' { break; } diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index bfa285c57fa9..c2e8ffd7665b 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -55,7 +55,7 @@ pub(crate) trait DocVisitor<'a>: Sized { /// Don't override! fn visit_item_recur(&mut self, item: &'a Item) { match &item.kind { - StrippedItem(i) => self.visit_inner_recur(&*i), + StrippedItem(i) => self.visit_inner_recur(i), _ => self.visit_inner_recur(&item.kind), } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 31c33fbf4973..11f06f7d917c 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -312,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => { return false; } - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { let i = tcx.hir().item(i); @@ -476,7 +476,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Macro(ref macro_def, _) => { + hir::ItemKind::Macro(macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, // above, since they need to be documented at the module top level. Accordingly, // we only want to handle macros if one of three conditions holds: @@ -496,7 +496,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Mod(ref m) => { + hir::ItemKind::Mod(m) => { self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id); } hir::ItemKind::Fn(..) @@ -560,7 +560,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // We need to implement this visitor so it'll go everywhere and retrieve items we're interested in // such as impl blocks in const blocks. -impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { From cddc8318f5ef4d9b99c18db491216637e161968c Mon Sep 17 00:00:00 2001 From: rami3l Date: Wed, 27 Nov 2024 21:56:05 +0800 Subject: [PATCH 142/330] Bump unsupported `ubuntu` CI images to 24.04 LTS --- src/ci/docker/host-x86_64/arm-android/Dockerfile | 5 +++-- src/ci/docker/host-x86_64/dist-android/Dockerfile | 2 +- src/ci/docker/host-x86_64/dist-ohos/Dockerfile | 2 +- src/ci/docker/scripts/android-base-apt-get.sh | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile index 222fa8a7355c..aade95882685 100644 --- a/src/ci/docker/host-x86_64/arm-android/Dockerfile +++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive COPY scripts/android-base-apt-get.sh /scripts/ @@ -11,7 +11,8 @@ RUN . /scripts/android-ndk.sh && \ RUN dpkg --add-architecture i386 && \ apt-get update && \ apt-get install -y --no-install-recommends \ - libgl1-mesa-glx \ + libgl1 \ + libglx-mesa0 \ libpulse0 \ libstdc++6:i386 \ openjdk-8-jre-headless \ diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile index 54649e0d22b9..95fed6ee767b 100644 --- a/src/ci/docker/host-x86_64/dist-android/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:24.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh diff --git a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile index 6dff3095b46a..bbbf0b3adf2a 100644 --- a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:23.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/src/ci/docker/scripts/android-base-apt-get.sh b/src/ci/docker/scripts/android-base-apt-get.sh index 22e2e243e430..d0252e356fd9 100644 --- a/src/ci/docker/scripts/android-base-apt-get.sh +++ b/src/ci/docker/scripts/android-base-apt-get.sh @@ -10,7 +10,7 @@ apt-get install -y --no-install-recommends \ g++ \ git \ libssl-dev \ - libncurses5 \ + libncurses-dev \ make \ ninja-build \ pkg-config \ From 90ad2adfea5a7f4baebb083cd3a190fa491d0ec8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Nov 2024 15:06:37 +1100 Subject: [PATCH 143/330] Improve span handling in `parse_expr_bottom`. `parse_expr_bottom` stores `this.token.span` in `lo`, but then fails to use it in many places where it could. This commit fixes that, and likewise (to a smaller extent) in `parse_ty_common`. --- .../rustc_parse/src/parser/diagnostics.rs | 5 ++--- compiler/rustc_parse/src/parser/expr.rs | 19 ++++++++----------- compiler/rustc_parse/src/parser/ty.rs | 11 ++++------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a1fe55089707..34131e3af6e2 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1990,7 +1990,6 @@ impl<'a> Parser<'a> { /// `await? `, `await()`, and `await { }`. pub(super) fn recover_incorrect_await_syntax( &mut self, - lo: Span, await_sp: Span, ) -> PResult<'a, P> { let (hi, expr, is_question) = if self.token == token::Not { @@ -1999,8 +1998,8 @@ impl<'a> Parser<'a> { } else { self.recover_await_prefix(await_sp)? }; - let (sp, guar) = self.error_on_incorrect_await(lo, hi, &expr, is_question); - let expr = self.mk_expr_err(lo.to(sp), guar); + let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, &expr, is_question); + let expr = self.mk_expr_err(await_sp.to(sp), guar); self.maybe_recover_from_bad_qpath(expr) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index aa5e9586daf9..4430d2d14313 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1446,34 +1446,31 @@ impl<'a> Parser<'a> { this.parse_expr_closure() } else { assert!(this.eat_keyword(kw::For)); - this.parse_expr_for(None, this.prev_token.span) + this.parse_expr_for(None, lo) } } else if this.eat_keyword(kw::While) { - this.parse_expr_while(None, this.prev_token.span) + this.parse_expr_while(None, lo) } else if let Some(label) = this.eat_label() { this.parse_expr_labeled(label, true) } else if this.eat_keyword(kw::Loop) { - let sp = this.prev_token.span; - this.parse_expr_loop(None, this.prev_token.span).map_err(|mut err| { - err.span_label(sp, "while parsing this `loop` expression"); + this.parse_expr_loop(None, lo).map_err(|mut err| { + err.span_label(lo, "while parsing this `loop` expression"); err }) } else if this.eat_keyword(kw::Match) { - let match_sp = this.prev_token.span; this.parse_expr_match().map_err(|mut err| { - err.span_label(match_sp, "while parsing this `match` expression"); + err.span_label(lo, "while parsing this `match` expression"); err }) } else if this.eat_keyword(kw::Unsafe) { - let sp = this.prev_token.span; this.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err( |mut err| { - err.span_label(sp, "while parsing this `unsafe` expression"); + err.span_label(lo, "while parsing this `unsafe` expression"); err }, ) } else if this.check_inline_const(0) { - this.parse_const_block(lo.to(this.token.span), false) + this.parse_const_block(lo, false) } else if this.may_recover() && this.is_do_catch_block() { this.recover_do_catch() } else if this.is_try_block() { @@ -1514,7 +1511,7 @@ impl<'a> Parser<'a> { this.parse_expr_closure() } } else if this.eat_keyword_noexpect(kw::Await) { - this.recover_incorrect_await_syntax(lo, this.prev_token.span) + this.recover_incorrect_await_syntax(lo) } else { this.parse_expr_lit() } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index c561ea3823d0..505586e74f11 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -274,7 +274,6 @@ impl<'a> Parser<'a> { // Function pointer type self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)? } else if self.check_keyword(kw::For) { - let for_span = self.token.span; // Function pointer type or bound list (trait object type) starting with a poly-trait. // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` @@ -302,7 +301,7 @@ impl<'a> Parser<'a> { kw: kw.name.as_str(), sugg: errors::TransposeDynOrImplSugg { removal_span, - insertion_span: for_span.shrink_to_lo(), + insertion_span: lo.shrink_to_lo(), kw: kw.name.as_str(), }, }); @@ -345,16 +344,14 @@ impl<'a> Parser<'a> { // FIXME(c_variadic): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? // NOTE: This may regress certain MBE calls if done incorrectly. - let guar = self - .dcx() - .emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) }); + let guar = self.dcx().emit_err(NestedCVariadicType { span: lo }); TyKind::Err(guar) } } } else { let msg = format!("expected type, found {}", super::token_descr(&self.token)); - let mut err = self.dcx().struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected type"); + let mut err = self.dcx().struct_span_err(lo, msg); + err.span_label(lo, "expected type"); return Err(err); }; From 6e3cb4abfbbdb6fb7e34eed99840d1fe22c6b682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 28 Nov 2024 08:37:22 +0200 Subject: [PATCH 144/330] Preparing for merge from rust-lang/rust --- src/tools/rust-analyzer/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 00f4f743a7c4..8f41ed9e14f9 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -145f9cf95de1fbde3fa11e98461310e0373253e6 +f005c7437def424a1c43cbc380352a58d8ac920b From 1a435ed7edc19812c29006701b0106a0d0802542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 28 Nov 2024 08:39:56 +0200 Subject: [PATCH 145/330] Bump rustc crates --- src/tools/rust-analyzer/Cargo.lock | 24 ++++++++++++------------ src/tools/rust-analyzer/Cargo.toml | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 019609e6a5be..2bd4d17fe222 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1492,9 +1492,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fde78db053c78c87776ec738677649f791645883f82ff145f68caf9f18e1a" +checksum = "613760a3071b25a67a8d7bc97b37c7fd4722562e9479137b83ae9cf8f8c1601a" dependencies = [ "bitflags 2.6.0", "ra-ap-rustc_index", @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da115d496e5abd65e2dceb6883d7597593badfe23fea3439202b8da5a11ea250" +checksum = "5b2bc6b4ecede8ff28295041e22c2e66853f8e0125990c05135bad3c30bad12c" dependencies = [ "arrayvec", "ra-ap-rustc_index_macros", @@ -1514,9 +1514,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be86d06a75a8125c1ace197d5030e6e02721348d32e572baea35c891669ad1e2" +checksum = "2374a39fb2d92d0509178c2b442eadca3cc10e403ef9729a040c1855b08ff261" dependencies = [ "proc-macro2", "quote", @@ -1525,9 +1525,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64b46ae0d8f59acc32e64e0085532b831f0d6182d870a7cd86c046c2c46e722" +checksum = "5a2cf8e48b69af3ecc29ed3449892e8a999111d2f75212a78aa242e117cf1711" dependencies = [ "unicode-properties", "unicode-xid", @@ -1535,9 +1535,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbdaad19ddbd0ff46e947ca8dbb6ae678a112d3938669fb3ad6bfd244917e24b" +checksum = "8d6f59a22b559263c5c42747ae362cf5d4fb272293fa119a4623f8ec288f9656" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1545,9 +1545,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.76.0" +version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5761e37c78d98ede9f20f6b66526093d0be66aa256d5cbdf214495843ba74d" +checksum = "a7d0575b54ffe09bc5d2f158454bc05f0c30c01d9992310965f854be50ae22b8" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.0.0", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 94e7de553bf4..632b290ba984 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" } vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.76", default-features = false } -ra-ap-rustc_parse_format = { version = "0.76", default-features = false } -ra-ap-rustc_index = { version = "0.76", default-features = false } -ra-ap-rustc_abi = { version = "0.76", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.76", default-features = false } +ra-ap-rustc_lexer = { version = "0.80", default-features = false } +ra-ap-rustc_parse_format = { version = "0.80", default-features = false } +ra-ap-rustc_index = { version = "0.80", default-features = false } +ra-ap-rustc_abi = { version = "0.80", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.80", default-features = false } # local crates that aren't published to crates.io. These should not have versions. test-fixture = { path = "./crates/test-fixture" } From 77080d8eb359be41c696033d45e52f544ab9bd57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Nov 2024 07:58:46 +0100 Subject: [PATCH 146/330] move target JSON (de)serialization to separate file --- compiler/rustc_target/src/spec/json.rs | 798 +++++++++++++++++++++++++ compiler/rustc_target/src/spec/mod.rs | 791 +----------------------- 2 files changed, 800 insertions(+), 789 deletions(-) create mode 100644 compiler/rustc_target/src/spec/json.rs diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs new file mode 100644 index 000000000000..206766325aa1 --- /dev/null +++ b/compiler/rustc_target/src/spec/json.rs @@ -0,0 +1,798 @@ +use std::borrow::Cow; +use std::collections::BTreeMap; +use std::str::FromStr; + +use serde_json::Value; + +use super::{Target, TargetKind, TargetOptions, TargetWarnings}; +use crate::json::{Json, ToJson}; + +impl Target { + /// Loads a target descriptor from a JSON object. + pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> { + // While ugly, this code must remain this way to retain + // compatibility with existing JSON fields and the internal + // expected naming of the Target and TargetOptions structs. + // To ensure compatibility is retained, the built-in targets + // are round-tripped through this code to catch cases where + // the JSON parser is not updated to match the structs. + + let mut obj = match obj { + Value::Object(obj) => obj, + _ => return Err("Expected JSON object for target")?, + }; + + let mut get_req_field = |name: &str| { + obj.remove(name) + .and_then(|j| j.as_str().map(str::to_string)) + .ok_or_else(|| format!("Field {name} in target specification is required")) + }; + + let mut base = Target { + llvm_target: get_req_field("llvm-target")?.into(), + metadata: Default::default(), + pointer_width: get_req_field("target-pointer-width")? + .parse::() + .map_err(|_| "target-pointer-width must be an integer".to_string())?, + data_layout: get_req_field("data-layout")?.into(), + arch: get_req_field("arch")?.into(), + options: Default::default(), + }; + + // FIXME: This doesn't properly validate anything and just ignores the data if it's invalid. + // That's okay for now, the only use of this is when generating docs, which we don't do for + // custom targets. + if let Some(Json::Object(mut metadata)) = obj.remove("metadata") { + base.metadata.description = metadata + .remove("description") + .and_then(|desc| desc.as_str().map(|desc| desc.to_owned().into())); + base.metadata.tier = metadata + .remove("tier") + .and_then(|tier| tier.as_u64()) + .filter(|tier| (1..=3).contains(tier)); + base.metadata.host_tools = + metadata.remove("host_tools").and_then(|host| host.as_bool()); + base.metadata.std = metadata.remove("std").and_then(|host| host.as_bool()); + } + + let mut incorrect_type = vec![]; + + macro_rules! key { + ($key_name:ident) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { + base.$key_name = s; + } + } ); + ($key_name:ident = $json_name:expr) => ( { + let name = $json_name; + if let Some(s) = obj.remove(name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { + base.$key_name = s; + } + } ); + ($key_name:ident, bool) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = s; + } + } ); + ($key_name:ident = $json_name:expr, bool) => ( { + let name = $json_name; + if let Some(s) = obj.remove(name).and_then(|b| b.as_bool()) { + base.$key_name = s; + } + } ); + ($key_name:ident, u32) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { + if s < 1 || s > 5 { + return Err("Not a valid DWARF version number".into()); + } + base.$key_name = s as u32; + } + } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = Some(s); + } + } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { + base.$key_name = Some(s); + } + } ); + ($key_name:ident, MergeFunctions) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(mergefunc) => base.$key_name = mergefunc, + _ => return Some(Err(format!("'{}' is not a valid value for \ + merge-functions. Use 'disabled', \ + 'trampolines', or 'aliases'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, RelocModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(relocation_model) => base.$key_name = relocation_model, + _ => return Some(Err(format!("'{}' is not a valid relocation model. \ + Run `rustc --print relocation-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, CodeModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(code_model) => base.$key_name = Some(code_model), + _ => return Some(Err(format!("'{}' is not a valid code model. \ + Run `rustc --print code-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, TlsModel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(tls_model) => base.$key_name = tls_model, + _ => return Some(Err(format!("'{}' is not a valid TLS model. \ + Run `rustc --print tls-models` to \ + see the list of supported values.", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, SmallDataThresholdSupport) => ( { + obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(support) => base.small_data_threshold_support = support, + _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, PanicStrategy) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s { + "unwind" => base.$key_name = super::PanicStrategy::Unwind, + "abort" => base.$key_name = super::PanicStrategy::Abort, + _ => return Some(Err(format!("'{}' is not a valid value for \ + panic-strategy. Use 'unwind' or 'abort'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, RelroLevel) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(level) => base.$key_name = level, + _ => return Some(Err(format!("'{}' is not a valid value for \ + relro-level. Use 'full', 'partial, or 'off'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(level) => base.$key_name = Some(level), + _ => return Some(Err(format!("'{}' is not a valid value for \ + symbol-visibility. Use 'hidden', 'protected, or 'interposable'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, DebuginfoKind) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(level) => base.$key_name = level, + _ => return Some(Err( + format!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \ + 'dwarf-dsym' or 'pdb'.") + )), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, SplitDebuginfo) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(level) => base.$key_name = level, + _ => return Some(Err(format!("'{}' is not a valid value for \ + split-debuginfo. Use 'off' or 'dsymutil'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(j) = obj.remove(&name) { + if let Some(v) = j.as_array() { + base.$key_name = v.iter() + .map(|a| a.as_str().unwrap().to_string().into()) + .collect(); + } else { + incorrect_type.push(name) + } + } + } ); + ($key_name:ident, opt_list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(j) = obj.remove(&name) { + if let Some(v) = j.as_array() { + base.$key_name = Some(v.iter() + .map(|a| a.as_str().unwrap().to_string().into()) + .collect()); + } else { + incorrect_type.push(name) + } + } + } ); + ($key_name:ident, fallible_list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|j| { + if let Some(v) = j.as_array() { + match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() { + Ok(l) => { base.$key_name = l }, + // FIXME: `fallible_list` can't re-use the `key!` macro for list + // elements and the error messages from that macro, so it has a bad + // generic message instead + Err(_) => return Some(Err( + format!("`{:?}` is not a valid value for `{}`", j, name) + )), + } + } else { + incorrect_type.push(name) + } + Some(Ok(())) + }).unwrap_or(Ok(())) + } ); + ($key_name:ident, optional) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + base.$key_name = o + .as_str() + .map(|s| s.to_string().into()); + } + } ); + ($key_name:ident = $json_name:expr, LldFlavor) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + if let Some(flavor) = super::LldFlavor::from_str(&s) { + base.$key_name = flavor; + } else { + return Some(Err(format!( + "'{}' is not a valid value for lld-flavor. \ + Use 'darwin', 'gnu', 'link' or 'wasm'.", + s))) + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident = $json_name:expr, LinkerFlavorCli) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + match super::LinkerFlavorCli::from_str(s) { + Some(linker_flavor) => base.$key_name = linker_flavor, + _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ + Use {}", s, super::LinkerFlavorCli::one_of()))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, StackProbeType) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| match super::StackProbeType::from_json(&o) { + Ok(v) => { + base.$key_name = v; + Some(Ok(())) + }, + Err(s) => Some(Err( + format!("`{:?}` is not a valid value for `{}`: {}", o, name, s) + )), + }).unwrap_or(Ok(())) + } ); + ($key_name:ident, SanitizerSet) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(a) = o.as_array() { + for s in a { + use super::SanitizerSet; + base.$key_name |= match s.as_str() { + Some("address") => SanitizerSet::ADDRESS, + Some("cfi") => SanitizerSet::CFI, + Some("dataflow") => SanitizerSet::DATAFLOW, + Some("kcfi") => SanitizerSet::KCFI, + Some("kernel-address") => SanitizerSet::KERNELADDRESS, + Some("leak") => SanitizerSet::LEAK, + Some("memory") => SanitizerSet::MEMORY, + Some("memtag") => SanitizerSet::MEMTAG, + Some("safestack") => SanitizerSet::SAFESTACK, + Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK, + Some("thread") => SanitizerSet::THREAD, + Some("hwaddress") => SanitizerSet::HWADDRESS, + Some(s) => return Err(format!("unknown sanitizer {}", s)), + _ => return Err(format!("not a string: {:?}", s)), + }; + } + } else { + incorrect_type.push(name) + } + } + Ok::<(), String>(()) + } ); + ($key_name:ident, link_self_contained_components) => ( { + // Skeleton of what needs to be parsed: + // + // ``` + // $name: { + // "components": [ + // + // ] + // } + // ``` + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(o) = o.as_object() { + let component_array = o.get("components") + .ok_or_else(|| format!("{name}: expected a \ + JSON object with a `components` field."))?; + let component_array = component_array.as_array() + .ok_or_else(|| format!("{name}.components: expected a JSON array"))?; + let mut components = super::LinkSelfContainedComponents::empty(); + for s in component_array { + components |= match s.as_str() { + Some(s) => { + super::LinkSelfContainedComponents::from_str(s) + .ok_or_else(|| format!("unknown \ + `-Clink-self-contained` component: {s}"))? + }, + _ => return Err(format!("not a string: {:?}", s)), + }; + } + base.$key_name = super::LinkSelfContainedDefault::WithComponents(components); + } else { + incorrect_type.push(name) + } + } + Ok::<(), String>(()) + } ); + ($key_name:ident = $json_name:expr, link_self_contained_backwards_compatible) => ( { + let name = $json_name; + obj.remove(name).and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(lsc_default) => base.$key_name = lsc_default, + _ => return Some(Err(format!("'{}' is not a valid `-Clink-self-contained` default. \ + Use 'false', 'true', 'musl' or 'mingw'", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident = $json_name:expr, link_objects) => ( { + let name = $json_name; + if let Some(val) = obj.remove(name) { + let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ + JSON object with fields per CRT object kind.", name))?; + let mut args = super::CrtObjects::new(); + for (k, v) in obj { + let kind = super::LinkOutputKind::from_str(&k).ok_or_else(|| { + format!("{}: '{}' is not a valid value for CRT object kind. \ + Use '(dynamic,static)-(nopic,pic)-exe' or \ + '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k) + })?; + + let v = v.as_array().ok_or_else(|| + format!("{}.{}: expected a JSON array", name, k) + )?.iter().enumerate() + .map(|(i,s)| { + let s = s.as_str().ok_or_else(|| + format!("{}.{}[{}]: expected a JSON string", name, k, i))?; + Ok(s.to_string().into()) + }) + .collect::, String>>()?; + + args.insert(kind, v); + } + base.$key_name = args; + } + } ); + ($key_name:ident = $json_name:expr, link_args) => ( { + let name = $json_name; + if let Some(val) = obj.remove(name) { + let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ + JSON object with fields per linker-flavor.", name))?; + let mut args = super::LinkArgsCli::new(); + for (k, v) in obj { + let flavor = super::LinkerFlavorCli::from_str(&k).ok_or_else(|| { + format!("{}: '{}' is not a valid value for linker-flavor. \ + Use 'em', 'gcc', 'ld' or 'msvc'", name, k) + })?; + + let v = v.as_array().ok_or_else(|| + format!("{}.{}: expected a JSON array", name, k) + )?.iter().enumerate() + .map(|(i,s)| { + let s = s.as_str().ok_or_else(|| + format!("{}.{}[{}]: expected a JSON string", name, k, i))?; + Ok(s.to_string().into()) + }) + .collect::, String>>()?; + + args.insert(flavor, v); + } + base.$key_name = args; + } + } ); + ($key_name:ident, env) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(o) = obj.remove(&name) { + if let Some(a) = o.as_array() { + for o in a { + if let Some(s) = o.as_str() { + if let [k, v] = *s.split('=').collect::>() { + base.$key_name + .to_mut() + .push((k.to_string().into(), v.to_string().into())) + } + } + } + } else { + incorrect_type.push(name) + } + } + } ); + ($key_name:ident, target_families) => ( { + if let Some(value) = obj.remove("target-family") { + if let Some(v) = value.as_array() { + base.$key_name = v.iter() + .map(|a| a.as_str().unwrap().to_string().into()) + .collect(); + } else if let Some(v) = value.as_str() { + base.$key_name = vec![v.to_string().into()].into(); + } + } + } ); + ($key_name:ident, Conv) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { + match super::Conv::from_str(s) { + Ok(c) => { + base.$key_name = c; + Some(Ok(())) + } + Err(e) => Some(Err(e)) + } + })).unwrap_or(Ok(())) + } ); + } + + if let Some(j) = obj.remove("target-endian") { + if let Some(s) = j.as_str() { + base.endian = s.parse()?; + } else { + incorrect_type.push("target-endian".into()) + } + } + + if let Some(fp) = obj.remove("frame-pointer") { + if let Some(s) = fp.as_str() { + base.frame_pointer = s + .parse() + .map_err(|()| format!("'{s}' is not a valid value for frame-pointer"))?; + } else { + incorrect_type.push("frame-pointer".into()) + } + } + + key!(c_int_width = "target-c-int-width"); + key!(c_enum_min_bits, Option); // if None, matches c_int_width + key!(os); + key!(env); + key!(abi); + key!(vendor); + key!(linker, optional); + key!(linker_flavor_json = "linker-flavor", LinkerFlavorCli)?; + key!(lld_flavor_json = "lld-flavor", LldFlavor)?; + key!(linker_is_gnu_json = "linker-is-gnu", bool); + key!(pre_link_objects = "pre-link-objects", link_objects); + key!(post_link_objects = "post-link-objects", link_objects); + key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); + key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects); + // Deserializes the backwards-compatible variants of `-Clink-self-contained` + key!( + link_self_contained = "crt-objects-fallback", + link_self_contained_backwards_compatible + )?; + // Deserializes the components variant of `-Clink-self-contained` + key!(link_self_contained, link_self_contained_components)?; + key!(pre_link_args_json = "pre-link-args", link_args); + key!(late_link_args_json = "late-link-args", link_args); + key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args); + key!(late_link_args_static_json = "late-link-args-static", link_args); + key!(post_link_args_json = "post-link-args", link_args); + key!(link_script, optional); + key!(link_env, env); + key!(link_env_remove, list); + key!(asm_args, list); + key!(cpu); + key!(features); + key!(dynamic_linking, bool); + key!(direct_access_external_data, Option); + key!(dll_tls_export, bool); + key!(only_cdylib, bool); + key!(executables, bool); + key!(relocation_model, RelocModel)?; + key!(code_model, CodeModel)?; + key!(tls_model, TlsModel)?; + key!(disable_redzone, bool); + key!(function_sections, bool); + key!(dll_prefix); + key!(dll_suffix); + key!(exe_suffix); + key!(staticlib_prefix); + key!(staticlib_suffix); + key!(families, target_families); + key!(abi_return_struct_as_int, bool); + key!(is_like_aix, bool); + key!(is_like_osx, bool); + key!(is_like_solaris, bool); + key!(is_like_windows, bool); + key!(is_like_msvc, bool); + key!(is_like_wasm, bool); + key!(is_like_android, bool); + key!(default_dwarf_version, u32); + key!(allows_weak_linkage, bool); + key!(has_rpath, bool); + key!(no_default_libraries, bool); + key!(position_independent_executables, bool); + key!(static_position_independent_executables, bool); + key!(plt_by_default, bool); + key!(relro_level, RelroLevel)?; + key!(archive_format); + key!(allow_asm, bool); + key!(main_needs_argc_argv, bool); + key!(has_thread_local, bool); + key!(obj_is_bitcode, bool); + key!(bitcode_llvm_cmdline); + key!(max_atomic_width, Option); + key!(min_atomic_width, Option); + key!(atomic_cas, bool); + key!(panic_strategy, PanicStrategy)?; + key!(crt_static_allows_dylibs, bool); + key!(crt_static_default, bool); + key!(crt_static_respected, bool); + key!(stack_probes, StackProbeType)?; + key!(min_global_align, Option); + key!(default_codegen_units, Option); + key!(trap_unreachable, bool); + key!(requires_lto, bool); + key!(singlethread, bool); + key!(no_builtins, bool); + key!(default_visibility, Option)?; + key!(emit_debug_gdb_scripts, bool); + key!(requires_uwtable, bool); + key!(default_uwtable, bool); + key!(simd_types_indirect, bool); + key!(limit_rdylib_exports, bool); + key!(override_export_symbols, opt_list); + key!(merge_functions, MergeFunctions)?; + key!(mcount = "target-mcount"); + key!(llvm_mcount_intrinsic, optional); + key!(llvm_abiname); + key!(relax_elf_relocations, bool); + key!(llvm_args, list); + key!(use_ctors_section, bool); + key!(eh_frame_header, bool); + key!(has_thumb_interworking, bool); + key!(debuginfo_kind, DebuginfoKind)?; + key!(split_debuginfo, SplitDebuginfo)?; + key!(supported_split_debuginfo, fallible_list)?; + key!(supported_sanitizers, SanitizerSet)?; + key!(generate_arange_section, bool); + key!(supports_stack_protector, bool); + key!(small_data_threshold_support, SmallDataThresholdSupport)?; + key!(entry_name); + key!(entry_abi, Conv)?; + key!(supports_xray, bool); + + base.update_from_cli(); + base.check_consistency(TargetKind::Json)?; + + // Each field should have been read using `Json::remove` so any keys remaining are unused. + let remaining_keys = obj.keys(); + Ok((base, TargetWarnings { + unused_fields: remaining_keys.cloned().collect(), + incorrect_type, + })) + } +} + +impl ToJson for Target { + fn to_json(&self) -> Json { + let mut d = serde_json::Map::new(); + let default: TargetOptions = Default::default(); + let mut target = self.clone(); + target.update_to_cli(); + + macro_rules! target_val { + ($attr:ident) => {{ + let name = (stringify!($attr)).replace("_", "-"); + d.insert(name, target.$attr.to_json()); + }}; + } + + macro_rules! target_option_val { + ($attr:ident) => {{ + let name = (stringify!($attr)).replace("_", "-"); + if default.$attr != target.$attr { + d.insert(name, target.$attr.to_json()); + } + }}; + ($attr:ident, $json_name:expr) => {{ + let name = $json_name; + if default.$attr != target.$attr { + d.insert(name.into(), target.$attr.to_json()); + } + }}; + (link_args - $attr:ident, $json_name:expr) => {{ + let name = $json_name; + if default.$attr != target.$attr { + let obj = target + .$attr + .iter() + .map(|(k, v)| (k.desc().to_string(), v.clone())) + .collect::>(); + d.insert(name.to_string(), obj.to_json()); + } + }}; + (env - $attr:ident) => {{ + let name = (stringify!($attr)).replace("_", "-"); + if default.$attr != target.$attr { + let obj = target + .$attr + .iter() + .map(|&(ref k, ref v)| format!("{k}={v}")) + .collect::>(); + d.insert(name, obj.to_json()); + } + }}; + } + + target_val!(llvm_target); + target_val!(metadata); + d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json()); + target_val!(arch); + target_val!(data_layout); + + target_option_val!(endian, "target-endian"); + target_option_val!(c_int_width, "target-c-int-width"); + target_option_val!(os); + target_option_val!(env); + target_option_val!(abi); + target_option_val!(vendor); + target_option_val!(linker); + target_option_val!(linker_flavor_json, "linker-flavor"); + target_option_val!(lld_flavor_json, "lld-flavor"); + target_option_val!(linker_is_gnu_json, "linker-is-gnu"); + target_option_val!(pre_link_objects); + target_option_val!(post_link_objects); + target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); + target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback"); + target_option_val!(link_args - pre_link_args_json, "pre-link-args"); + target_option_val!(link_args - late_link_args_json, "late-link-args"); + target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic"); + target_option_val!(link_args - late_link_args_static_json, "late-link-args-static"); + target_option_val!(link_args - post_link_args_json, "post-link-args"); + target_option_val!(link_script); + target_option_val!(env - link_env); + target_option_val!(link_env_remove); + target_option_val!(asm_args); + target_option_val!(cpu); + target_option_val!(features); + target_option_val!(dynamic_linking); + target_option_val!(direct_access_external_data); + target_option_val!(dll_tls_export); + target_option_val!(only_cdylib); + target_option_val!(executables); + target_option_val!(relocation_model); + target_option_val!(code_model); + target_option_val!(tls_model); + target_option_val!(disable_redzone); + target_option_val!(frame_pointer); + target_option_val!(function_sections); + target_option_val!(dll_prefix); + target_option_val!(dll_suffix); + target_option_val!(exe_suffix); + target_option_val!(staticlib_prefix); + target_option_val!(staticlib_suffix); + target_option_val!(families, "target-family"); + target_option_val!(abi_return_struct_as_int); + target_option_val!(is_like_aix); + target_option_val!(is_like_osx); + target_option_val!(is_like_solaris); + target_option_val!(is_like_windows); + target_option_val!(is_like_msvc); + target_option_val!(is_like_wasm); + target_option_val!(is_like_android); + target_option_val!(default_dwarf_version); + target_option_val!(allows_weak_linkage); + target_option_val!(has_rpath); + target_option_val!(no_default_libraries); + target_option_val!(position_independent_executables); + target_option_val!(static_position_independent_executables); + target_option_val!(plt_by_default); + target_option_val!(relro_level); + target_option_val!(archive_format); + target_option_val!(allow_asm); + target_option_val!(main_needs_argc_argv); + target_option_val!(has_thread_local); + target_option_val!(obj_is_bitcode); + target_option_val!(bitcode_llvm_cmdline); + target_option_val!(min_atomic_width); + target_option_val!(max_atomic_width); + target_option_val!(atomic_cas); + target_option_val!(panic_strategy); + target_option_val!(crt_static_allows_dylibs); + target_option_val!(crt_static_default); + target_option_val!(crt_static_respected); + target_option_val!(stack_probes); + target_option_val!(min_global_align); + target_option_val!(default_codegen_units); + target_option_val!(trap_unreachable); + target_option_val!(requires_lto); + target_option_val!(singlethread); + target_option_val!(no_builtins); + target_option_val!(default_visibility); + target_option_val!(emit_debug_gdb_scripts); + target_option_val!(requires_uwtable); + target_option_val!(default_uwtable); + target_option_val!(simd_types_indirect); + target_option_val!(limit_rdylib_exports); + target_option_val!(override_export_symbols); + target_option_val!(merge_functions); + target_option_val!(mcount, "target-mcount"); + target_option_val!(llvm_mcount_intrinsic); + target_option_val!(llvm_abiname); + target_option_val!(relax_elf_relocations); + target_option_val!(llvm_args); + target_option_val!(use_ctors_section); + target_option_val!(eh_frame_header); + target_option_val!(has_thumb_interworking); + target_option_val!(debuginfo_kind); + target_option_val!(split_debuginfo); + target_option_val!(supported_split_debuginfo); + target_option_val!(supported_sanitizers); + target_option_val!(c_enum_min_bits); + target_option_val!(generate_arange_section); + target_option_val!(supports_stack_protector); + target_option_val!(small_data_threshold_support); + target_option_val!(entry_name); + target_option_val!(entry_abi); + target_option_val!(supports_xray); + + // Serializing `-Clink-self-contained` needs a dynamic key to support the + // backwards-compatible variants. + d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json()); + + Json::Object(d) + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1c7d473447ac..a2e9430830a2 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -34,8 +34,6 @@ //! the target's settings, though `target-feature` and `link-args` will *add* //! to the list specified by the target, rather than replace. -// ignore-tidy-filelength - use std::borrow::Cow; use std::collections::BTreeMap; use std::hash::{Hash, Hasher}; @@ -68,6 +66,8 @@ pub mod abi { } mod base; +mod json; + pub use base::avr_gnu::ef_avr_arch; /// Linker is called through a C/C++ compiler. @@ -3206,622 +3206,6 @@ impl Target { || (self.env == "sgx" && self.vendor == "fortanix") } - /// Loads a target descriptor from a JSON object. - pub fn from_json(obj: Json) -> Result<(Target, TargetWarnings), String> { - // While ugly, this code must remain this way to retain - // compatibility with existing JSON fields and the internal - // expected naming of the Target and TargetOptions structs. - // To ensure compatibility is retained, the built-in targets - // are round-tripped through this code to catch cases where - // the JSON parser is not updated to match the structs. - - let mut obj = match obj { - Value::Object(obj) => obj, - _ => return Err("Expected JSON object for target")?, - }; - - let mut get_req_field = |name: &str| { - obj.remove(name) - .and_then(|j| j.as_str().map(str::to_string)) - .ok_or_else(|| format!("Field {name} in target specification is required")) - }; - - let mut base = Target { - llvm_target: get_req_field("llvm-target")?.into(), - metadata: Default::default(), - pointer_width: get_req_field("target-pointer-width")? - .parse::() - .map_err(|_| "target-pointer-width must be an integer".to_string())?, - data_layout: get_req_field("data-layout")?.into(), - arch: get_req_field("arch")?.into(), - options: Default::default(), - }; - - // FIXME: This doesn't properly validate anything and just ignores the data if it's invalid. - // That's okay for now, the only use of this is when generating docs, which we don't do for - // custom targets. - if let Some(Json::Object(mut metadata)) = obj.remove("metadata") { - base.metadata.description = metadata - .remove("description") - .and_then(|desc| desc.as_str().map(|desc| desc.to_owned().into())); - base.metadata.tier = metadata - .remove("tier") - .and_then(|tier| tier.as_u64()) - .filter(|tier| (1..=3).contains(tier)); - base.metadata.host_tools = - metadata.remove("host_tools").and_then(|host| host.as_bool()); - base.metadata.std = metadata.remove("std").and_then(|host| host.as_bool()); - } - - let mut incorrect_type = vec![]; - - macro_rules! key { - ($key_name:ident) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { - base.$key_name = s; - } - } ); - ($key_name:ident = $json_name:expr) => ( { - let name = $json_name; - if let Some(s) = obj.remove(name).and_then(|s| s.as_str().map(str::to_string).map(Cow::from)) { - base.$key_name = s; - } - } ); - ($key_name:ident, bool) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { - base.$key_name = s; - } - } ); - ($key_name:ident = $json_name:expr, bool) => ( { - let name = $json_name; - if let Some(s) = obj.remove(name).and_then(|b| b.as_bool()) { - base.$key_name = s; - } - } ); - ($key_name:ident, u32) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { - if s < 1 || s > 5 { - return Err("Not a valid DWARF version number".into()); - } - base.$key_name = s as u32; - } - } ); - ($key_name:ident, Option) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { - base.$key_name = Some(s); - } - } ); - ($key_name:ident, Option) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { - base.$key_name = Some(s); - } - } ); - ($key_name:ident, MergeFunctions) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(mergefunc) => base.$key_name = mergefunc, - _ => return Some(Err(format!("'{}' is not a valid value for \ - merge-functions. Use 'disabled', \ - 'trampolines', or 'aliases'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, RelocModel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(relocation_model) => base.$key_name = relocation_model, - _ => return Some(Err(format!("'{}' is not a valid relocation model. \ - Run `rustc --print relocation-models` to \ - see the list of supported values.", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, CodeModel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(code_model) => base.$key_name = Some(code_model), - _ => return Some(Err(format!("'{}' is not a valid code model. \ - Run `rustc --print code-models` to \ - see the list of supported values.", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, TlsModel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(tls_model) => base.$key_name = tls_model, - _ => return Some(Err(format!("'{}' is not a valid TLS model. \ - Run `rustc --print tls-models` to \ - see the list of supported values.", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, SmallDataThresholdSupport) => ( { - obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(support) => base.small_data_threshold_support = support, - _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, PanicStrategy) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s { - "unwind" => base.$key_name = PanicStrategy::Unwind, - "abort" => base.$key_name = PanicStrategy::Abort, - _ => return Some(Err(format!("'{}' is not a valid value for \ - panic-strategy. Use 'unwind' or 'abort'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, RelroLevel) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(level) => base.$key_name = level, - _ => return Some(Err(format!("'{}' is not a valid value for \ - relro-level. Use 'full', 'partial, or 'off'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, Option) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(level) => base.$key_name = Some(level), - _ => return Some(Err(format!("'{}' is not a valid value for \ - symbol-visibility. Use 'hidden', 'protected, or 'interposable'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, DebuginfoKind) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(level) => base.$key_name = level, - _ => return Some(Err( - format!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \ - 'dwarf-dsym' or 'pdb'.") - )), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, SplitDebuginfo) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(level) => base.$key_name = level, - _ => return Some(Err(format!("'{}' is not a valid value for \ - split-debuginfo. Use 'off' or 'dsymutil'.", - s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, list) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(j) = obj.remove(&name) { - if let Some(v) = j.as_array() { - base.$key_name = v.iter() - .map(|a| a.as_str().unwrap().to_string().into()) - .collect(); - } else { - incorrect_type.push(name) - } - } - } ); - ($key_name:ident, opt_list) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(j) = obj.remove(&name) { - if let Some(v) = j.as_array() { - base.$key_name = Some(v.iter() - .map(|a| a.as_str().unwrap().to_string().into()) - .collect()); - } else { - incorrect_type.push(name) - } - } - } ); - ($key_name:ident, fallible_list) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|j| { - if let Some(v) = j.as_array() { - match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() { - Ok(l) => { base.$key_name = l }, - // FIXME: `fallible_list` can't re-use the `key!` macro for list - // elements and the error messages from that macro, so it has a bad - // generic message instead - Err(_) => return Some(Err( - format!("`{:?}` is not a valid value for `{}`", j, name) - )), - } - } else { - incorrect_type.push(name) - } - Some(Ok(())) - }).unwrap_or(Ok(())) - } ); - ($key_name:ident, optional) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - base.$key_name = o - .as_str() - .map(|s| s.to_string().into()); - } - } ); - ($key_name:ident = $json_name:expr, LldFlavor) => ( { - let name = $json_name; - obj.remove(name).and_then(|o| o.as_str().and_then(|s| { - if let Some(flavor) = LldFlavor::from_str(&s) { - base.$key_name = flavor; - } else { - return Some(Err(format!( - "'{}' is not a valid value for lld-flavor. \ - Use 'darwin', 'gnu', 'link' or 'wasm'.", - s))) - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident = $json_name:expr, LinkerFlavor) => ( { - let name = $json_name; - obj.remove(name).and_then(|o| o.as_str().and_then(|s| { - match LinkerFlavorCli::from_str(s) { - Some(linker_flavor) => base.$key_name = linker_flavor, - _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \ - Use {}", s, LinkerFlavorCli::one_of()))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident, StackProbeType) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| match StackProbeType::from_json(&o) { - Ok(v) => { - base.$key_name = v; - Some(Ok(())) - }, - Err(s) => Some(Err( - format!("`{:?}` is not a valid value for `{}`: {}", o, name, s) - )), - }).unwrap_or(Ok(())) - } ); - ($key_name:ident, SanitizerSet) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - if let Some(a) = o.as_array() { - for s in a { - base.$key_name |= match s.as_str() { - Some("address") => SanitizerSet::ADDRESS, - Some("cfi") => SanitizerSet::CFI, - Some("dataflow") => SanitizerSet::DATAFLOW, - Some("kcfi") => SanitizerSet::KCFI, - Some("kernel-address") => SanitizerSet::KERNELADDRESS, - Some("leak") => SanitizerSet::LEAK, - Some("memory") => SanitizerSet::MEMORY, - Some("memtag") => SanitizerSet::MEMTAG, - Some("safestack") => SanitizerSet::SAFESTACK, - Some("shadow-call-stack") => SanitizerSet::SHADOWCALLSTACK, - Some("thread") => SanitizerSet::THREAD, - Some("hwaddress") => SanitizerSet::HWADDRESS, - Some(s) => return Err(format!("unknown sanitizer {}", s)), - _ => return Err(format!("not a string: {:?}", s)), - }; - } - } else { - incorrect_type.push(name) - } - } - Ok::<(), String>(()) - } ); - ($key_name:ident, link_self_contained_components) => ( { - // Skeleton of what needs to be parsed: - // - // ``` - // $name: { - // "components": [ - // - // ] - // } - // ``` - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - if let Some(o) = o.as_object() { - let component_array = o.get("components") - .ok_or_else(|| format!("{name}: expected a \ - JSON object with a `components` field."))?; - let component_array = component_array.as_array() - .ok_or_else(|| format!("{name}.components: expected a JSON array"))?; - let mut components = LinkSelfContainedComponents::empty(); - for s in component_array { - components |= match s.as_str() { - Some(s) => { - LinkSelfContainedComponents::from_str(s) - .ok_or_else(|| format!("unknown \ - `-Clink-self-contained` component: {s}"))? - }, - _ => return Err(format!("not a string: {:?}", s)), - }; - } - base.$key_name = LinkSelfContainedDefault::WithComponents(components); - } else { - incorrect_type.push(name) - } - } - Ok::<(), String>(()) - } ); - ($key_name:ident = $json_name:expr, link_self_contained_backwards_compatible) => ( { - let name = $json_name; - obj.remove(name).and_then(|o| o.as_str().and_then(|s| { - match s.parse::() { - Ok(lsc_default) => base.$key_name = lsc_default, - _ => return Some(Err(format!("'{}' is not a valid `-Clink-self-contained` default. \ - Use 'false', 'true', 'musl' or 'mingw'", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); - ($key_name:ident = $json_name:expr, link_objects) => ( { - let name = $json_name; - if let Some(val) = obj.remove(name) { - let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ - JSON object with fields per CRT object kind.", name))?; - let mut args = CrtObjects::new(); - for (k, v) in obj { - let kind = LinkOutputKind::from_str(&k).ok_or_else(|| { - format!("{}: '{}' is not a valid value for CRT object kind. \ - Use '(dynamic,static)-(nopic,pic)-exe' or \ - '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k) - })?; - - let v = v.as_array().ok_or_else(|| - format!("{}.{}: expected a JSON array", name, k) - )?.iter().enumerate() - .map(|(i,s)| { - let s = s.as_str().ok_or_else(|| - format!("{}.{}[{}]: expected a JSON string", name, k, i))?; - Ok(s.to_string().into()) - }) - .collect::, String>>()?; - - args.insert(kind, v); - } - base.$key_name = args; - } - } ); - ($key_name:ident = $json_name:expr, link_args) => ( { - let name = $json_name; - if let Some(val) = obj.remove(name) { - let obj = val.as_object().ok_or_else(|| format!("{}: expected a \ - JSON object with fields per linker-flavor.", name))?; - let mut args = LinkArgsCli::new(); - for (k, v) in obj { - let flavor = LinkerFlavorCli::from_str(&k).ok_or_else(|| { - format!("{}: '{}' is not a valid value for linker-flavor. \ - Use 'em', 'gcc', 'ld' or 'msvc'", name, k) - })?; - - let v = v.as_array().ok_or_else(|| - format!("{}.{}: expected a JSON array", name, k) - )?.iter().enumerate() - .map(|(i,s)| { - let s = s.as_str().ok_or_else(|| - format!("{}.{}[{}]: expected a JSON string", name, k, i))?; - Ok(s.to_string().into()) - }) - .collect::, String>>()?; - - args.insert(flavor, v); - } - base.$key_name = args; - } - } ); - ($key_name:ident, env) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - if let Some(o) = obj.remove(&name) { - if let Some(a) = o.as_array() { - for o in a { - if let Some(s) = o.as_str() { - if let [k, v] = *s.split('=').collect::>() { - base.$key_name - .to_mut() - .push((k.to_string().into(), v.to_string().into())) - } - } - } - } else { - incorrect_type.push(name) - } - } - } ); - ($key_name:ident, TargetFamilies) => ( { - if let Some(value) = obj.remove("target-family") { - if let Some(v) = value.as_array() { - base.$key_name = v.iter() - .map(|a| a.as_str().unwrap().to_string().into()) - .collect(); - } else if let Some(v) = value.as_str() { - base.$key_name = vec![v.to_string().into()].into(); - } - } - } ); - ($key_name:ident, Conv) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match Conv::from_str(s) { - Ok(c) => { - base.$key_name = c; - Some(Ok(())) - } - Err(e) => Some(Err(e)) - } - })).unwrap_or(Ok(())) - } ); - } - - if let Some(j) = obj.remove("target-endian") { - if let Some(s) = j.as_str() { - base.endian = s.parse()?; - } else { - incorrect_type.push("target-endian".into()) - } - } - - if let Some(fp) = obj.remove("frame-pointer") { - if let Some(s) = fp.as_str() { - base.frame_pointer = s - .parse() - .map_err(|()| format!("'{s}' is not a valid value for frame-pointer"))?; - } else { - incorrect_type.push("frame-pointer".into()) - } - } - - key!(c_int_width = "target-c-int-width"); - key!(c_enum_min_bits, Option); // if None, matches c_int_width - key!(os); - key!(env); - key!(abi); - key!(vendor); - key!(linker, optional); - key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?; - key!(lld_flavor_json = "lld-flavor", LldFlavor)?; - key!(linker_is_gnu_json = "linker-is-gnu", bool); - key!(pre_link_objects = "pre-link-objects", link_objects); - key!(post_link_objects = "post-link-objects", link_objects); - key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects); - key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects); - // Deserializes the backwards-compatible variants of `-Clink-self-contained` - key!( - link_self_contained = "crt-objects-fallback", - link_self_contained_backwards_compatible - )?; - // Deserializes the components variant of `-Clink-self-contained` - key!(link_self_contained, link_self_contained_components)?; - key!(pre_link_args_json = "pre-link-args", link_args); - key!(late_link_args_json = "late-link-args", link_args); - key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args); - key!(late_link_args_static_json = "late-link-args-static", link_args); - key!(post_link_args_json = "post-link-args", link_args); - key!(link_script, optional); - key!(link_env, env); - key!(link_env_remove, list); - key!(asm_args, list); - key!(cpu); - key!(features); - key!(dynamic_linking, bool); - key!(direct_access_external_data, Option); - key!(dll_tls_export, bool); - key!(only_cdylib, bool); - key!(executables, bool); - key!(relocation_model, RelocModel)?; - key!(code_model, CodeModel)?; - key!(tls_model, TlsModel)?; - key!(disable_redzone, bool); - key!(function_sections, bool); - key!(dll_prefix); - key!(dll_suffix); - key!(exe_suffix); - key!(staticlib_prefix); - key!(staticlib_suffix); - key!(families, TargetFamilies); - key!(abi_return_struct_as_int, bool); - key!(is_like_aix, bool); - key!(is_like_osx, bool); - key!(is_like_solaris, bool); - key!(is_like_windows, bool); - key!(is_like_msvc, bool); - key!(is_like_wasm, bool); - key!(is_like_android, bool); - key!(default_dwarf_version, u32); - key!(allows_weak_linkage, bool); - key!(has_rpath, bool); - key!(no_default_libraries, bool); - key!(position_independent_executables, bool); - key!(static_position_independent_executables, bool); - key!(plt_by_default, bool); - key!(relro_level, RelroLevel)?; - key!(archive_format); - key!(allow_asm, bool); - key!(main_needs_argc_argv, bool); - key!(has_thread_local, bool); - key!(obj_is_bitcode, bool); - key!(bitcode_llvm_cmdline); - key!(max_atomic_width, Option); - key!(min_atomic_width, Option); - key!(atomic_cas, bool); - key!(panic_strategy, PanicStrategy)?; - key!(crt_static_allows_dylibs, bool); - key!(crt_static_default, bool); - key!(crt_static_respected, bool); - key!(stack_probes, StackProbeType)?; - key!(min_global_align, Option); - key!(default_codegen_units, Option); - key!(trap_unreachable, bool); - key!(requires_lto, bool); - key!(singlethread, bool); - key!(no_builtins, bool); - key!(default_visibility, Option)?; - key!(emit_debug_gdb_scripts, bool); - key!(requires_uwtable, bool); - key!(default_uwtable, bool); - key!(simd_types_indirect, bool); - key!(limit_rdylib_exports, bool); - key!(override_export_symbols, opt_list); - key!(merge_functions, MergeFunctions)?; - key!(mcount = "target-mcount"); - key!(llvm_mcount_intrinsic, optional); - key!(llvm_abiname); - key!(relax_elf_relocations, bool); - key!(llvm_args, list); - key!(use_ctors_section, bool); - key!(eh_frame_header, bool); - key!(has_thumb_interworking, bool); - key!(debuginfo_kind, DebuginfoKind)?; - key!(split_debuginfo, SplitDebuginfo)?; - key!(supported_split_debuginfo, fallible_list)?; - key!(supported_sanitizers, SanitizerSet)?; - key!(generate_arange_section, bool); - key!(supports_stack_protector, bool); - key!(small_data_threshold_support, SmallDataThresholdSupport)?; - key!(entry_name); - key!(entry_abi, Conv)?; - key!(supports_xray, bool); - - base.update_from_cli(); - base.check_consistency(TargetKind::Json)?; - - // Each field should have been read using `Json::remove` so any keys remaining are unused. - let remaining_keys = obj.keys(); - Ok((base, TargetWarnings { - unused_fields: remaining_keys.cloned().collect(), - incorrect_type, - })) - } - /// Load a built-in target pub fn expect_builtin(target_tuple: &TargetTuple) -> Target { match *target_tuple { @@ -3924,177 +3308,6 @@ impl Target { } } -impl ToJson for Target { - fn to_json(&self) -> Json { - let mut d = serde_json::Map::new(); - let default: TargetOptions = Default::default(); - let mut target = self.clone(); - target.update_to_cli(); - - macro_rules! target_val { - ($attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - d.insert(name, target.$attr.to_json()); - }}; - } - - macro_rules! target_option_val { - ($attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != target.$attr { - d.insert(name, target.$attr.to_json()); - } - }}; - ($attr:ident, $json_name:expr) => {{ - let name = $json_name; - if default.$attr != target.$attr { - d.insert(name.into(), target.$attr.to_json()); - } - }}; - (link_args - $attr:ident, $json_name:expr) => {{ - let name = $json_name; - if default.$attr != target.$attr { - let obj = target - .$attr - .iter() - .map(|(k, v)| (k.desc().to_string(), v.clone())) - .collect::>(); - d.insert(name.to_string(), obj.to_json()); - } - }}; - (env - $attr:ident) => {{ - let name = (stringify!($attr)).replace("_", "-"); - if default.$attr != target.$attr { - let obj = target - .$attr - .iter() - .map(|&(ref k, ref v)| format!("{k}={v}")) - .collect::>(); - d.insert(name, obj.to_json()); - } - }}; - } - - target_val!(llvm_target); - target_val!(metadata); - d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json()); - target_val!(arch); - target_val!(data_layout); - - target_option_val!(endian, "target-endian"); - target_option_val!(c_int_width, "target-c-int-width"); - target_option_val!(os); - target_option_val!(env); - target_option_val!(abi); - target_option_val!(vendor); - target_option_val!(linker); - target_option_val!(linker_flavor_json, "linker-flavor"); - target_option_val!(lld_flavor_json, "lld-flavor"); - target_option_val!(linker_is_gnu_json, "linker-is-gnu"); - target_option_val!(pre_link_objects); - target_option_val!(post_link_objects); - target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback"); - target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback"); - target_option_val!(link_args - pre_link_args_json, "pre-link-args"); - target_option_val!(link_args - late_link_args_json, "late-link-args"); - target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic"); - target_option_val!(link_args - late_link_args_static_json, "late-link-args-static"); - target_option_val!(link_args - post_link_args_json, "post-link-args"); - target_option_val!(link_script); - target_option_val!(env - link_env); - target_option_val!(link_env_remove); - target_option_val!(asm_args); - target_option_val!(cpu); - target_option_val!(features); - target_option_val!(dynamic_linking); - target_option_val!(direct_access_external_data); - target_option_val!(dll_tls_export); - target_option_val!(only_cdylib); - target_option_val!(executables); - target_option_val!(relocation_model); - target_option_val!(code_model); - target_option_val!(tls_model); - target_option_val!(disable_redzone); - target_option_val!(frame_pointer); - target_option_val!(function_sections); - target_option_val!(dll_prefix); - target_option_val!(dll_suffix); - target_option_val!(exe_suffix); - target_option_val!(staticlib_prefix); - target_option_val!(staticlib_suffix); - target_option_val!(families, "target-family"); - target_option_val!(abi_return_struct_as_int); - target_option_val!(is_like_aix); - target_option_val!(is_like_osx); - target_option_val!(is_like_solaris); - target_option_val!(is_like_windows); - target_option_val!(is_like_msvc); - target_option_val!(is_like_wasm); - target_option_val!(is_like_android); - target_option_val!(default_dwarf_version); - target_option_val!(allows_weak_linkage); - target_option_val!(has_rpath); - target_option_val!(no_default_libraries); - target_option_val!(position_independent_executables); - target_option_val!(static_position_independent_executables); - target_option_val!(plt_by_default); - target_option_val!(relro_level); - target_option_val!(archive_format); - target_option_val!(allow_asm); - target_option_val!(main_needs_argc_argv); - target_option_val!(has_thread_local); - target_option_val!(obj_is_bitcode); - target_option_val!(bitcode_llvm_cmdline); - target_option_val!(min_atomic_width); - target_option_val!(max_atomic_width); - target_option_val!(atomic_cas); - target_option_val!(panic_strategy); - target_option_val!(crt_static_allows_dylibs); - target_option_val!(crt_static_default); - target_option_val!(crt_static_respected); - target_option_val!(stack_probes); - target_option_val!(min_global_align); - target_option_val!(default_codegen_units); - target_option_val!(trap_unreachable); - target_option_val!(requires_lto); - target_option_val!(singlethread); - target_option_val!(no_builtins); - target_option_val!(default_visibility); - target_option_val!(emit_debug_gdb_scripts); - target_option_val!(requires_uwtable); - target_option_val!(default_uwtable); - target_option_val!(simd_types_indirect); - target_option_val!(limit_rdylib_exports); - target_option_val!(override_export_symbols); - target_option_val!(merge_functions); - target_option_val!(mcount, "target-mcount"); - target_option_val!(llvm_mcount_intrinsic); - target_option_val!(llvm_abiname); - target_option_val!(relax_elf_relocations); - target_option_val!(llvm_args); - target_option_val!(use_ctors_section); - target_option_val!(eh_frame_header); - target_option_val!(has_thumb_interworking); - target_option_val!(debuginfo_kind); - target_option_val!(split_debuginfo); - target_option_val!(supported_split_debuginfo); - target_option_val!(supported_sanitizers); - target_option_val!(c_enum_min_bits); - target_option_val!(generate_arange_section); - target_option_val!(supports_stack_protector); - target_option_val!(small_data_threshold_support); - target_option_val!(entry_name); - target_option_val!(entry_abi); - target_option_val!(supports_xray); - - // Serializing `-Clink-self-contained` needs a dynamic key to support the - // backwards-compatible variants. - d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json()); - - Json::Object(d) - } -} - /// Either a target tuple string or a path to a JSON file. #[derive(Clone, Debug)] pub enum TargetTuple { From 15e8a2691b57a1a486851c4cdfc0342724b1d974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 28 Nov 2024 09:40:14 +0200 Subject: [PATCH 147/330] Fix proc macro test --- .../rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 97c76bf8d173..c1ca59606379 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -1085,6 +1085,7 @@ fn resolve_proc_macro() { let sysroot = project_model::Sysroot::discover( &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()), &Default::default(), + project_model::SysrootQueryMetadata::CargoMetadata, ); let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap(); From 807e978923f98189d2a2c06026983e6482472d92 Mon Sep 17 00:00:00 2001 From: longxiangqiao Date: Thu, 28 Nov 2024 15:59:17 +0800 Subject: [PATCH 148/330] chore: fix 404 status URL Signed-off-by: longxiangqiao --- .../rustc/src/platform-support/armeb-unknown-linux-gnueabi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md index e7e3fd01c4dc..3c3e35a51b80 100644 --- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md +++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md @@ -16,7 +16,7 @@ BE8 architecture is the default big-endian architecture for Arm since [Armv6](ht The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard Arm configuration). ## Target definition -The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required. +The target definition can be seen [here](https://github.com/rust-lang/rust/blob/master/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required. ## Building the target Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. From 0c8c38fbc70799508ecac22e0d25b8f3338abcf5 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Thu, 28 Nov 2024 09:03:07 +0100 Subject: [PATCH 149/330] bootstrap: allow skipping steps with start of path --- src/bootstrap/src/core/builder/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index d59e0fa72880..114b5d1cf605 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -258,11 +258,11 @@ impl PathSet { // internal use only fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool { - if let Some(p_kind) = &p.kind { - p.path.ends_with(needle) && *p_kind == module - } else { - p.path.ends_with(needle) - } + let check_path = || { + // This order is important for retro-compatibility, as `starts_with` was introduced later. + p.path.ends_with(needle) || p.path.starts_with(needle) + }; + if let Some(p_kind) = &p.kind { check_path() && *p_kind == module } else { check_path() } } /// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the From 74cf503341d77f2f3e550f6e6b9b527c34d25e71 Mon Sep 17 00:00:00 2001 From: timvisee Date: Thu, 28 Nov 2024 09:39:33 +0100 Subject: [PATCH 150/330] Use consistent wording in docs, use zero instead of 0 --- library/core/src/num/int_macros.rs | 26 +++++++++++++------------- library/core/src/num/uint_macros.rs | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 64dcb4c91e62..6c50f21a773b 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1828,7 +1828,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -1986,7 +1986,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2014,7 +2014,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2042,7 +2042,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2069,7 +2069,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2526,7 +2526,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2557,7 +2557,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2588,7 +2588,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2619,7 +2619,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2887,7 +2887,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples @@ -2926,7 +2926,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` and + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` and /// `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples @@ -2975,7 +2975,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples @@ -3019,7 +3019,7 @@ macro_rules! int_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0 or if `self` is `Self::MIN` + /// This function will panic if `rhs` is zero or if `self` is `Self::MIN` /// and `rhs` is -1. This behavior is not affected by the `overflow-checks` flag. /// /// # Examples diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0383c13fa082..23aace0cd666 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1877,7 +1877,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2034,7 +2034,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2063,7 +2063,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2091,7 +2091,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2121,7 +2121,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2545,7 +2545,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2576,7 +2576,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2604,7 +2604,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2635,7 +2635,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2872,7 +2872,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// @@ -2900,7 +2900,7 @@ macro_rules! uint_impl { /// /// # Panics /// - /// This function will panic if `rhs` is 0. + /// This function will panic if `rhs` is zero. /// /// # Examples /// From 89b20e95fd6cb6e976692505ca4ee74e2df3f028 Mon Sep 17 00:00:00 2001 From: timvisee Date: Thu, 28 Nov 2024 09:46:26 +0100 Subject: [PATCH 151/330] Also use zero when referencing to capacity or length --- .../alloc/src/collections/binary_heap/mod.rs | 4 +-- library/alloc/src/vec/mod.rs | 8 ++--- library/core/src/iter/traits/iterator.rs | 4 +-- library/core/src/slice/mod.rs | 32 +++++++++---------- library/std/src/collections/hash/map.rs | 4 +-- library/std/src/collections/hash/set.rs | 4 +-- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 59f10b09c73f..0bc65cdbc55a 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -452,7 +452,7 @@ impl BinaryHeap { /// /// The binary heap will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the binary heap will not allocate. + /// `capacity`. If `capacity` is zero, the binary heap will not allocate. /// /// # Examples /// @@ -496,7 +496,7 @@ impl BinaryHeap { /// /// The binary heap will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the binary heap will not allocate. + /// `capacity`. If `capacity` is zero, the binary heap will not allocate. /// /// # Examples /// diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 990b7e8f7612..87e730b13f8b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -427,7 +427,7 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// It is important to note that although the returned vector has the /// minimum *capacity* specified, the vector will have a zero *length*. For @@ -487,7 +487,7 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// # Errors /// @@ -745,7 +745,7 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// It is important to note that although the returned vector has the /// minimum *capacity* specified, the vector will have a zero *length*. For @@ -808,7 +808,7 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector will not allocate. /// /// # Errors /// diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index ffaf1bc56e94..38dfbbef3932 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1553,7 +1553,7 @@ pub trait Iterator { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a + /// Panics if `N` is zero. This check will most probably get changed to a /// compile time error before this method gets stabilized. /// /// ```should_panic @@ -3454,7 +3454,7 @@ pub trait Iterator { /// /// # Panics /// - /// Panics if `N` is 0. + /// Panics if `N` is zero. /// /// # Examples /// diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b3defba5a982..96426cd189cb 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1039,7 +1039,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `size` is 0. + /// Panics if `size` is zero. /// /// # Examples /// @@ -1095,7 +1095,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1130,7 +1130,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1172,7 +1172,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1211,7 +1211,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1288,7 +1288,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1334,7 +1334,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1372,7 +1372,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1448,7 +1448,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1489,7 +1489,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1533,7 +1533,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1568,7 +1568,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `N` is 0. This check will most probably get changed to a compile time + /// Panics if `N` is zero. This check will most probably get changed to a compile time /// error before this method gets stabilized. /// /// # Examples @@ -1604,7 +1604,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1639,7 +1639,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1682,7 +1682,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// @@ -1722,7 +1722,7 @@ impl [T] { /// /// # Panics /// - /// Panics if `chunk_size` is 0. + /// Panics if `chunk_size` is zero. /// /// # Examples /// diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 24bbc2f32cf6..09c0b61fb2b8 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -235,7 +235,7 @@ impl HashMap { /// /// The hash map will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash map will not allocate. + /// `capacity`. If `capacity` is zero, the hash map will not allocate. /// /// # Examples /// @@ -287,7 +287,7 @@ impl HashMap { /// /// The hash map will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash map will not allocate. + /// `capacity`. If `capacity` is zero, the hash map will not allocate. /// /// Warning: `hasher` is normally randomly generated, and /// is designed to allow HashMaps to be resistant to attacks that diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index f86bcdb4796e..21a73259f617 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -130,7 +130,7 @@ impl HashSet { /// /// The hash set will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash set will not allocate. + /// `capacity`. If `capacity` is zero, the hash set will not allocate. /// /// # Examples /// @@ -379,7 +379,7 @@ impl HashSet { /// /// The hash set will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is 0, the hash set will not allocate. + /// `capacity`. If `capacity` is zero, the hash set will not allocate. /// /// Warning: `hasher` is normally randomly generated, and /// is designed to allow `HashSet`s to be resistant to attacks that From 9fe7750bcd51f54b8ef171c3323b2acc54679533 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 27 Nov 2024 18:37:39 +0100 Subject: [PATCH 152/330] uplift fold_regions to rustc_type_ir --- compiler/rustc_borrowck/src/lib.rs | 3 +- .../rustc_borrowck/src/region_infer/mod.rs | 5 +- .../src/region_infer/opaque_types.rs | 7 +- compiler/rustc_borrowck/src/renumber.rs | 3 +- .../src/type_check/constraint_conversion.rs | 3 +- compiler/rustc_borrowck/src/type_check/mod.rs | 5 +- .../rustc_borrowck/src/universal_regions.rs | 6 +- .../rustc_hir_analysis/src/check/check.rs | 4 +- compiler/rustc_hir_analysis/src/collect.rs | 3 +- .../rustc_hir_analysis/src/collect/type_of.rs | 3 +- .../src/hir_ty_lowering/mod.rs | 3 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 3 +- compiler/rustc_hir_typeck/src/writeback.rs | 7 +- .../src/infer/lexical_region_resolve/mod.rs | 4 +- compiler/rustc_infer/src/infer/mod.rs | 4 +- compiler/rustc_middle/src/mir/query.rs | 5 +- compiler/rustc_middle/src/ty/fold.rs | 83 +------------------ compiler/rustc_middle/src/ty/util.rs | 3 +- .../infer/nice_region_error/util.rs | 3 +- .../src/traits/select/mod.rs | 3 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 4 +- compiler/rustc_ty_utils/src/ty.rs | 3 +- compiler/rustc_type_ir/src/fold.rs | 74 ++++++++++++++++- src/librustdoc/clean/auto_trait.rs | 3 +- 24 files changed, 129 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 16a4f6991774..9b7474c22084 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -34,6 +34,7 @@ use rustc_infer::infer::{ use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::*; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ @@ -502,7 +503,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { for data in tcx.typeck(def_id).concrete_opaque_types.iter().map(|(k, v)| (*k, *v)) { // HIR typeck did not infer the regions of the opaque, so we instantiate // them with fresh inference variables. - let (key, hidden_ty) = tcx.fold_regions(data, |_, _| { + let (key, hidden_ty) = fold_regions(tcx, data, |_, _| { self.next_nll_region_var_in_universe( NllRegionVariableOrigin::Existential { from_forall: false }, ty::UniverseIndex::ROOT, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 0ddb4e110e3f..99af5500ac63 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -18,6 +18,7 @@ use rustc_middle::mir::{ TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; @@ -1100,7 +1101,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let ty = ty.fold_with(&mut OpaqueFolder { tcx }); let mut failed = false; - let ty = tcx.fold_regions(ty, |r, _depth| { + let ty = fold_regions(tcx, ty, |r, _depth| { let r_vid = self.to_region_vid(r); let r_scc = self.constraint_sccs.scc(r_vid); @@ -1273,7 +1274,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable>, { - tcx.fold_regions(value, |r, _db| { + fold_regions(tcx, value, |r, _db| { let vid = self.to_region_vid(r); let scc = self.constraint_sccs.scc(vid); let repr = self.scc_representative(scc); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 993d5d863339..7164a129235f 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -3,6 +3,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; use rustc_macros::extension; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, @@ -117,7 +118,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }); debug!(?opaque_type_key, ?arg_regions); - let concrete_type = infcx.tcx.fold_regions(concrete_type, |region, _| { + let concrete_type = fold_regions(infcx.tcx, concrete_type, |region, _| { arg_regions .iter() .find(|&&(arg_vid, _)| self.eval_equal(region.as_var(), arg_vid)) @@ -204,7 +205,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable>, { - tcx.fold_regions(ty, |region, _| match *region { + fold_regions(tcx, ty, |region, _| match *region { ty::ReVar(vid) => { let scc = self.constraint_sccs.scc(vid); @@ -442,7 +443,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> { let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); let mut seen = vec![tcx.lifetimes.re_static]; - let canonical_args = tcx.fold_regions(args, |r1, _| { + let canonical_args = fold_regions(tcx, args, |r1, _| { if r1.is_error() { r1 } else if let Some(&r2) = seen.iter().find(|&&r2| { diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index b7aef71eb54a..d83d6ade2032 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -2,6 +2,7 @@ use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::{Body, ConstOperand, Location, Promoted}; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable}; use rustc_span::Symbol; use tracing::{debug, instrument}; @@ -68,7 +69,7 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> { F: Fn() -> RegionCtxt, { let origin = NllRegionVariableOrigin::Existential { from_forall: false }; - self.infcx.tcx.fold_regions(value, |_region, _depth| { + fold_regions(self.infcx.tcx, value, |_region, _depth| { self.infcx.next_nll_region_var(origin, || region_ctxt_fn()) }) } diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 67915371b1f2..918efac2a201 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -8,6 +8,7 @@ use rustc_middle::bug; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::traits::ScrubbedTraitError; @@ -216,7 +217,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { /// are dealt with during trait solving. fn replace_placeholders_with_nll>>(&mut self, value: T) -> T { if value.has_placeholders() { - self.tcx.fold_regions(value, |r, _| match *r { + fold_regions(self.tcx, value, |r, _| match *r { ty::RePlaceholder(placeholder) => { self.constraints.placeholder_region(self.infcx, placeholder) } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index b4763acbefa0..89e683b8ae3d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -26,6 +26,7 @@ use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt, @@ -213,7 +214,7 @@ pub(crate) fn type_check<'a, 'tcx>( // Convert all regions to nll vars. let (opaque_type_key, hidden_type) = - infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| { + fold_regions(infcx.tcx, (opaque_type_key, hidden_type), |region, _| { match region.kind() { ty::ReVar(_) => region, ty::RePlaceholder(placeholder) => { @@ -2073,7 +2074,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let is_implicit_coercion = coercion_source == CoercionSource::Implicit; - let unsize_to = tcx.fold_regions(ty, |r, _| { + let unsize_to = fold_regions(tcx, ty, |r, _| { if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r } }); self.prove_trait_ref( diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index f1c23aa26a97..86a0111db49b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -26,7 +26,7 @@ use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_macros::extension; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::fold::{TypeFoldable, fold_regions}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, @@ -824,7 +824,7 @@ impl<'tcx> BorrowckInferCtxt<'tcx> { where T: TypeFoldable>, { - self.infcx.tcx.fold_regions(value, |region, _depth| { + fold_regions(self.infcx.tcx, value, |region, _depth| { let name = region.get_name_or_anon(); debug!(?region, ?name); @@ -906,7 +906,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { where T: TypeFoldable>, { - tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region))) + fold_regions(tcx, value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region))) } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c66572a93772..24d37bfad793 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -17,7 +17,7 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; use rustc_middle::ty::error::TypeErrorToStringExt; -use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::ty::fold::{BottomUpFolder, fold_regions}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt}; use rustc_middle::ty::{ @@ -346,7 +346,7 @@ fn check_opaque_meets_bounds<'tcx>( // FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it // here rather than using ReErased. let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args); - let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() { + let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() { ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)), _ => re, }); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 93be3e06e5d9..cf062e82cb60 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,6 +34,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; @@ -1415,7 +1416,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( GenericParamKind::Lifetime { .. } => true, _ => false, }); - let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r { + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r { ty::ReErased => { if has_region_params { ty::Region::new_error_with_message( diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 816761fd00fa..18fb5bfd912f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,6 +5,7 @@ use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::plumbing::CyclePlaceholder; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; @@ -113,7 +114,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // so no need for ConstArg. Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { let ty = tcx.typeck(def_id).node_type(tcx.local_def_id_to_hir_id(def_id)); - let ty = tcx.fold_regions(ty, |r, _| { + let ty = fold_regions(tcx, ty, |r, _| { if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } }); let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false, None) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 01276abec22b..cf780a3d3bba 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -37,6 +37,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, @@ -1569,7 +1570,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), ); - let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); + let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... if value.has_escaping_bound_vars() { return false; diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 5b0165bf993d..c0fb94d2cb29 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,6 +5,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -75,7 +76,7 @@ fn diagnostic_hir_wf_check<'tcx>( // This visitor can walk into binders, resulting in the `tcx_ty` to // potentially reference escaping bound variables. We simply erase // those here. - let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| { + let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| { if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } }); let cause = traits::ObligationCause::new( diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 2f436ce77a40..e17a68c86921 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, fold_regions}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable}; use rustc_span::Span; @@ -827,7 +827,10 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { // no reason to keep regions around. They will be repopulated during MIR // borrowck, and specifically region constraints will be populated during // MIR typeck which is run on the new body. - value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased); + // + // We're not using `tcx.erase_regions` as that also anonymizes bound variables, + // regressing borrowck diagnostics. + value = fold_regions(tcx, value, |_, _| tcx.lifetimes.re_erased); // Normalize consts in writeback, because GCE doesn't normalize eagerly. if tcx.features().generic_const_exprs() { diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 6af49accc841..e454a88e847f 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -9,7 +9,7 @@ use rustc_data_structures::graph::implementation::{ use rustc_data_structures::intern::Interned; use rustc_data_structures::unord::UnordSet; use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::fold::{TypeFoldable, fold_regions}; use rustc_middle::ty::{ self, ReBound, ReEarlyParam, ReErased, ReError, ReLateParam, RePlaceholder, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt, @@ -974,7 +974,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { where T: TypeFoldable>, { - tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r)) + fold_regions(tcx, value, |r, _db| self.resolve_region(tcx, r)) } fn value(&self, rid: RegionVid) -> &VarValue<'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 555c1022a8a1..233c24f8c432 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -33,7 +33,7 @@ use rustc_middle::traits::select; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{ - BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, + BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, }; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ @@ -1165,7 +1165,7 @@ impl<'tcx> InferCtxt<'tcx> { } if value.has_infer_regions() { let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved")); - Ok(self.tcx.fold_regions(value, |re, _| { + Ok(fold_regions(self.tcx, value, |re, _| { if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re } })) } else { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 86abeb503823..8a7083687135 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -17,6 +17,7 @@ use smallvec::SmallVec; use super::{ConstValue, SourceInfo}; use crate::mir; +use crate::ty::fold::fold_regions; use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt}; rustc_index::newtype_index! { @@ -315,7 +316,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { /// All regions of `ty` must be of kind `ReVar` and must represent /// universal regions *external* to the closure. pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { - let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { + let inner = fold_regions(tcx, ty, |r, depth| match r.kind() { ty::ReVar(vid) => { let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), @@ -334,7 +335,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { tcx: TyCtxt<'tcx>, mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, ) -> Ty<'tcx> { - tcx.fold_regions(self.inner, |r, depth| match r.kind() { + fold_regions(tcx, self.inner, |r, depth| match r.kind() { ty::ReBound(debruijn, br) => { debug_assert_eq!(debruijn, depth); map(ty::RegionVid::new(br.var.index())) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 7adbd556141f..1b073d3c466d 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -2,9 +2,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; pub use rustc_type_ir::fold::{ - FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region, shift_vars, + FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, shift_region, + shift_vars, }; -use tracing::{debug, instrument}; use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt}; @@ -50,85 +50,6 @@ where } } -/////////////////////////////////////////////////////////////////////////// -// Region folder - -impl<'tcx> TyCtxt<'tcx> { - /// Folds the escaping and free regions in `value` using `f`. - pub fn fold_regions( - self, - value: T, - mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, - ) -> T - where - T: TypeFoldable>, - { - value.fold_with(&mut RegionFolder::new(self, &mut f)) - } -} - -/// Folds over the substructure of a type, visiting its component -/// types and all regions that occur *free* within it. -/// -/// That is, function pointer types and trait object can introduce -/// new bound regions which are not visited by this visitors as -/// they are not free; only regions that occur free will be -/// visited by `fld_r`. -pub struct RegionFolder<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - - /// Stores the index of a binder *just outside* the stuff we have - /// visited. So this begins as INNERMOST; when we pass through a - /// binder, it is incremented (via `shift_in`). - current_index: ty::DebruijnIndex, - - /// Callback invokes for each free region. The `DebruijnIndex` - /// points to the binder *just outside* the ones we have passed - /// through. - fold_region_fn: - &'a mut (dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx> + 'a), -} - -impl<'a, 'tcx> RegionFolder<'a, 'tcx> { - #[inline] - pub fn new( - tcx: TyCtxt<'tcx>, - fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>, - ) -> RegionFolder<'a, 'tcx> { - RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn } - } -} - -impl<'a, 'tcx> TypeFolder> for RegionFolder<'a, 'tcx> { - fn cx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_binder>>( - &mut self, - t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.current_index.shift_in(1); - let t = t.super_fold_with(self); - self.current_index.shift_out(1); - t - } - - #[instrument(skip(self), level = "debug", ret)] - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReBound(debruijn, _) if debruijn < self.current_index => { - debug!(?self.current_index, "skipped bound region"); - r - } - _ => { - debug!(?self.current_index, "folding free region"); - (self.fold_region_fn)(r, self.current_index) - } - } - } -} - /////////////////////////////////////////////////////////////////////////// // Bound vars replacer diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 55a7a837b6de..797ac9685b1e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -21,6 +21,7 @@ use tracing::{debug, instrument}; use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::Providers; +use crate::ty::fold::fold_regions; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable, @@ -735,7 +736,7 @@ impl<'tcx> TyCtxt<'tcx> { .filter(|decl| !decl.ignore_for_traits) .map(move |decl| { let mut vars = vec![]; - let ty = self.fold_regions(decl.ty, |re, debruijn| { + let ty = fold_regions(self, decl.ty, |re, debruijn| { assert_eq!(re, self.lifetimes.re_erased); let var = ty::BoundVar::from_usize(vars.len()); vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 75054b221533..218d2e753efd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -3,6 +3,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use tracing::instrument; @@ -83,7 +84,7 @@ pub fn find_param_with_region<'tcx>( // May return None; sometimes the tables are not yet populated. let ty = fn_sig.inputs()[index]; let mut found_anon_region = false; - let new_param_ty = tcx.fold_regions(ty, |r, _| { + let new_param_ty = fold_regions(tcx, ty, |r, _| { if r == anon_region { found_anon_region = true; replace_region diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3b64a47181a6..c7ee9b939be4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -25,6 +25,7 @@ use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds}; pub use rustc_middle::traits::select::*; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::TypeErrorToStringExt; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{ self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, @@ -3209,7 +3210,7 @@ fn bind_coroutine_hidden_types_above<'tcx>( // Only remap erased regions if we use them. if considering_regions { bty = bty.map_bound(|ty| { - tcx.fold_regions(ty, |r, current_depth| match r.kind() { + fold_regions(tcx, ty, |r, current_depth| match r.kind() { ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 5cd10e905387..c4637f1293cb 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -6,6 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -86,7 +87,8 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' } } // FIXME: This could use a real folder, I guess. - let remapped_wf_tys = tcx.fold_regions( + let remapped_wf_tys = fold_regions( + tcx, tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), |region, _| { // If `region` is a `ReLateParam` that is captured by the diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 61f2262dfe83..774f06602588 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -5,6 +5,7 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::bug; use rustc_middle::query::Providers; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, }; @@ -197,7 +198,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { // We have entered some binders as we've walked into the // bounds of the RPITIT. Shift these binders back out when // constructing the top-level projection predicate. - let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| { + let shifted_alias_ty = fold_regions(self.tcx, unshifted_alias_ty, |re, depth| { if let ty::ReBound(index, bv) = re.kind() { if depth != ty::INNERMOST { return ty::Region::new_error_with_message( diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 8209d6f5fe3b..d337a1a8ad9b 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -49,7 +49,7 @@ use std::mem; use rustc_index::{Idx, IndexVec}; use thin_vec::ThinVec; -use tracing::instrument; +use tracing::{debug, instrument}; use crate::data_structures::Lrc; use crate::inherent::*; @@ -431,3 +431,75 @@ where value.fold_with(&mut Shifter::new(cx, amount)) } } + +/////////////////////////////////////////////////////////////////////////// +// Region folder + +pub fn fold_regions( + cx: I, + value: T, + mut f: impl FnMut(I::Region, ty::DebruijnIndex) -> I::Region, +) -> T +where + T: TypeFoldable, +{ + value.fold_with(&mut RegionFolder::new(cx, &mut f)) +} + +/// Folds over the substructure of a type, visiting its component +/// types and all regions that occur *free* within it. +/// +/// That is, function pointer types and trait object can introduce +/// new bound regions which are not visited by this visitors as +/// they are not free; only regions that occur free will be +/// visited by `fld_r`. +pub struct RegionFolder<'a, I: Interner> { + cx: I, + + /// Stores the index of a binder *just outside* the stuff we have + /// visited. So this begins as INNERMOST; when we pass through a + /// binder, it is incremented (via `shift_in`). + current_index: ty::DebruijnIndex, + + /// Callback invokes for each free region. The `DebruijnIndex` + /// points to the binder *just outside* the ones we have passed + /// through. + fold_region_fn: &'a mut (dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region + 'a), +} + +impl<'a, I: Interner> RegionFolder<'a, I> { + #[inline] + pub fn new( + cx: I, + fold_region_fn: &'a mut dyn FnMut(I::Region, ty::DebruijnIndex) -> I::Region, + ) -> RegionFolder<'a, I> { + RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn } + } +} + +impl<'a, I: Interner> TypeFolder for RegionFolder<'a, I> { + fn cx(&self) -> I { + self.cx + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + #[instrument(skip(self), level = "debug", ret)] + fn fold_region(&mut self, r: I::Region) -> I::Region { + match r.kind() { + ty::ReBound(debruijn, _) if debruijn < self.current_index => { + debug!(?self.current_index, "skipped bound region"); + r + } + _ => { + debug!(?self.current_index, "folding free region"); + (self.fold_region_fn)(r, self.current_index) + } + } + } +} diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 3fe567b1c397..185898c31b75 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_hir as hir; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::bug; +use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, Region, Ty}; use rustc_span::def_id::DefId; use rustc_span::symbol::{Symbol, kw}; @@ -182,7 +183,7 @@ fn clean_param_env<'tcx>( .is_some_and(|pred| tcx.lang_items().sized_trait() == Some(pred.def_id())) }) .map(|pred| { - tcx.fold_regions(pred, |r, _| match *r { + fold_regions(tcx, pred, |r, _| match *r { // FIXME: Don't `unwrap_or`, I think we should panic if we encounter an infer var that // we can't map to a concrete region. However, `AutoTraitFinder` *does* leak those kinds // of `ReVar`s for some reason at the time of writing. See `rustdoc-ui/` tests. From 18e2253e79fc8a5973a7abfb0fe19f60961338b5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 26 Nov 2024 15:40:54 +0100 Subject: [PATCH 153/330] move tests into subdir --- .../ui/traits/next-solver/{ => opaques}/dont-remap-tait-substs.rs | 0 .../dont-type_of-tait-in-defining-scope.is_send.stderr | 0 .../dont-type_of-tait-in-defining-scope.not_send.stderr | 0 .../{ => opaques}/dont-type_of-tait-in-defining-scope.rs | 0 .../next-solver/{ => opaques}/select-alias-bound-as-param.rs | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/traits/next-solver/{ => opaques}/dont-remap-tait-substs.rs (100%) rename tests/ui/traits/next-solver/{ => opaques}/dont-type_of-tait-in-defining-scope.is_send.stderr (100%) rename tests/ui/traits/next-solver/{ => opaques}/dont-type_of-tait-in-defining-scope.not_send.stderr (100%) rename tests/ui/traits/next-solver/{ => opaques}/dont-type_of-tait-in-defining-scope.rs (100%) rename tests/ui/traits/next-solver/{ => opaques}/select-alias-bound-as-param.rs (100%) diff --git a/tests/ui/traits/next-solver/dont-remap-tait-substs.rs b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs similarity index 100% rename from tests/ui/traits/next-solver/dont-remap-tait-substs.rs rename to tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr similarity index 100% rename from tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.is_send.stderr rename to tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr similarity index 100% rename from tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.not_send.stderr rename to tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr diff --git a/tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs similarity index 100% rename from tests/ui/traits/next-solver/dont-type_of-tait-in-defining-scope.rs rename to tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs diff --git a/tests/ui/traits/next-solver/select-alias-bound-as-param.rs b/tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs similarity index 100% rename from tests/ui/traits/next-solver/select-alias-bound-as-param.rs rename to tests/ui/traits/next-solver/opaques/select-alias-bound-as-param.rs From 34a8c2dbba9fe2d57029027781500ab7fc305199 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 26 Nov 2024 16:01:08 +0100 Subject: [PATCH 154/330] support revealing defined opaque post borrowck --- .../rustc_hir_analysis/src/check/check.rs | 14 +++- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- compiler/rustc_infer/src/infer/context.rs | 6 +- compiler/rustc_infer/src/infer/mod.rs | 13 +++- .../rustc_infer/src/infer/opaque_types/mod.rs | 5 +- .../src/solve/assembly/mod.rs | 4 +- .../src/solve/eval_ctxt/mod.rs | 6 ++ .../rustc_next_trait_solver/src/solve/mod.rs | 15 ++++- .../src/solve/normalizes_to/mod.rs | 21 ++---- .../src/solve/normalizes_to/opaque_types.rs | 21 ++++++ .../src/solve/trait_goals.rs | 19 ++---- .../src/solve/delegate.rs | 4 +- .../src/traits/normalize.rs | 14 ++-- .../src/traits/project.rs | 4 +- .../src/traits/query/normalize.rs | 6 +- .../src/traits/select/mod.rs | 7 +- compiler/rustc_ty_utils/src/instance.rs | 3 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 13 ++++ compiler/rustc_type_ir/src/relate/combine.rs | 6 +- .../no-define-in-wf-check.current.stderr | 34 ++++++++++ .../opaques/no-define-in-wf-check.rs | 66 +++++++++++++++++++ 21 files changed, 226 insertions(+), 58 deletions(-) create mode 100644 tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr create mode 100644 tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 24d37bfad793..192dc1b4d229 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -322,8 +322,12 @@ fn check_opaque_meets_bounds<'tcx>( }; let param_env = tcx.param_env(defining_use_anchor); - // FIXME(#132279): This should eventually use the already defined hidden types. - let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); + // FIXME(#132279): Once `PostBorrowckAnalysis` is supported in the old solver, this branch should be removed. + let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() { + TypingMode::post_borrowck_analysis(tcx, defining_use_anchor) + } else { + TypingMode::analysis_in_body(tcx, defining_use_anchor) + }); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let args = match origin { @@ -417,7 +421,11 @@ fn check_opaque_meets_bounds<'tcx>( let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; - if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = origin { + if infcx.next_trait_solver() { + Ok(()) + } else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } = + origin + { // HACK: this should also fall through to the hidden type check below, but the original // implementation had a bug where equivalent lifetimes are not identical. This caused us // to reject existing stable code that is otherwise completely fine. The real fix is to diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 5aaad3636a2a..039c117c0999 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1574,7 +1574,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Thus we need to prevent them from trying to match the `&_` autoref // candidates that get created for `&self` trait methods. ty::Alias(ty::Opaque, alias_ty) - if self.infcx.can_define_opaque_ty(alias_ty.def_id) + if !self.next_trait_solver() + && self.infcx.can_define_opaque_ty(alias_ty.def_id) && !xform_self_ty.is_ty_var() => { return ProbeResult::NoMatch; diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 1968ed347529..5fc9b679c8ac 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DUMMY_SP, ErrorGuaranteed}; -use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin}; +use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; @@ -87,6 +87,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) } + fn next_region_infer(&self) -> ty::Region<'tcx> { + self.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) + } + fn next_ty_infer(&self) -> Ty<'tcx> { self.next_ty_var(DUMMY_SP) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 233c24f8c432..544f941dda57 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -990,11 +990,17 @@ impl<'tcx> InferCtxt<'tcx> { #[inline(always)] pub fn can_define_opaque_ty(&self, id: impl Into) -> bool { + debug_assert!(!self.next_trait_solver()); match self.typing_mode() { TypingMode::Analysis { defining_opaque_types } => { id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id)) } - TypingMode::Coherence | TypingMode::PostAnalysis => false, + // FIXME(#132279): This function is quite weird in post-analysis + // and post-borrowck analysis mode. We may need to modify its uses + // to support PostBorrowckAnalysis in the old solver as well. + TypingMode::Coherence + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => false, } } @@ -1276,7 +1282,6 @@ impl<'tcx> InferCtxt<'tcx> { /// using canonicalization or carrying this inference context around. pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> { let typing_mode = match self.typing_mode() { - ty::TypingMode::Coherence => ty::TypingMode::Coherence, // FIXME(#132279): This erases the `defining_opaque_types` as it isn't possible // to handle them without proper canonicalization. This means we may cause cycle // errors and fail to reveal opaques while inside of bodies. We should rename this @@ -1284,7 +1289,9 @@ impl<'tcx> InferCtxt<'tcx> { ty::TypingMode::Analysis { defining_opaque_types: _ } => { TypingMode::non_body_analysis() } - ty::TypingMode::PostAnalysis => ty::TypingMode::PostAnalysis, + mode @ (ty::TypingMode::Coherence + | ty::TypingMode::PostBorrowckAnalysis { .. } + | ty::TypingMode::PostAnalysis) => mode, }; ty::TypingEnv { typing_mode, param_env } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index a608ea1ad579..b64686afd234 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -98,6 +98,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, param_env: ty::ParamEnv<'tcx>, ) -> Result>>, TypeError<'tcx>> { + debug_assert!(!self.next_trait_solver()); let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); @@ -546,7 +547,9 @@ impl<'tcx> InferCtxt<'tcx> { ); } } - ty::TypingMode::PostAnalysis => bug!("insert hidden type post-analysis"), + mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => { + bug!("insert hidden type in {mode:?}") + } } Ok(()) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index adac35b57cd7..198ccb000f34 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -339,7 +339,9 @@ where match self.typing_mode() { TypingMode::Coherence => {} - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => { self.discard_impls_shadowed_by_env(goal, &mut candidates); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 40d1576256eb..70ceb22bfea5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -644,6 +644,12 @@ where } } + pub(super) fn next_region_var(&mut self) -> I::Region { + let region = self.delegate.next_region_infer(); + self.inspect.add_var_value(region); + region + } + pub(super) fn next_ty_infer(&mut self) -> I::Ty { let ty = self.delegate.next_ty_infer(); self.inspect.add_var_value(ty); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 5c54656cc59f..ebf1013db1ec 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -23,7 +23,7 @@ mod trait_goals; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner}; +use rustc_type_ir::{self as ty, Interner, TypingMode}; use tracing::instrument; pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt}; @@ -321,6 +321,19 @@ where Ok(ct) } } + + fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool { + match self.typing_mode() { + // Opaques are never rigid outside of analysis mode. + TypingMode::Coherence | TypingMode::PostAnalysis => false, + // During analysis, opaques are rigid unless they may be defined by + // the current body. + TypingMode::Analysis { defining_opaque_types: non_rigid_opaques } + | TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => { + !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id)) + } + } + } } fn response_no_constraints_raw( diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 33bd1cf2f56e..f5b1b23b8e97 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -6,7 +6,7 @@ mod weak_types; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, NormalizesTo, TypingMode, Upcast as _}; +use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -71,21 +71,10 @@ where Ok(()) } ty::AliasTermKind::OpaqueTy => { - match self.typing_mode() { - // Opaques are never rigid outside of analysis mode. - TypingMode::Coherence | TypingMode::PostAnalysis => Err(NoSolution), - // During analysis, opaques are only rigid if we may not define it. - TypingMode::Analysis { defining_opaque_types } => { - if rigid_alias - .def_id - .as_local() - .is_some_and(|def_id| defining_opaque_types.contains(&def_id)) - { - Err(NoSolution) - } else { - Ok(()) - } - } + if self.opaque_type_is_rigid(rigid_alias.def_id) { + Ok(()) + } else { + Err(NoSolution) } } // FIXME(generic_const_exprs): we would need to support generic consts here diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 336bcb9df33a..26a8a22d77eb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -2,6 +2,7 @@ //! behaves differently depending on the current `TypingMode`. use rustc_index::bit_set::GrowableBitSet; +use rustc_type_ir::fold::fold_regions; use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner, TypingMode}; @@ -95,6 +96,26 @@ where ); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } + TypingMode::PostBorrowckAnalysis { defined_opaque_types } => { + let Some(def_id) = opaque_ty.def_id.as_local() else { + return Err(NoSolution); + }; + + if !defined_opaque_types.contains(&def_id) { + return Err(NoSolution); + } + + let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); + // FIXME: Actually use a proper binder here instead of relying on `ReErased`. + // + // This is also probably unsound or sth :shrug: + let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() { + ty::ReErased => self.next_region_var(), + _ => re, + }); + self.eq(goal.param_env, expected, actual)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } TypingMode::PostAnalysis => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 096dc32ccc92..6641d2bf9249 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -69,7 +69,9 @@ where // it's not a real impl. (ty::ImplPolarity::Reservation, _) => match ecx.typing_mode() { TypingMode::Coherence => Certainty::AMBIGUOUS, - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => return Err(NoSolution), }, // Impl matches polarity @@ -174,20 +176,7 @@ where // ideally we want to avoid, since we can make progress on this goal // via an alias bound or a locally-inferred hidden type instead. if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { - match ecx.typing_mode() { - TypingMode::Coherence | TypingMode::PostAnalysis => { - unreachable!("rigid opaque outside of analysis: {goal:?}"); - } - TypingMode::Analysis { defining_opaque_types } => { - if opaque_ty - .def_id - .as_local() - .is_some_and(|def_id| defining_opaque_types.contains(&def_id)) - { - return Err(NoSolution); - } - } - } + debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id)); } ecx.probe_and_evaluate_goal_for_constituent_tys( diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 09bba24ba613..97cde67799c2 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -205,7 +205,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. match self.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { .. } => false, + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => false, TypingMode::PostAnalysis => { let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); !poly_trait_ref.still_further_specializable() diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 4d3d8c66e62b..e99c5eacbd8e 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -118,9 +118,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( // Opaques are treated as rigid outside of `TypingMode::PostAnalysis`, // so we can ignore those. match infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { - flags.remove(ty::TypeFlags::HAS_TY_OPAQUE) - } + // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), TypingMode::PostAnalysis => {} } @@ -213,9 +214,10 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ty::Opaque => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.selcx.infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { - ty.super_fold_with(self) - } + // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self), TypingMode::PostAnalysis => { let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2864f277df57..01f6cccb375a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -975,7 +975,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. match selcx.infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { .. } => { + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => { debug!( assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), ?obligation.predicate, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 22cfbb2c8403..2ef9d5421ba6 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -216,9 +216,9 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { ty::Opaque => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.infcx.typing_mode() { - TypingMode::Coherence | TypingMode::Analysis { defining_opaque_types: _ } => { - ty.try_super_fold_with(self)? - } + TypingMode::Coherence + | TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?, TypingMode::PostAnalysis => { let args = data.args.try_fold_with(self)?; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c7ee9b939be4..50c4f9eff6ff 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1471,7 +1471,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let obligation = &stack.obligation; match self.infcx.typing_mode() { TypingMode::Coherence => {} - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => return Ok(()), + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => return Ok(()), } debug!("is_knowable()"); @@ -1518,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TypingMode::Analysis { defining_opaque_types } => { defining_opaque_types.is_empty() || !pred.has_opaque_types() } + // The hidden types of `defined_opaque_types` is not local to the current + // inference context, so we can freely move this to the global cache. + TypingMode::PostBorrowckAnalysis { .. } => true, // The global cache is only used if there are no opaque types in // the defining scope or we're outside of analysis. // diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 8798772e398d..1a98c85bee9f 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -149,7 +149,8 @@ fn resolve_associated_item<'tcx>( // get a result which isn't correct for all monomorphizations. match typing_env.typing_mode { ty::TypingMode::Coherence - | ty::TypingMode::Analysis { defining_opaque_types: _ } => false, + | ty::TypingMode::Analysis { .. } + | ty::TypingMode::PostBorrowckAnalysis { .. } => false, ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), } }; diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 13ad505bc048..a892b88c2c63 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -63,6 +63,12 @@ pub enum TypingMode { /// } /// ``` Analysis { defining_opaque_types: I::DefiningOpaqueTypes }, + /// Any analysis after borrowck for a given body should be able to use all the + /// hidden types defined by borrowck, without being able to define any new ones. + /// + /// This is currently only used by the new solver, but should be implemented in + /// the old solver as well. + PostBorrowckAnalysis { defined_opaque_types: I::DefiningOpaqueTypes }, /// After analysis, mostly during codegen and MIR optimizations, we're able to /// reveal all opaque types. As the concrete type should *never* be observable /// directly by the user, this should not be used by checks which may expose @@ -85,6 +91,12 @@ impl TypingMode { pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode { TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } } + + pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode { + TypingMode::PostBorrowckAnalysis { + defined_opaque_types: cx.opaque_types_defined_by(body_def_id), + } + } } pub trait InferCtxtLike: Sized { @@ -126,6 +138,7 @@ pub trait InferCtxtLike: Sized { vid: ty::RegionVid, ) -> ::Region; + fn next_region_infer(&self) -> ::Region; fn next_ty_infer(&self) -> ::Ty; fn next_const_infer(&self) -> ::Const; fn fresh_args_for_item( diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index c8abfee314e2..d49f8d3093db 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -136,9 +136,9 @@ where relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); Ok(a) } - TypingMode::Analysis { .. } | TypingMode::PostAnalysis => { - structurally_relate_tys(relation, a, b) - } + TypingMode::Analysis { .. } + | TypingMode::PostBorrowckAnalysis { .. } + | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b), } } diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr new file mode 100644 index 000000000000..9a28dc093c1b --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr @@ -0,0 +1,34 @@ +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:19:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:27:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:36:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: unconstrained opaque type + --> $DIR/no-define-in-wf-check.rs:47:18 + | +LL | type Tait1 = impl Sized; + | ^^^^^^^^^^ + | + = note: `Tait1` must be used in combination with a concrete type within the same module + +error: aborting due to 4 previous errors + diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs new file mode 100644 index 000000000000..dd6df097da1b --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs @@ -0,0 +1,66 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +// Regression test for trait-system-refactor-initiative#106. We previously +// tried to define other opaques while checking that opaques are well-formed. +// +// This resulted in undesirable ambiguity + +#![feature(type_alias_impl_trait)] + +mod ex0 { + fn foo() -> (impl Sized, impl Sized) { + ((), ()) + } +} +mod ex1 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + fn foo(x: Tait1) -> impl Sized { + let () = x; + } +} + +mod ex2 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + type Tait2 = impl Sized; + fn foo(x: Tait1) -> Tait2 { + let () = x; + } +} + +mod ex3 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + trait Something {} + impl Something for T {} + type Tait2 = impl Something; + fn foo(x: Tait1) -> Tait2 { + let () = x; + } +} + +mod ex4 { + type Tait1 = impl Sized; + //[current]~^ ERROR unconstrained opaque type + trait Trait { + type Assoc; + } + + impl Trait for T { + type Assoc = T; + } + + // ambiguity when checking that `Tait2` is wf + // + // ambiguity proving `(): Trait`. + type Tait2 = impl Trait<(), Assoc = impl Trait>; + fn foo(x: Tait1) -> Tait2 { + let () = x; + } +} + +fn main() {} From 43c12ed4a4af048a18180717305381d72df90ef6 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Thu, 28 Nov 2024 12:17:57 +0100 Subject: [PATCH 155/330] Bump `ruzstd` to 0.7.3 This fixes the yet to be published advisory for uninit/out-of-bounds memory reads and potential exposure. See https://github.com/rustsec/advisory-db/pull/2147 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29176a3ae8e2..144e7b4e4b32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4711,9 +4711,9 @@ checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ruzstd" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3938e133aac070997ddc684d4b393777d293ba170f2988c8fd5ea2ad4ce21" +checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" dependencies = [ "twox-hash", ] From 467e200cd5c032489b9bc87284f2a8fbfb922fc3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 25 Nov 2024 18:17:23 +0100 Subject: [PATCH 156/330] add tests --- ...=> const_arg_trivial_macro_expansion-1.rs} | 287 +++++++++++++++--- ...onst_arg_trivial_macro_expansion-3-pass.rs | 46 +++ .../const_arg_trivial_macro_expansion-4.rs | 18 ++ ...const_arg_trivial_macro_expansion-4.stderr | 37 +++ 4 files changed, 352 insertions(+), 36 deletions(-) rename tests/ui/const-generics/early/{const_arg_trivial_macro_expansion.rs => const_arg_trivial_macro_expansion-1.rs} (56%) create mode 100644 tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs create mode 100644 tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs create mode 100644 tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-1.rs similarity index 56% rename from tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs rename to tests/ui/const-generics/early/const_arg_trivial_macro_expansion-1.rs index 2fdd703ab6f3..5ea445520f1a 100644 --- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-1.rs @@ -85,6 +85,14 @@ macro_rules! braced_braced_expr { () => {{ braced_expr!() }}; } +macro_rules! closure { + () => { |()| () }; +} + +macro_rules! empty { + () => {}; +} + #[rustfmt::skip] mod array_paren_call { // Arrays where the expanded result is a `Res::Err` @@ -128,6 +136,14 @@ mod array_paren_call { fn array_33() -> [(); braced_expr!()] { loop {} } fn array_34() -> [(); { unbraced_expr!() }] { loop {} } fn array_35() -> [(); { braced_expr!() }] { loop {} } + + // Arrays whose expanded form contains a nested definition + fn array_36() -> [(); closure!()] { loop {} } + fn array_37() -> [(); { closure!() }] { loop {} } + + // Arrays whose macro expansion is empty + fn array_38() -> [(); empty!()] { loop {} } + fn array_39() -> [(); { empty!() }] { loop {} } } #[rustfmt::skip] @@ -173,6 +189,14 @@ mod array_brace_call { fn array_33() -> [(); braced_expr!{}] { loop {} } fn array_34() -> [(); { unbraced_expr!{} }] { loop {} } fn array_35() -> [(); { braced_expr!{} }] { loop {} } + + // Arrays whose expanded form contains a nested definition + fn array_36() -> [(); closure!{}] { loop {} } + fn array_37() -> [(); { closure!{} }] { loop {} } + + // Arrays whose macro expansion is empty + fn array_38() -> [(); empty!{}] { loop {} } + fn array_39() -> [(); { empty!{} }] { loop {} } } #[rustfmt::skip] @@ -218,6 +242,14 @@ mod array_square_call { fn array_33() -> [(); braced_expr![]] { loop {} } fn array_34() -> [(); { unbraced_expr![] }] { loop {} } fn array_35() -> [(); { braced_expr![] }] { loop {} } + + // Arrays whose expanded form contains a nested definition + fn array_36() -> [(); closure![]] { loop {} } + fn array_37() -> [(); { closure![] }] { loop {} } + + // Arrays whose macro expansion is empty + fn array_38() -> [(); empty![]] { loop {} } + fn array_39() -> [(); { empty![] }] { loop {} } } struct Foo; @@ -255,18 +287,26 @@ mod adt_paren_call { fn adt_23() -> Foo<{ braced_ident!() }> { loop {} } // An ADT where the expanded result is a complex expr - fn array_24() -> Foo { loop {} } - fn array_25() -> Foo { loop {} } - fn array_26() -> Foo { loop {} } - fn array_27() -> Foo { loop {} } - fn array_28() -> Foo<{ unbraced_unbraced_expr!() }> { loop {} } - fn array_29() -> Foo<{ braced_unbraced_expr!() }> { loop {} } - fn array_30() -> Foo<{ unbraced_braced_expr!() }> { loop {} } - fn array_31() -> Foo<{ braced_braced_expr!() }> { loop {} } - fn array_32() -> Foo { loop {} } - fn array_33() -> Foo { loop {} } - fn array_34() -> Foo<{ unbraced_expr!() }> { loop {} } - fn array_35() -> Foo<{ braced_expr!() }> { loop {} } + fn adt_24() -> Foo { loop {} } + fn adt_25() -> Foo { loop {} } + fn adt_26() -> Foo { loop {} } + fn adt_27() -> Foo { loop {} } + fn adt_28() -> Foo<{ unbraced_unbraced_expr!() }> { loop {} } + fn adt_29() -> Foo<{ braced_unbraced_expr!() }> { loop {} } + fn adt_30() -> Foo<{ unbraced_braced_expr!() }> { loop {} } + fn adt_31() -> Foo<{ braced_braced_expr!() }> { loop {} } + fn adt_32() -> Foo { loop {} } + fn adt_33() -> Foo { loop {} } + fn adt_34() -> Foo<{ unbraced_expr!() }> { loop {} } + fn adt_35() -> Foo<{ braced_expr!() }> { loop {} } + + // An ADT whose expanded form contains a nested definition + fn adt_36() -> Foo { loop {} } + fn adt_37() -> Foo<{ closure!() }> { loop {} } + + // An ADT whose macro expansion is empty + fn adt_38() -> Foo { loop {} } + fn adt_39() -> Foo<{ empty!() }> { loop {} } } #[rustfmt::skip] @@ -302,18 +342,26 @@ mod adt_brace_call { fn adt_23() -> Foo<{ braced_ident!{} }> { loop {} } // An ADT where the expanded result is a complex expr - fn array_24() -> Foo { loop {} } - fn array_25() -> Foo { loop {} } - fn array_26() -> Foo { loop {} } - fn array_27() -> Foo { loop {} } - fn array_28() -> Foo<{ unbraced_unbraced_expr!{} }> { loop {} } - fn array_29() -> Foo<{ braced_unbraced_expr!{} }> { loop {} } - fn array_30() -> Foo<{ unbraced_braced_expr!{} }> { loop {} } - fn array_31() -> Foo<{ braced_braced_expr!{} }> { loop {} } - fn array_32() -> Foo { loop {} } - fn array_33() -> Foo { loop {} } - fn array_34() -> Foo<{ unbraced_expr!{} }> { loop {} } - fn array_35() -> Foo<{ braced_expr!{} }> { loop {} } + fn adt_24() -> Foo { loop {} } + fn adt_25() -> Foo { loop {} } + fn adt_26() -> Foo { loop {} } + fn adt_27() -> Foo { loop {} } + fn adt_28() -> Foo<{ unbraced_unbraced_expr!{} }> { loop {} } + fn adt_29() -> Foo<{ braced_unbraced_expr!{} }> { loop {} } + fn adt_30() -> Foo<{ unbraced_braced_expr!{} }> { loop {} } + fn adt_31() -> Foo<{ braced_braced_expr!{} }> { loop {} } + fn adt_32() -> Foo { loop {} } + fn adt_33() -> Foo { loop {} } + fn adt_34() -> Foo<{ unbraced_expr!{} }> { loop {} } + fn adt_35() -> Foo<{ braced_expr!{} }> { loop {} } + + // An ADT whose expanded form contains a nested definition + fn adt_36() -> Foo { loop {} } + fn adt_37() -> Foo<{ closure!{} }> { loop {} } + + // An ADT whose macro expansion is empty + fn adt_38() -> Foo { loop {} } + fn adt_39() -> Foo<{ empty!{} }> { loop {} } } #[rustfmt::skip] @@ -349,18 +397,185 @@ mod adt_square_call { fn adt_23() -> Foo<{ braced_ident![] }> { loop {} } // An ADT where the expanded result is a complex expr - fn array_24() -> Foo { loop {} } - fn array_25() -> Foo { loop {} } - fn array_26() -> Foo { loop {} } - fn array_27() -> Foo { loop {} } - fn array_28() -> Foo<{ unbraced_unbraced_expr![] }> { loop {} } - fn array_29() -> Foo<{ braced_unbraced_expr![] }> { loop {} } - fn array_30() -> Foo<{ unbraced_braced_expr![] }> { loop {} } - fn array_31() -> Foo<{ braced_braced_expr![] }> { loop {} } - fn array_32() -> Foo { loop {} } - fn array_33() -> Foo { loop {} } - fn array_34() -> Foo<{ unbraced_expr![] }> { loop {} } - fn array_35() -> Foo<{ braced_expr![] }> { loop {} } + fn adt_24() -> Foo { loop {} } + fn adt_25() -> Foo { loop {} } + fn adt_26() -> Foo { loop {} } + fn adt_27() -> Foo { loop {} } + fn adt_28() -> Foo<{ unbraced_unbraced_expr![] }> { loop {} } + fn adt_29() -> Foo<{ braced_unbraced_expr![] }> { loop {} } + fn adt_30() -> Foo<{ unbraced_braced_expr![] }> { loop {} } + fn adt_31() -> Foo<{ braced_braced_expr![] }> { loop {} } + fn adt_32() -> Foo { loop {} } + fn adt_33() -> Foo { loop {} } + fn adt_34() -> Foo<{ unbraced_expr![] }> { loop {} } + fn adt_35() -> Foo<{ braced_expr![] }> { loop {} } + + // An ADT whose expanded form contains a nested definition + fn adt_36() -> Foo { loop {} } + fn adt_37() -> Foo<{ closure![] }> { loop {} } + + // An ADT whose macro expansion is empty + fn adt_38() -> Foo { loop {} } + fn adt_39() -> Foo<{ empty![] }> { loop {} } +} + +#[rustfmt::skip] +mod repeat_paren_call { + // A repeat expr where the expanded result is a `Res::Err` + fn repeat_0() { [(); unbraced_unbraced_ident!()]; } + fn repeat_1() { [(); braced_unbraced_ident!()]; } + fn repeat_2() { [(); unbraced_braced_ident!()]; } + fn repeat_3() { [(); braced_braced_ident!()]; } + fn repeat_4() { [(); { unbraced_unbraced_ident!() }]; } + fn repeat_5() { [(); { braced_unbraced_ident!() }]; } + fn repeat_6() { [(); { unbraced_braced_ident!() }]; } + fn repeat_7() { [(); { braced_braced_ident!() }]; } + fn repeat_8() { [(); unbraced_ident!()]; } + fn repeat_9() { [(); braced_ident!()]; } + fn repeat_10() { [(); { unbraced_ident!() }]; } + fn repeat_11() { [(); { braced_ident!() }]; } + + // A repeat expr where the expanded result is a `Res::ConstParam` + fn repeat_12() { [(); unbraced_unbraced_ident!()]; } + fn repeat_13() { [(); braced_unbraced_ident!()]; } + fn repeat_14() { [(); unbraced_braced_ident!()]; } + fn repeat_15() { [(); braced_braced_ident!()]; } + fn repeat_16() { [(); { unbraced_unbraced_ident!() }]; } + fn repeat_17() { [(); { braced_unbraced_ident!() }]; } + fn repeat_18() { [(); { unbraced_braced_ident!() }]; } + fn repeat_19() { [(); { braced_braced_ident!() }]; } + fn repeat_20() { [(); unbraced_ident!()]; } + fn repeat_21() { [(); braced_ident!()]; } + fn repeat_22() { [(); { unbraced_ident!() }]; } + fn repeat_23() { [(); { braced_ident!() }]; } + + // A repeat expr where the expanded result is a complex expr + fn repeat_24() { [(); unbraced_unbraced_expr!()]; } + fn repeat_25() { [(); braced_unbraced_expr!()]; } + fn repeat_26() { [(); unbraced_braced_expr!()]; } + fn repeat_27() { [(); braced_braced_expr!()]; } + fn repeat_28() { [(); { unbraced_unbraced_expr!() }]; } + fn repeat_29() { [(); { braced_unbraced_expr!() }]; } + fn repeat_30() { [(); { unbraced_braced_expr!() }]; } + fn repeat_31() { [(); { braced_braced_expr!() }]; } + fn repeat_32() { [(); unbraced_expr!()]; } + fn repeat_33() { [(); braced_expr!()]; } + fn repeat_34() { [(); { unbraced_expr!() }]; } + fn repeat_35() { [(); { braced_expr!() }]; } + + // A repeat expr whose expanded form contains a nested definition + fn repeat_36() { [(); closure!()] } + fn repeat_37() { [(); { closure!() }] } + + // A repeat expr whose macro expansion is empty + fn repeat_38() { [(); empty!()] } + fn repeat_39() { [(); { empty!() }] } +} + +#[rustfmt::skip] +mod repeat_brace_call { + // A repeat expr where the expanded result is a `Res::Err` + fn repeat_0() { [(); unbraced_unbraced_ident!{}]; } + fn repeat_1() { [(); braced_unbraced_ident!{}]; } + fn repeat_2() { [(); unbraced_braced_ident!{}]; } + fn repeat_3() { [(); braced_braced_ident!{}]; } + fn repeat_4() { [(); { unbraced_unbraced_ident!{} }]; } + fn repeat_5() { [(); { braced_unbraced_ident!{} }]; } + fn repeat_6() { [(); { unbraced_braced_ident!{} }]; } + fn repeat_7() { [(); { braced_braced_ident!{} }]; } + fn repeat_8() { [(); unbraced_ident!{}]; } + fn repeat_9() { [(); braced_ident!{}]; } + fn repeat_10() { [(); { unbraced_ident!{} }]; } + fn repeat_11() { [(); { braced_ident!{} }]; } + + // A repeat expr where the expanded result is a `Res::ConstParam` + fn repeat_12() { [(); unbraced_unbraced_ident!{}]; } + fn repeat_13() { [(); braced_unbraced_ident!{}]; } + fn repeat_14() { [(); unbraced_braced_ident!{}]; } + fn repeat_15() { [(); braced_braced_ident!{}]; } + fn repeat_16() { [(); { unbraced_unbraced_ident!{} }]; } + fn repeat_17() { [(); { braced_unbraced_ident!{} }]; } + fn repeat_18() { [(); { unbraced_braced_ident!{} }]; } + fn repeat_19() { [(); { braced_braced_ident!{} }]; } + fn repeat_20() { [(); unbraced_ident!{}]; } + fn repeat_21() { [(); braced_ident!{}]; } + fn repeat_22() { [(); { unbraced_ident!{} }]; } + fn repeat_23() { [(); { braced_ident!{} }]; } + + // A repeat expr where the expanded result is a complex expr + fn repeat_24() { [(); unbraced_unbraced_expr!{}]; } + fn repeat_25() { [(); braced_unbraced_expr!{}]; } + fn repeat_26() { [(); unbraced_braced_expr!{}]; } + fn repeat_27() { [(); braced_braced_expr!{}]; } + fn repeat_28() { [(); { unbraced_unbraced_expr!{} }]; } + fn repeat_29() { [(); { braced_unbraced_expr!{} }]; } + fn repeat_30() { [(); { unbraced_braced_expr!{} }]; } + fn repeat_31() { [(); { braced_braced_expr!{} }]; } + fn repeat_32() { [(); unbraced_expr!{}]; } + fn repeat_33() { [(); braced_expr!{}]; } + fn repeat_34() { [(); { unbraced_expr!{} }]; } + fn repeat_35() { [(); { braced_expr!{} }]; } + + // A repeat expr whose expanded form contains a nested definition + fn repeat_36() { [(); closure!{}] } + fn repeat_37() { [(); { closure!{} }] } + + // A repeat expr whose macro expansion is empty + fn repeat_38() { [(); empty!{}] } + fn repeat_39() { [(); { empty!{} }] } +} + +#[rustfmt::skip] +mod repeat_square_call { + // A repeat expr where the expanded result is a `Res::Err` + fn repeat_0() { [(); unbraced_unbraced_ident![]]; } + fn repeat_1() { [(); braced_unbraced_ident![]]; } + fn repeat_2() { [(); unbraced_braced_ident![]]; } + fn repeat_3() { [(); braced_braced_ident![]]; } + fn repeat_4() { [(); { unbraced_unbraced_ident![] }]; } + fn repeat_5() { [(); { braced_unbraced_ident![] }]; } + fn repeat_6() { [(); { unbraced_braced_ident![] }]; } + fn repeat_7() { [(); { braced_braced_ident![] }]; } + fn repeat_8() { [(); unbraced_ident![]]; } + fn repeat_9() { [(); braced_ident![]]; } + fn repeat_10() { [(); { unbraced_ident![] }]; } + fn repeat_11() { [(); { braced_ident![] }]; } + + // A repeat expr where the expanded result is a `Res::ConstParam` + fn repeat_12() { [(); unbraced_unbraced_ident![]]; } + fn repeat_13() { [(); braced_unbraced_ident![]]; } + fn repeat_14() { [(); unbraced_braced_ident![]]; } + fn repeat_15() { [(); braced_braced_ident![]]; } + fn repeat_16() { [(); { unbraced_unbraced_ident![] }]; } + fn repeat_17() { [(); { braced_unbraced_ident![] }]; } + fn repeat_18() { [(); { unbraced_braced_ident![] }]; } + fn repeat_19() { [(); { braced_braced_ident![] }]; } + fn repeat_20() { [(); unbraced_ident![]]; } + fn repeat_21() { [(); braced_ident![]]; } + fn repeat_22() { [(); { unbraced_ident![] }]; } + fn repeat_23() { [(); { braced_ident![] }]; } + + // A repeat expr where the expanded result is a complex expr + fn repeat_24() { [(); unbraced_unbraced_expr![]]; } + fn repeat_25() { [(); braced_unbraced_expr![]]; } + fn repeat_26() { [(); unbraced_braced_expr![]]; } + fn repeat_27() { [(); braced_braced_expr![]]; } + fn repeat_28() { [(); { unbraced_unbraced_expr![] }]; } + fn repeat_29() { [(); { braced_unbraced_expr![] }]; } + fn repeat_30() { [(); { unbraced_braced_expr![] }]; } + fn repeat_31() { [(); { braced_braced_expr![] }]; } + fn repeat_32() { [(); unbraced_expr![]]; } + fn repeat_33() { [(); braced_expr![]]; } + fn repeat_34() { [(); { unbraced_expr![] }]; } + fn repeat_35() { [(); { braced_expr![] }]; } + + // A repeat expr whose expanded form contains a nested definition + fn repeat_36() { [(); closure![]] } + fn repeat_37() { [(); { closure![] }] } + + // A repeat expr whose macro expansion is empty + fn repeat_38() { [(); empty![]] } + fn repeat_39() { [(); { empty![] }] } } fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs new file mode 100644 index 000000000000..fb6190324c6c --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-3-pass.rs @@ -0,0 +1,46 @@ +// Additional checks for macro expansion in const args + +//@ check-pass + +macro_rules! closure { + () => { |()| () }; +} + +macro_rules! indir_semi { + ($nested:ident) => { $nested!(); }; +} + +macro_rules! indir { + ($nested:ident) => { $nested!() }; +} + +macro_rules! empty { + () => {}; +} + +macro_rules! arg { + () => { N }; +} + +struct Adt; + +fn array1() -> [(); { closure!(); 0 }] { loop {} } +fn array2() -> [(); { indir!(closure); 0}] { loop {} } +fn array3() -> [(); { indir_semi!{ closure } 0 }] { loop {} } +fn array4() -> [(); { indir!{ empty } arg!{} }] { loop {} } +fn array5() -> [(); { empty!{} arg!() }] { loop {} } +fn array6() -> [(); { empty!{} N }] { loop {} } +fn array7() -> [(); { arg!{} empty!{} }] { loop {} } +fn array8() -> [(); { empty!{} arg!{} empty!{} }] { loop {} } + +fn adt1() -> Adt<{ closure!(); 0 }> { loop {} } +fn adt2() -> Adt<{ indir!(closure); 0}> { loop {} } +fn adt3() -> Adt<{ indir_semi!{ closure } 0 }> { loop {} } +fn adt4() -> Adt<{ indir!{ empty } arg!{} }> { loop {} } +fn adt5() -> Adt<{ empty!{} arg!() }> { loop {} } +fn adt6() -> Adt<{ empty!{} N }> { loop {} } +fn adt7() -> Adt<{ arg!{} empty!{} }> { loop {} } +fn adt8() -> Adt<{ empty!{} arg!{} empty!{} }> { loop {} } + + +fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs new file mode 100644 index 000000000000..3353d6cf2da3 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.rs @@ -0,0 +1,18 @@ +macro_rules! empty { + () => {}; +} + +macro_rules! arg { + () => { + N + //~^ ERROR generic parameters may not be used in const operations + //~| ERROR generic parameters may not be used in const operations + }; +} + +struct Foo; +fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } +fn bar() -> [(); { empty!{}; N }] { loop {} } +//~^ ERROR generic parameters may not be used in const operations + +fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr new file mode 100644 index 000000000000..4722968b2034 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr @@ -0,0 +1,37 @@ +error: generic parameters may not be used in const operations + --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 + | +LL | N + | ^ cannot perform const operation using `N` +... +LL | fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } + | ------ in this macro invocation + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: this error originates in the macro `arg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 + | +LL | N + | ^ cannot perform const operation using `N` +... +LL | fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } + | ------ in this macro invocation + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: this error originates in the macro `arg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: generic parameters may not be used in const operations + --> $DIR/const_arg_trivial_macro_expansion-4.rs:15:46 + | +LL | fn bar() -> [(); { empty!{}; N }] { loop {} } + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 3 previous errors + From 94131bd0a8e125d6d32034aadf010d9250f83867 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 25 Nov 2024 18:42:10 +0100 Subject: [PATCH 157/330] always create `DefId`s when lowering anon-consts --- compiler/rustc_ast/src/ast.rs | 7 +- compiler/rustc_ast_lowering/src/asm.rs | 17 +- compiler/rustc_ast_lowering/src/expr.rs | 8 +- compiler/rustc_ast_lowering/src/lib.rs | 19 +-- compiler/rustc_metadata/src/rmeta/encoder.rs | 14 ++ compiler/rustc_resolve/src/def_collector.rs | 158 +++---------------- compiler/rustc_resolve/src/late.rs | 4 +- compiler/rustc_resolve/src/lib.rs | 13 -- tests/ui/consts/issue-36163.stderr | 6 +- 9 files changed, 61 insertions(+), 185 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ecb6ef5a2a64..56b20e0ad893 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1184,14 +1184,15 @@ pub struct Expr { } impl Expr { - /// Is this expr either `N`, or `{ N }`. + /// Could this expr be either `N`, or `{ N }`, where `N` is a const parameter. /// /// If this is not the case, name resolution does not resolve `N` when using /// `min_const_generics` as more complex expressions are not supported. /// /// Does not ensure that the path resolves to a const param, the caller should check this. - pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool { - let this = if strip_identity_block { self.maybe_unwrap_block() } else { self }; + /// This also does not consider macros, so it's only correct after macro-expansion. + pub fn is_potential_trivial_const_arg(&self) -> bool { + let this = self.maybe_unwrap_block(); if let ExprKind::Path(None, path) = &this.kind && path.is_potential_trivial_const_arg() diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index ff803e509973..cc0171d74a41 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -224,16 +224,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Wrap the expression in an AnonConst. let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); - // HACK(min_generic_const_args): see lower_anon_const - if !expr.is_potential_trivial_const_arg(true) { - self.create_def( - parent_def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - *op_sp, - ); - } + self.create_def( + parent_def_id, + node_id, + kw::Empty, + DefKind::AnonConst, + *op_sp, + ); let anon_const = AnonConst { id: node_id, value: P(expr) }; hir::InlineAsmOperand::SymFn { anon_const: self.lower_anon_const_to_anon_const(&anon_const), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3af29838b72c..dafed4f906aa 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -454,13 +454,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if legacy_args_idx.contains(&idx) { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); - - // HACK(min_generic_const_args): see lower_anon_const - if !arg.is_potential_trivial_const_arg(true) { - // Add a definition for the in-band const def. - self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); - } - + self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); let mut visitor = WillCreateDefIdsVisitor {}; let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { AstP(Expr { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dae816663e00..ea2e77fb9ddb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2159,7 +2159,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, ); - return ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) }; + return ConstArg { + hir_id: self.lower_node_id(anon.id), + kind: hir::ConstArgKind::Path(qpath), + }; } let lowered_anon = self.lower_anon_const_to_anon_const(anon); @@ -2169,20 +2172,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - if c.value.is_potential_trivial_const_arg(true) { - // HACK(min_generic_const_args): see DefCollector::visit_anon_const - // Over there, we guess if this is a bare param and only create a def if - // we think it's not. However we may can guess wrong (see there for example) - // in which case we have to create the def here. - self.create_def( - self.current_def_id_parent, - c.id, - kw::Empty, - DefKind::AnonConst, - c.value.span, - ); - } - self.arena.alloc(self.with_new_scopes(c.value.span, |this| { let def_id = this.local_def_id(c.id); let hir_id = this.lower_node_id(c.id); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index dd149af52052..068a5d31a8e1 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1383,6 +1383,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); self.tables.def_kind.set_some(def_id.index, def_kind); + + // The `DefCollector` will sometimes create unnecessary `DefId`s + // for trivial const arguments which are directly lowered to + // `ConstArgKind::Path`. We never actually access this `DefId` + // anywhere so we don't need to encode it for other crates. + if def_kind == DefKind::AnonConst + && matches!( + tcx.hir_node_by_def_id(local_id), + hir::Node::ConstArg(hir::ConstArg { kind: hir::ConstArgKind::Path(..), .. }) + ) + { + continue; + } + if should_encode_span(def_kind) { let def_span = tcx.def_span(local_id); record!(self.tables.def_span[def_id] <- def_span); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 7536869e2fe2..664928425812 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -12,23 +12,16 @@ use rustc_span::hygiene::LocalExpnId; use rustc_span::symbol::{Symbol, kw, sym}; use tracing::debug; -use crate::{ImplTraitContext, InvocationParent, PendingAnonConstInfo, Resolver}; +use crate::{ImplTraitContext, InvocationParent, Resolver}; pub(crate) fn collect_definitions( resolver: &mut Resolver<'_, '_>, fragment: &AstFragment, expansion: LocalExpnId, ) { - let InvocationParent { parent_def, pending_anon_const_info, impl_trait_context, in_attr } = + let InvocationParent { parent_def, impl_trait_context, in_attr } = resolver.invocation_parents[&expansion]; - let mut visitor = DefCollector { - resolver, - parent_def, - pending_anon_const_info, - expansion, - impl_trait_context, - in_attr, - }; + let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr }; fragment.visit_with(&mut visitor); } @@ -36,13 +29,6 @@ pub(crate) fn collect_definitions( struct DefCollector<'a, 'ra, 'tcx> { resolver: &'a mut Resolver<'ra, 'tcx>, parent_def: LocalDefId, - /// If we have an anon const that consists of a macro invocation, e.g. `Foo<{ m!() }>`, - /// we need to wait until we know what the macro expands to before we create the def for - /// the anon const. That's because we lower some anon consts into `hir::ConstArgKind::Path`, - /// which don't have defs. - /// - /// See `Self::visit_anon_const()`. - pending_anon_const_info: Option, impl_trait_context: ImplTraitContext, in_attr: bool, expansion: LocalExpnId, @@ -110,61 +96,13 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { fn visit_macro_invoc(&mut self, id: NodeId) { let id = id.placeholder_to_expn_id(); - let pending_anon_const_info = self.pending_anon_const_info.take(); let old_parent = self.resolver.invocation_parents.insert(id, InvocationParent { parent_def: self.parent_def, - pending_anon_const_info, impl_trait_context: self.impl_trait_context, in_attr: self.in_attr, }); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } - - /// Determines whether the const argument `AnonConst` is a simple macro call, optionally - /// surrounded with braces. - /// - /// If this const argument *is* a trivial macro call then the id for the macro call is - /// returned along with the information required to build the anon const's def if - /// the macro call expands to a non-trivial expression. - fn is_const_arg_trivial_macro_expansion( - &self, - anon_const: &'a AnonConst, - ) -> Option<(PendingAnonConstInfo, NodeId)> { - anon_const.value.optionally_braced_mac_call(false).map(|(block_was_stripped, id)| { - ( - PendingAnonConstInfo { - id: anon_const.id, - span: anon_const.value.span, - block_was_stripped, - }, - id, - ) - }) - } - - /// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes - /// surrounded with braces if a set of braces has not already been entered. This is required - /// as `{ N }` is treated as equivalent to a bare parameter `N` whereas `{{ N }}` is treated as - /// a real block expression and is lowered to an anonymous constant which is not allowed to use - /// generic parameters. - /// - /// If this expression is a trivial macro call then the id for the macro call is - /// returned along with the information required to build the anon const's def if - /// the macro call expands to a non-trivial expression. - fn is_const_arg_sub_expr_trivial_macro_expansion( - &self, - const_arg_sub_expr: &'a Expr, - ) -> Option<(PendingAnonConstInfo, NodeId)> { - let pending_anon = self.pending_anon_const_info.unwrap_or_else(|| - panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"), - ); - - const_arg_sub_expr.optionally_braced_mac_call(pending_anon.block_was_stripped).map( - |(block_was_stripped, id)| { - (PendingAnonConstInfo { block_was_stripped, ..pending_anon }, id) - }, - ) - } } impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { @@ -376,78 +314,34 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - // HACK(min_generic_const_args): don't create defs for anon consts if we think they will - // later be turned into ConstArgKind::Path's. because this is before resolve is done, we - // may accidentally identify a construction of a unit struct as a param and not create a - // def. we'll then create a def later in ast lowering in this case. the parent of nested - // items will be messed up, but that's ok because there can't be any if we're just looking - // for bare idents. - - if let Some((pending_anon, macro_invoc)) = - self.is_const_arg_trivial_macro_expansion(constant) - { - self.pending_anon_const_info = Some(pending_anon); - return self.visit_macro_invoc(macro_invoc); - } else if constant.value.is_potential_trivial_const_arg(true) { - return visit::walk_anon_const(self, constant); - } - - let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + let parent = + self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); + self.with_parent(parent, |this| visit::walk_anon_const(this, constant)); } fn visit_expr(&mut self, expr: &'a Expr) { - // If we're visiting the expression of a const argument that was a macro call then - // check if it is *still* unknown whether it is a trivial const arg or not. If so - // recurse into the macro call and delay creating the anon const def until expansion. - if self.pending_anon_const_info.is_some() - && let Some((pending_anon, macro_invoc)) = - self.is_const_arg_sub_expr_trivial_macro_expansion(expr) - { - self.pending_anon_const_info = Some(pending_anon); - return self.visit_macro_invoc(macro_invoc); - } - - // See self.pending_anon_const_info for explanation - let parent_def = self - .pending_anon_const_info - .take() - // If we already stripped away a set of braces then do not do it again when determining - // if the macro expanded to a trivial const arg. This arises in cases such as: - // `Foo<{ bar!() }>` where `bar!()` expands to `{ N }`. This should not be considered a - // trivial const argument even though `{ N }` by itself *is*. - .filter(|pending_anon| { - !expr.is_potential_trivial_const_arg(!pending_anon.block_was_stripped) - }) - .map(|pending_anon| { - self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span) - }) - .unwrap_or(self.parent_def); - - self.with_parent(parent_def, |this| { - let parent_def = match expr.kind { - ExprKind::MacCall(..) => return this.visit_macro_invoc(expr.id), - ExprKind::Closure(..) | ExprKind::Gen(..) => { - this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) + let parent_def = match expr.kind { + ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), + ExprKind::Closure(..) | ExprKind::Gen(..) => { + self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) + } + ExprKind::ConstBlock(ref constant) => { + for attr in &expr.attrs { + visit::walk_attribute(self, attr); } - ExprKind::ConstBlock(ref constant) => { - for attr in &expr.attrs { - visit::walk_attribute(this, attr); - } - let def = this.create_def( - constant.id, - kw::Empty, - DefKind::InlineConst, - constant.value.span, - ); - this.with_parent(def, |this| visit::walk_anon_const(this, constant)); - return; - } - _ => this.parent_def, - }; + let def = self.create_def( + constant.id, + kw::Empty, + DefKind::InlineConst, + constant.value.span, + ); + self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + return; + } + _ => self.parent_def, + }; - this.with_parent(parent_def, |this| visit::walk_expr(this, expr)) - }) + self.with_parent(parent_def, |this| visit::walk_expr(this, expr)) } fn visit_ty(&mut self, ty: &'a Ty) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 60815ffdb1b9..fc92dc8b4ed7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4521,7 +4521,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_anon_const_manual( - constant.value.is_potential_trivial_const_arg(true), + constant.value.is_potential_trivial_const_arg(), anon_const_kind, |this| this.resolve_expr(&constant.value, None), ) @@ -4685,7 +4685,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // that is how they will be later lowered to HIR. if const_args.contains(&idx) { self.resolve_anon_const_manual( - argument.is_potential_trivial_const_arg(true), + argument.is_potential_trivial_const_arg(), AnonConstKind::ConstArg(IsRepeatExpr::No), |this| this.resolve_expr(argument, None), ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e382295b8f6d..094871ad2687 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -174,7 +174,6 @@ impl<'ra> ParentScope<'ra> { #[derive(Copy, Debug, Clone)] struct InvocationParent { parent_def: LocalDefId, - pending_anon_const_info: Option, impl_trait_context: ImplTraitContext, in_attr: bool, } @@ -182,23 +181,11 @@ struct InvocationParent { impl InvocationParent { const ROOT: Self = Self { parent_def: CRATE_DEF_ID, - pending_anon_const_info: None, impl_trait_context: ImplTraitContext::Existential, in_attr: false, }; } -#[derive(Copy, Debug, Clone)] -struct PendingAnonConstInfo { - // A const arg is only a "trivial" const arg if it has at *most* one set of braces - // around the argument. We track whether we have stripped an outter brace so that - // if a macro expands to a braced expression *and* the macro was itself inside of - // some braces then we can consider it to be a non-trivial const argument. - block_was_stripped: bool, - id: NodeId, - span: Span, -} - #[derive(Copy, Debug, Clone)] enum ImplTraitContext { Existential, diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 52d3e003f0ac..8a7a0981f415 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const-evaluating + checking `Foo::{constant#0}`... +note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... --> $DIR/issue-36163.rs:4:9 | LL | B = A, @@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle + = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-36163.rs:3:1 | From 23ba2d11944a2eb538dca4583ff2465ca8da37a3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 25 Nov 2024 18:43:34 +0100 Subject: [PATCH 158/330] ast_lowering: rm separate `def_id_parent` no longer necessary as we now always create a ` DefId` for anon-consts --- compiler/rustc_ast_lowering/src/asm.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 100 +++++++++++------------- compiler/rustc_ast_lowering/src/lib.rs | 54 ++++--------- 3 files changed, 61 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index cc0171d74a41..17bcff774b84 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -222,7 +222,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; // Wrap the expression in an AnonConst. - let parent_def_id = self.current_def_id_parent; + let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); self.create_def( parent_def_id, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index dafed4f906aa..3032042ff9fe 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -109,9 +109,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ConstBlock { def_id, hir_id: this.lower_node_id(c.id), - body: this.with_def_id_parent(def_id, |this| { - this.lower_const_body(c.value.span, Some(&c.value)) - }), + body: this.lower_const_body(c.value.span, Some(&c.value)), } }); hir::ExprKind::ConstBlock(c) @@ -452,7 +450,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generic_args = ThinVec::new(); for (idx, arg) in args.iter().cloned().enumerate() { if legacy_args_idx.contains(&idx) { - let parent_def_id = self.current_def_id_parent; + let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); let mut visitor = WillCreateDefIdsVisitor {}; @@ -753,19 +751,17 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime_elision_allowed: false, }); - let body = self.with_def_id_parent(closure_def_id, move |this| { - this.lower_body(move |this| { - this.coroutine_kind = Some(coroutine_kind); + let body = self.lower_body(move |this| { + this.coroutine_kind = Some(coroutine_kind); - let old_ctx = this.task_context; - if task_context.is_some() { - this.task_context = task_context; - } - let res = body(this); - this.task_context = old_ctx; + let old_ctx = this.task_context; + if task_context.is_some() { + this.task_context = task_context; + } + let res = body(this); + this.task_context = old_ctx; - (params, res) - }) + (params, res) }); // `static |<_task_context?>| -> { }`: @@ -1050,26 +1046,24 @@ impl<'hir> LoweringContext<'_, 'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { - this.with_def_id_parent(closure_def_id, move |this| { - let mut coroutine_kind = if this - .attrs - .get(&closure_hir_id.local_id) - .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) - { - Some(hir::CoroutineKind::Coroutine(Movability::Movable)) - } else { - None - }; - let body_id = this.lower_fn_body(decl, |this| { - this.coroutine_kind = coroutine_kind; - let e = this.lower_expr_mut(body); - coroutine_kind = this.coroutine_kind; - e - }); - let coroutine_option = - this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); - (body_id, coroutine_option) - }) + let mut coroutine_kind = if this + .attrs + .get(&closure_hir_id.local_id) + .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) + { + Some(hir::CoroutineKind::Coroutine(Movability::Movable)) + } else { + None + }; + let body_id = this.lower_fn_body(decl, |this| { + this.coroutine_kind = coroutine_kind; + let e = this.lower_expr_mut(body); + coroutine_kind = this.coroutine_kind; + e + }); + let coroutine_option = + this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); + (body_id, coroutine_option) }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); @@ -1159,28 +1153,26 @@ impl<'hir> LoweringContext<'_, 'hir> { ); let body = self.with_new_scopes(fn_decl_span, |this| { - this.with_def_id_parent(closure_def_id, |this| { - let inner_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + let inner_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - // Transform `async |x: u8| -> X { ... }` into - // `|x: u8| || -> X { ... }`. - let body_id = this.lower_body(|this| { - let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( - &inner_decl, - |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), - fn_decl_span, - body.span, - coroutine_kind, - hir::CoroutineSource::Closure, - ); + // Transform `async |x: u8| -> X { ... }` into + // `|x: u8| || -> X { ... }`. + let body_id = this.lower_body(|this| { + let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( + &inner_decl, + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), + fn_decl_span, + body.span, + coroutine_kind, + hir::CoroutineSource::Closure, + ); - this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id); + this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id); - (parameters, expr) - }); - body_id - }) + (parameters, expr) + }); + body_id }); let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ea2e77fb9ddb..96546239f4c2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -117,18 +117,6 @@ struct LoweringContext<'a, 'hir> { is_in_dyn_type: bool, current_hir_id_owner: hir::OwnerId, - /// Why do we need this in addition to [`Self::current_hir_id_owner`]? - /// - /// Currently (as of June 2024), anonymous constants are not HIR owners; however, - /// they do get their own DefIds. Some of these DefIds have to be created during - /// AST lowering, rather than def collection, because we can't tell until after - /// name resolution whether an anonymous constant will end up instead being a - /// [`hir::ConstArgKind::Path`]. However, to compute which generics are - /// available to an anonymous constant nested inside another, we need to make - /// sure that the parent is recorded as the parent anon const, not the enclosing - /// item. So we need to track parent defs differently from HIR owners, since they - /// will be finer-grained in the case of anon consts. - current_def_id_parent: LocalDefId, item_local_id_counter: hir::ItemLocalId, trait_map: ItemLocalMap>, @@ -161,7 +149,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { attrs: SortedMap::default(), children: Vec::default(), current_hir_id_owner: hir::CRATE_OWNER_ID, - current_def_id_parent: CRATE_DEF_ID, item_local_id_counter: hir::ItemLocalId::ZERO, ident_and_label_to_local_id: Default::default(), #[cfg(debug_assertions)] @@ -565,7 +552,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert_eq!(_old, None); } - let item = self.with_def_id_parent(def_id, f); + let item = f(self); debug_assert_eq!(def_id, item.def_id().def_id); // `f` should have consumed all the elements in these vectors when constructing `item`. debug_assert!(self.impl_trait_defs.is_empty()); @@ -590,13 +577,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.children.push((def_id, hir::MaybeOwner::Owner(info))); } - fn with_def_id_parent(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T { - let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent); - let result = f(self); - self.current_def_id_parent = current_def_id_parent; - result - } - fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); @@ -773,7 +753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Fresh { param, kind, .. } => { // Late resolution delegates to us the creation of the `LocalDefId`. let _def_id = self.create_def( - self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? + self.current_hir_id_owner.def_id, param, kw::UnderscoreLifetime, DefKind::LifetimeParam, @@ -1466,17 +1446,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id); debug!(?opaque_ty_def_id, ?opaque_ty_hir_id); - let opaque_ty_def = self.with_def_id_parent(opaque_ty_def_id, |this| { - let bounds = lower_item_bounds(this); - let opaque_ty_def = hir::OpaqueTy { - hir_id: opaque_ty_hir_id, - def_id: opaque_ty_def_id, - bounds, - origin, - span: this.lower_span(opaque_ty_span), - }; - this.arena.alloc(opaque_ty_def) - }); + let bounds = lower_item_bounds(self); + let opaque_ty_def = hir::OpaqueTy { + hir_id: opaque_ty_hir_id, + def_id: opaque_ty_def_id, + bounds, + origin, + span: self.lower_span(opaque_ty_span), + }; + let opaque_ty_def = self.arena.alloc(opaque_ty_def); hir::TyKind::OpaqueDef(opaque_ty_def) } @@ -2084,7 +2062,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { // Construct an AnonConst where the expr is the "ty"'s path. - let parent_def_id = self.current_def_id_parent; + let parent_def_id = self.current_hir_id_owner.def_id; let node_id = self.next_node_id(); let span = self.lower_span(span); @@ -2108,9 +2086,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::AnonConst { def_id, hir_id, - body: this.with_def_id_parent(def_id, |this| { - this.lower_const_body(path_expr.span, Some(&path_expr)) - }), + body: this.lower_const_body(path_expr.span, Some(&path_expr)), span, }) }); @@ -2178,9 +2154,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::AnonConst { def_id, hir_id, - body: this.with_def_id_parent(def_id, |this| { - this.lower_const_body(c.value.span, Some(&c.value)) - }), + body: this.lower_const_body(c.value.span, Some(&c.value)), span: this.lower_span(c.value.span), } })) From d401a078e7839745c8e7d172527111134ad206dd Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 25 Nov 2024 18:50:20 +0100 Subject: [PATCH 159/330] update comment --- compiler/rustc_hir/src/def.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 3276f516a52a..0b7ffc4af459 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -109,7 +109,16 @@ pub enum DefKind { Use, /// An `extern` block. ForeignMod, - /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`. + /// + /// Not all anon-consts are actually still relevant in the HIR. We lower + /// trivial const-arguments directly to `hir::ConstArgKind::Path`, at which + /// point the definition for the anon-const ends up unused and incomplete. + /// + /// We do not provide any a `Span` for the definition and pretty much all other + /// queries also ICE when using this `DefId`. Given that the `DefId` of such + /// constants should only be reachable by iterating all definitions of a + /// given crate, you should not have to worry about this. AnonConst, /// An inline constant, e.g. `const { 1 + 2 }` InlineConst, From 9b6dfdd2abdf5f33f784c5e8f04506f9cd0c72aa Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 28 Nov 2024 13:53:38 +0100 Subject: [PATCH 160/330] Mark visionOS as supporting `std` Cargo's -Zbuild-std has recently started checking this field, which causes it to fail to compile even though we have full support for the standard library on these targets. --- .../rustc_target/src/spec/targets/aarch64_apple_visionos.rs | 2 +- .../rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index 62d6ffbd34f0..9817c5a8eb0d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { description: Some("ARM64 Apple visionOS".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index a66c4f6e96bd..d411f7105408 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { description: Some("ARM64 Apple visionOS simulator".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32" From dae1bf3911173edd0af476c8bcf117719267e59a Mon Sep 17 00:00:00 2001 From: Slanterns Date: Thu, 28 Nov 2024 23:06:15 +0800 Subject: [PATCH 161/330] fix typo in RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 3707f170a573..8702bb021184 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -43,7 +43,7 @@ Libraries - [Document that `catch_unwind` can deal with foreign exceptions without UB, although the exact behavior is unspecified.](https://github.com/rust-lang/rust/pull/128321) - [Implement `Default` for `HashMap`/`HashSet` iterators that don't already have it.](https://github.com/rust-lang/rust/pull/128711) - [Bump Unicode to version 16.0.0.](https://github.com/rust-lang/rust/pull/130183) -- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229). +- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229) From ba7316655645c020263e207ee9c036131b511d45 Mon Sep 17 00:00:00 2001 From: Julian Frimmel Date: Sun, 6 Oct 2024 12:33:25 +0200 Subject: [PATCH 162/330] Support `clobber_abi` for AVR inline assembly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the relevant registers to the list of clobbered regis- ters (part of #93335). This follows the [ABI documentation] of AVR-GCC: > The [...] call-clobbered general purpose registers (GPRs) are > registers that might be destroyed (clobbered) by a function call. > > - **R18–R27, R30, R31** > > These GPRs are call clobbered. An ordinary function may use them > without restoring the contents. [...] > > - **R0, T-Flag** > > The temporary register and the T-flag in SREG are also call- > clobbered, but this knowledge is not exposed explicitly to the > compiler (R0 is a fixed register). Therefore this commit lists the aforementioned registers `r18–r27`, `r30` and `r31` as clobbered registers. Since the `r0` register (listed above as well) is not available in inline assembly at all (potentially because the AVR-GCC considers it a fixed register causing the register to never be used in register allocation and LLVM adopting this), there is no need to list it in the clobber list (the `r0`-variant is not even available). A comment was added to ensure, that the `r0` gets added to the clobber-list once the register gets usable in inline ASM. Since the SREG is normally considered clobbered anyways (unless the user supplies the `preserve_flags`-option), there is no need to explicitly list a bit in this register (which is not possible to list anyways). Note, that this commit completely ignores the case of interrupts (that are described in the ABI-specification), since every register touched in an ISR need to be saved anyways. [ABI documentation]: https://gcc.gnu.org/wiki/avr-gcc#Call-Used_Registers --- compiler/rustc_target/src/asm/avr.rs | 5 +++++ compiler/rustc_target/src/asm/mod.rs | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs index 276f376b297e..9adcbecdf3c1 100644 --- a/compiler/rustc_target/src/asm/avr.rs +++ b/compiler/rustc_target/src/asm/avr.rs @@ -106,6 +106,11 @@ def_regs! { "the stack pointer cannot be used as an operand for inline asm", #error = ["r0", "r1", "r1r0"] => "r0 and r1 are not available due to an issue in LLVM", + // If this changes within LLVM, the compiler might use the registers + // in the future. This must be reflected in the set of clobbered + // registers, else the clobber ABI implementation is *unsound*, as + // this generates invalid code (register is not marked as clobbered + // but may change the register content). } } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 9fe733e063cf..204d5d533610 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -928,6 +928,7 @@ pub enum InlineAsmClobberAbi { AArch64, AArch64NoX18, Arm64EC, + Avr, RiscV, RiscVE, LoongArch, @@ -986,6 +987,10 @@ impl InlineAsmClobberAbi { }), _ => Err(&["C", "system", "efiapi"]), }, + InlineAsmArch::Avr => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::Avr), + _ => Err(&["C", "system"]), + }, InlineAsmArch::LoongArch64 => match name { "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch), _ => Err(&["C", "system"]), @@ -1133,6 +1138,23 @@ impl InlineAsmClobberAbi { d24, d25, d26, d27, d28, d29, d30, d31, } }, + InlineAsmClobberAbi::Avr => clobbered_regs! { + Avr AvrInlineAsmReg { + // The list of "Call-Used Registers" according to + // https://gcc.gnu.org/wiki/avr-gcc#Call-Used_Registers + + // Clobbered registers available in inline assembly + r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r30, r31, + // As per the AVR-GCC-ABI documentation linked above, the R0 + // register is a clobbered register as well. Since we don't + // allow the usage of R0 in inline assembly, nothing has to + // be done here. + // Likewise, the T-flag in the SREG should be clobbered, but + // this is not necessary to be listed here, since the SREG + // is considered clobbered anyways unless `preserve_flags` + // is used. + } + }, InlineAsmClobberAbi::RiscV => clobbered_regs! { RiscV RiscVInlineAsmReg { // ra From d7e0a3eee0c5e79134664293eea3c46b91f0bec7 Mon Sep 17 00:00:00 2001 From: Julian Frimmel Date: Sun, 6 Oct 2024 13:09:29 +0200 Subject: [PATCH 163/330] Add test case for the clobber options --- tests/codegen/asm-clobber_abi-avr.rs | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/codegen/asm-clobber_abi-avr.rs diff --git a/tests/codegen/asm-clobber_abi-avr.rs b/tests/codegen/asm-clobber_abi-avr.rs new file mode 100644 index 000000000000..6e0c75368e23 --- /dev/null +++ b/tests/codegen/asm-clobber_abi-avr.rs @@ -0,0 +1,43 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ needs-llvm-components: avr + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @sreg_is_clobbered +// CHECK: void asm sideeffect "", "~{sreg}"() +#[no_mangle] +pub unsafe fn sreg_is_clobbered() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @sreg_is_not_clobbered_if_preserve_flags_is_used +// CHECK: void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn sreg_is_not_clobbered_if_preserve_flags_is_used() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={r18},={r19},={r20},={r21},={r22},={r23},={r24},={r25},={r26},={r27},={r30},={r31},~{sreg}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem)); +} + +// CHECK-LABEL: @clobber_abi_with_preserved_flags +// CHECK: asm sideeffect "", "={r18},={r19},={r20},={r21},={r22},={r23},={r24},={r25},={r26},={r27},={r30},={r31}"() +#[no_mangle] +pub unsafe fn clobber_abi_with_preserved_flags() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} From 2bd3bbb2e0132d6d9c3766f35c2efc34414a8a66 Mon Sep 17 00:00:00 2001 From: Julian Frimmel Date: Sat, 2 Nov 2024 08:25:53 +0100 Subject: [PATCH 164/330] Move & rename test case to match naming of #132456 --- tests/codegen/{asm-clobber_abi-avr.rs => asm/avr-clobbers.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/codegen/{asm-clobber_abi-avr.rs => asm/avr-clobbers.rs} (100%) diff --git a/tests/codegen/asm-clobber_abi-avr.rs b/tests/codegen/asm/avr-clobbers.rs similarity index 100% rename from tests/codegen/asm-clobber_abi-avr.rs rename to tests/codegen/asm/avr-clobbers.rs From 67d2f3f6857a1d28113f1a63eb003b53d17088c9 Mon Sep 17 00:00:00 2001 From: Julian Frimmel Date: Thu, 28 Nov 2024 12:57:42 +0100 Subject: [PATCH 165/330] Reword error message of reserved AVR registers Those are reserved as per the GCC (and thus LLVM) ABI, which is distinct from an issue. The rewording was requested in this [review]. [review]: https://github.com/rust-lang/rust/pull/131323#issuecomment-2479178721 --- compiler/rustc_target/src/asm/avr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs index 9adcbecdf3c1..55d393c81d3e 100644 --- a/compiler/rustc_target/src/asm/avr.rs +++ b/compiler/rustc_target/src/asm/avr.rs @@ -105,7 +105,7 @@ def_regs! { #error = ["SP", "SPL", "SPH"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["r0", "r1", "r1r0"] => - "r0 and r1 are not available due to an issue in LLVM", + "LLVM reserves r0 (scratch register) and r1 (zero register)", // If this changes within LLVM, the compiler might use the registers // in the future. This must be reflected in the set of clobbered // registers, else the clobber ABI implementation is *unsound*, as From 0f8ebba54a8e41a9daccbbedae88e8798f4557c3 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 29 Nov 2024 00:24:36 +0900 Subject: [PATCH 166/330] Support #[repr(simd)] types in input/output of PowerPC inline assembly --- compiler/rustc_codegen_gcc/src/asm.rs | 10 +- compiler/rustc_codegen_llvm/src/asm.rs | 10 +- compiler/rustc_span/src/symbol.rs | 2 + compiler/rustc_target/src/asm/powerpc.rs | 6 +- .../asm-experimental-arch.md | 6 +- tests/assembly/asm/powerpc-types.rs | 237 +++++++++++++++++- tests/codegen/asm/powerpc-clobbers.rs | 13 +- tests/ui/asm/powerpc/bad-reg.aix64.stderr | 136 +++++----- tests/ui/asm/powerpc/bad-reg.powerpc.stderr | 172 +++++++------ tests/ui/asm/powerpc/bad-reg.powerpc64.stderr | 160 ++++++------ .../ui/asm/powerpc/bad-reg.powerpc64le.stderr | 136 +++++----- tests/ui/asm/powerpc/bad-reg.rs | 59 +++-- 12 files changed, 595 insertions(+), 352 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 341d1b9c179b..a1f9eab10e76 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -656,9 +656,9 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -736,9 +736,11 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { + cx.type_vector(cx.type_i32(), 4) + } InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => { + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 9aa01bd1b956..1483d576362b 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -656,9 +656,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> PowerPC(PowerPCInlineAsmRegClass::reg) => "r", PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", PowerPC(PowerPCInlineAsmRegClass::freg) => "f", - PowerPC(PowerPCInlineAsmRegClass::cr) - | PowerPC(PowerPCInlineAsmRegClass::xer) - | PowerPC(PowerPCInlineAsmRegClass::vreg) => { + PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", + PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => "r", @@ -825,9 +824,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(), PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(), - PowerPC(PowerPCInlineAsmRegClass::cr) - | PowerPC(PowerPCInlineAsmRegClass::xer) - | PowerPC(PowerPCInlineAsmRegClass::vreg) => { + PowerPC(PowerPCInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i32(), 4), + PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => { unreachable!("clobber-only") } RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3a07c283e0eb..6cd754a47e94 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -392,6 +392,7 @@ symbols! { allow_fail, allow_internal_unsafe, allow_internal_unstable, + altivec, alu32, always, and, @@ -2154,6 +2155,7 @@ symbols! { volatile_store, vreg, vreg_low16, + vsx, vtable_align, vtable_size, warn, diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index aa8b26170bee..a5a96b87e367 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -51,7 +51,11 @@ impl PowerPCInlineAsmRegClass { } } Self::freg => types! { _: F32, F64; }, - Self::vreg => &[], + // FIXME: vsx also supports integers and floats: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773 + Self::vreg => types! { + altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4); + vsx: VecI64(2), VecF64(2); + }, Self::cr | Self::xer => &[], } } diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 12a73f0508b2..f2d0caa5e37c 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -34,7 +34,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` | | PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` | | PowerPC | `freg` | `f[0-31]` | `f` | -| PowerPC | `vreg` | `v[0-31]` | Only clobbers | +| PowerPC | `vreg` | `v[0-31]` | `v` | | PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | | PowerPC | `xer` | `xer` | Only clobbers | | wasm32 | `local` | None\* | `r` | @@ -75,7 +75,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `freg` | None | `f32`, `f64` | -| PowerPC | `vreg` | N/A | Only clobbers | +| PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` | +| PowerPC | `vreg` | `vsx` | `i64x2`, `f64x2` | | PowerPC | `cr` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | @@ -181,6 +182,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `0` | None | | PowerPC | `reg_nonzero` | None | `3` | None | | PowerPC | `freg` | None | `0` | None | +| PowerPC | `vreg` | None | `0` | None | | SPARC | `reg` | None | `%o0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index 85321e5f345a..d67e0f66f66f 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -1,9 +1,15 @@ -//@ revisions: powerpc powerpc64 +//@ revisions: powerpc powerpc_altivec powerpc_vsx powerpc64 powerpc64_vsx //@ assembly-output: emit-asm //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu //@[powerpc] needs-llvm-components: powerpc -//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc_altivec] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec --cfg altivec +//@[powerpc_altivec] needs-llvm-components: powerpc +//@[powerpc_vsx] compile-flags: --target powerpc-unknown-linux-gnu -C target-feature=+altivec,+vsx --cfg altivec --cfg vsx +//@[powerpc_vsx] needs-llvm-components: powerpc +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu --cfg altivec //@[powerpc64] needs-llvm-components: powerpc +//@[powerpc64_vsx] compile-flags: --target powerpc64-unknown-linux-gnu -C target-feature=+vsx --cfg altivec --cfg vsx +//@[powerpc64_vsx] needs-llvm-components: powerpc //@ compile-flags: -Zmerge-functions=disabled #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] @@ -11,6 +17,13 @@ #![no_core] #![allow(asm_sub_register, non_camel_case_types)] +#[cfg_attr(altivec, cfg(not(target_feature = "altivec")))] +#[cfg_attr(not(altivec), cfg(target_feature = "altivec"))] +compile_error!("altivec cfg and target feature mismatch"); +#[cfg_attr(vsx, cfg(not(target_feature = "vsx")))] +#[cfg_attr(not(vsx), cfg(target_feature = "vsx"))] +compile_error!("vsx cfg and target feature mismatch"); + #[rustc_builtin_macro] macro_rules! asm { () => {}; @@ -29,8 +42,23 @@ trait Sized {} #[lang = "copy"] trait Copy {} +impl Copy for [T; N] {} + type ptr = *const i32; +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i16x8([i16; 8]); +#[repr(simd)] +pub struct i32x4([i32; 4]); +#[repr(simd)] +pub struct i64x2([i64; 2]); +#[repr(simd)] +pub struct f32x4([f32; 4]); +#[repr(simd)] +pub struct f64x2([f64; 2]); + impl Copy for i8 {} impl Copy for u8 {} impl Copy for i16 {} @@ -39,6 +67,13 @@ impl Copy for i64 {} impl Copy for f32 {} impl Copy for f64 {} impl Copy for ptr {} +impl Copy for i8x16 {} +impl Copy for i16x8 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} +impl Copy for f32x4 {} +impl Copy for f64x2 {} + extern "C" { fn extern_func(); static extern_static: u8; @@ -124,6 +159,72 @@ check!(reg_f32, f32, freg, "fmr"); // CHECK: #NO_APP check!(reg_f64, f64, freg, "fmr"); +// powerpc_altivec-LABEL: vreg_i8x16: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i8x16: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_i8x16, i8x16, vreg, "vmr"); + +// powerpc_altivec-LABEL: vreg_i16x8: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i16x8: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_i16x8, i16x8, vreg, "vmr"); + +// powerpc_altivec-LABEL: vreg_i32x4: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i32x4: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_i32x4, i32x4, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_i64x2: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_i64x2: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_i64x2, i64x2, vreg, "vmr"); + +// powerpc_altivec-LABEL: vreg_f32x4: +// powerpc_altivec: #APP +// powerpc_altivec: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_f32x4: +// powerpc64: #APP +// powerpc64: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64: #NO_APP +#[cfg(altivec)] +check!(vreg_f32x4, f32x4, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_f64x2: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64x2: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f64x2, f64x2, vreg, "vmr"); + // CHECK-LABEL: reg_i8_r0: // CHECK: #APP // CHECK: mr 0, 0 @@ -197,3 +298,135 @@ check_reg!(reg_f32_f18, f32, "18", "f18", "fmr"); // CHECK: fmr 18, 18 // CHECK: #NO_APP check_reg!(reg_f64_f18, f64, "18", "f18", "fmr"); + +// powerpc_altivec-LABEL: vreg_i8x16_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i8x16_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i8x16_v0, i8x16, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_i16x8_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i16x8_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i16x8_v0, i16x8, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_i32x4_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i32x4_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i32x4_v0, i32x4, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_i64x2_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_i64x2_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_i64x2_v0, i64x2, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_f32x4_v0: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 0, 0 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_f32x4_v0: +// powerpc64: #APP +// powerpc64: vmr 0, 0 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64x2_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64x2_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr"); + +// powerpc_altivec-LABEL: vreg_i8x16_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i8x16_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i8x16_v18, i8x16, "18", "v18", "vmr"); + +// powerpc_altivec-LABEL: vreg_i16x8_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i16x8_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i16x8_v18, i16x8, "18", "v18", "vmr"); + +// powerpc_altivec-LABEL: vreg_i32x4_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_i32x4_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_i32x4_v18, i32x4, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_i64x2_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_i64x2_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_i64x2_v18, i64x2, "18", "v18", "vmr"); + +// powerpc_altivec-LABEL: vreg_f32x4_v18: +// powerpc_altivec: #APP +// powerpc_altivec: vmr 18, 18 +// powerpc_altivec: #NO_APP +// powerpc64-LABEL: vreg_f32x4_v18: +// powerpc64: #APP +// powerpc64: vmr 18, 18 +// powerpc64: #NO_APP +#[cfg(altivec)] +check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64x2_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64x2_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr"); diff --git a/tests/codegen/asm/powerpc-clobbers.rs b/tests/codegen/asm/powerpc-clobbers.rs index e97e8300ca74..2832377cef00 100644 --- a/tests/codegen/asm/powerpc-clobbers.rs +++ b/tests/codegen/asm/powerpc-clobbers.rs @@ -7,6 +7,7 @@ //@[powerpc64le] needs-llvm-components: powerpc //@[aix64] compile-flags: --target powerpc64-ibm-aix //@[aix64] needs-llvm-components: powerpc +// ignore-tidy-linelength #![crate_type = "rlib"] #![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] @@ -48,15 +49,23 @@ pub unsafe fn xer_clobber() { asm!("", out("xer") _, options(nostack, nomem, preserves_flags)); } +// Output format depends on the availability of altivec. // CHECK-LABEL: @v0_clobber -// CHECK: call void asm sideeffect "", "~{v0}"() +// powerpc: call void asm sideeffect "", "~{v0}"() +// powerpc64: call <4 x i32> asm sideeffect "", "=&{v0}"() +// powerpc64le: call <4 x i32> asm sideeffect "", "=&{v0}"() +// aix64: call <4 x i32> asm sideeffect "", "=&{v0}"() #[no_mangle] pub unsafe fn v0_clobber() { asm!("", out("v0") _, options(nostack, nomem, preserves_flags)); } +// Output format depends on the availability of altivec. // CHECK-LABEL: @clobber_abi -// CHECK: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// powerpc64le: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() +// aix64: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},={v0},={v1},={v2},={v3},={v4},={v5},={v6},={v7},={v8},={v9},={v10},={v11},={v12},={v13},={v14},={v15},={v16},={v17},={v18},={v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"() #[no_mangle] pub unsafe fn clobber_abi() { asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr index 34105ceac049..332bdf0ff546 100644 --- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,37 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:76:27 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +197,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +205,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +213,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +221,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +229,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 34 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr index 34105ceac049..13fc5a048d82 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,73 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:66:18 + | +LL | asm!("", in("v0") v32x4); // requires altivec + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:68:18 + | +LL | asm!("", out("v0") v32x4); // requires altivec + | ^^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:70:18 + | +LL | asm!("", in("v0") v64x2); // requires vsx + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:73:18 + | +LL | asm!("", out("v0") v64x2); // requires vsx + | ^^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:76:18 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:82:26 + | +LL | asm!("/* {} */", in(vreg) v32x4); // requires altivec + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:84:26 + | +LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx + | ^^^^^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:87:26 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^^^^^^^^^^ + +error: register class `vreg` requires at least one of the following target features: altivec, vsx + --> $DIR/bad-reg.rs:90:26 + | +LL | asm!("/* {} */", out(vreg) _); // requires altivec + | ^^^^^^^^^^^ + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +233,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +241,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +249,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +257,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +265,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 41 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr index 34105ceac049..9e0dd80b3dca 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,61 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ +error: `vsx` target feature is not enabled + --> $DIR/bad-reg.rs:70:27 + | +LL | asm!("", in("v0") v64x2); // requires vsx + | ^^^^^ + | + = note: this is required to use type `i64x2` with register class `vreg` + +error: `vsx` target feature is not enabled + --> $DIR/bad-reg.rs:73:28 + | +LL | asm!("", out("v0") v64x2); // requires vsx + | ^^^^^ + | + = note: this is required to use type `i64x2` with register class `vreg` + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:76:27 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: `vsx` target feature is not enabled + --> $DIR/bad-reg.rs:84:35 + | +LL | asm!("/* {} */", in(vreg) v64x2); // requires vsx + | ^^^^^ + | + = note: this is required to use type `i64x2` with register class `vreg` + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +221,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +229,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +237,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +245,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +253,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 37 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr index 34105ceac049..332bdf0ff546 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -1,125 +1,101 @@ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:45:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:34:18 + --> $DIR/bad-reg.rs:47:18 | LL | asm!("", out("r2") _); | ^^^^^^^^^^^ error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:51:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:53:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:42:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("fp") _); | ^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:44:18 + --> $DIR/bad-reg.rs:57:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:46:18 + --> $DIR/bad-reg.rs:59:18 | LL | asm!("", out("ctr") _); | ^^^^^^^^^^^^ error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:61:18 | LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:66:18 + --> $DIR/bad-reg.rs:109:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:69:18 + --> $DIR/bad-reg.rs:112:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:72:26 + --> $DIR/bad-reg.rs:115:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:75:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:79:18 + --> $DIR/bad-reg.rs:122:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:82:18 + --> $DIR/bad-reg.rs:125:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:85:26 + --> $DIR/bad-reg.rs:128:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:88:26 + --> $DIR/bad-reg.rs:131:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:93:18 - | -LL | asm!("", in("v0") x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:96:18 - | -LL | asm!("", out("v0") x); - | ^^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:99:26 - | -LL | asm!("/* {} */", in(vreg) x); - | ^^^^^^^^^^ - -error: register class `vreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:102:26 - | -LL | asm!("/* {} */", out(vreg) _); - | ^^^^^^^^^^^ - error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:106:31 + --> $DIR/bad-reg.rs:135:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -127,7 +103,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:108:31 + --> $DIR/bad-reg.rs:137:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -135,7 +111,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:110:31 + --> $DIR/bad-reg.rs:139:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -143,7 +119,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:112:31 + --> $DIR/bad-reg.rs:141:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -151,7 +127,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:114:31 + --> $DIR/bad-reg.rs:143:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -159,7 +135,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:116:31 + --> $DIR/bad-reg.rs:145:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -167,7 +143,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:118:31 + --> $DIR/bad-reg.rs:147:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -175,7 +151,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:120:31 + --> $DIR/bad-reg.rs:149:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -183,13 +159,37 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: cannot use register `r13`: r13 is a reserved register on this target - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:49:18 | LL | asm!("", out("r13") _); | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:27 + --> $DIR/bad-reg.rs:76:27 + | +LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:79:28 + | +LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:87:35 + | +LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + | ^ + | + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + +error: type `i32` cannot be used with this register class + --> $DIR/bad-reg.rs:109:27 | LL | asm!("", in("cr") x); | ^ @@ -197,7 +197,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:69:28 + --> $DIR/bad-reg.rs:112:28 | LL | asm!("", out("cr") x); | ^ @@ -205,7 +205,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:72:33 + --> $DIR/bad-reg.rs:115:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -213,7 +213,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:79:28 + --> $DIR/bad-reg.rs:122:28 | LL | asm!("", in("xer") x); | ^ @@ -221,7 +221,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:82:29 + --> $DIR/bad-reg.rs:125:29 | LL | asm!("", out("xer") x); | ^ @@ -229,36 +229,12 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:85:34 + --> $DIR/bad-reg.rs:128:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:93:27 - | -LL | asm!("", in("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:96:28 - | -LL | asm!("", out("v0") x); - | ^ - | - = note: register class `vreg` supports these types: - -error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:99:35 - | -LL | asm!("/* {} */", in(vreg) x); - | ^ - | - = note: register class `vreg` supports these types: - -error: aborting due to 38 previous errors +error: aborting due to 34 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs index 5023ad51838a..f34c45663a02 100644 --- a/tests/ui/asm/powerpc/bad-reg.rs +++ b/tests/ui/asm/powerpc/bad-reg.rs @@ -8,17 +8,28 @@ //@[aix64] compile-flags: --target powerpc64-ibm-aix //@[aix64] needs-llvm-components: powerpc //@ needs-asm-support +// ignore-tidy-linelength #![crate_type = "rlib"] -#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![feature(no_core, rustc_attrs, lang_items, repr_simd, asm_experimental_arch)] #![no_core] +#![allow(non_camel_case_types)] #[lang = "sized"] trait Sized {} #[lang = "copy"] trait Copy {} +#[repr(simd)] +pub struct i32x4([i32; 4]); +#[repr(simd)] +pub struct i64x2([i64; 2]); + +impl Copy for [T; N] {} impl Copy for i32 {} +impl Copy for i64 {} +impl Copy for i32x4 {} +impl Copy for i64x2 {} #[rustc_builtin_macro] macro_rules! asm { @@ -27,6 +38,8 @@ macro_rules! asm { fn f() { let mut x = 0; + let mut v32x4 = i32x4([0; 4]); + let mut v64x2 = i64x2([0; 2]); unsafe { // Unsupported registers asm!("", out("sp") _); @@ -47,6 +60,36 @@ fn f() { //~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm asm!("", out("vrsave") _); //~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm + + // vreg + asm!("", out("v0") _); // always ok + asm!("", in("v0") v32x4); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + asm!("", out("v0") v32x4); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + asm!("", in("v0") v64x2); // requires vsx + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64]~^^ ERROR `vsx` target feature is not enabled + asm!("", out("v0") v64x2); // requires vsx + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64]~^^ ERROR `vsx` target feature is not enabled + asm!("", in("v0") x); // FIXME: should be ok if vsx is available + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class + asm!("", out("v0") x); // FIXME: should be ok if vsx is available + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class + asm!("/* {} */", in(vreg) v32x4); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + asm!("/* {} */", in(vreg) v64x2); // requires vsx + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64]~^^ ERROR `vsx` target feature is not enabled + asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class + asm!("/* {} */", out(vreg) _); // requires altivec + //[powerpc]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx + // v20-v31 are reserved on AIX with vec-default ABI (this ABI is not currently used in Rust's builtin AIX targets). asm!("", out("v20") _); asm!("", out("v21") _); asm!("", out("v22") _); @@ -87,20 +130,6 @@ fn f() { //~| ERROR type `i32` cannot be used with this register class asm!("/* {} */", out(xer) _); //~^ ERROR can only be used as a clobber - // vreg - asm!("", out("v0") _); // ok - // FIXME: will be supported in the subsequent patch: https://github.com/rust-lang/rust/pull/131551 - asm!("", in("v0") x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("", out("v0") x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("/* {} */", in(vreg) x); - //~^ ERROR can only be used as a clobber - //~| ERROR type `i32` cannot be used with this register class - asm!("/* {} */", out(vreg) _); - //~^ ERROR can only be used as a clobber // Overlapping-only registers asm!("", out("cr") _, out("cr0") _); From ac9324cedbcdf3932ebcd37928054e8eb551104d Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 28 Nov 2024 16:41:39 +0100 Subject: [PATCH 167/330] Document s390x machine access via community cloud --- .../platform-support/s390x-unknown-linux-gnu.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md index 60e06c404c0d..6f09ce42dbbd 100644 --- a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md @@ -64,6 +64,22 @@ There are no special requirements for testing and running the target. For testing cross builds on the host, please refer to the "Cross-compilation toolchains and C code" section below. +If you want to do native testing but do not have your own s390x +machine, there are several options how to get access to one: + +* The [IBM LinuxONE Community Cloud][cloud-community] provides a + self-service portal where you can create s390x virtual machine + instances. These are intended for temporary use (limited to 120 days). + +* The [IBM LinuxONE Open Source Cloud][cloud-opensource] provides + permanent access to s390x machines. This requires approval by IBM, + which will normally be granted if you're planning to use the machine + to work on an open-source project that is relevant to the IBM Z + ecosystem - the Rust compiler would certainly qualify. + +[cloud-community]: https://linuxone.cloud.marist.edu/ +[cloud-opensource]: https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/ + ## Cross-compilation toolchains and C code Rust code built using the target is compatible with C code compiled with From 72d2db7bf46f565f4ee5cc73d65b4f4906e7420e Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 27 Nov 2024 17:21:59 +0000 Subject: [PATCH 168/330] Implement lint against `Symbol::intern` on a string literal --- compiler/rustc_lint/messages.ftl | 3 +++ compiler/rustc_lint/src/internal.rs | 35 +++++++++++++++++++++++-- compiler/rustc_lint/src/lib.rs | 2 ++ compiler/rustc_lint/src/lints.rs | 5 ++++ compiler/rustc_span/src/symbol.rs | 2 ++ src/bootstrap/src/core/builder/cargo.rs | 9 +++++++ 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 69fd7f2d8b25..bb4a3527b331 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -772,6 +772,9 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type +lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal + .help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs` + lint_trailing_semi_macro = trailing semicolon in macro used in expression position .note1 = macro invocations at the end of a block are treated as expressions .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 38c38b59bc58..755a75146bf9 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -17,8 +17,9 @@ use tracing::debug; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, - NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified, - TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag, + NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, + SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage, + UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -657,3 +658,33 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => false, } } + +declare_tool_lint! { + /// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal + pub rustc::SYMBOL_INTERN_STRING_LITERAL, + // rustc_driver crates out of the compiler can't/shouldn't add preinterned symbols; + // bootstrap will deny this manually + Allow, + "Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead", + report_in_external_macro: true +} + +declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]); + +impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { + if let ExprKind::Call(path, [arg]) = expr.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id) + && let ExprKind::Lit(kind) = arg.kind + && let rustc_ast::LitKind::Str(_, _) = kind.node + { + cx.emit_span_lint( + SYMBOL_INTERN_STRING_LITERAL, + kind.span, + SymbolInternStringLiteralDiag, + ); + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 4cf5c7b4ff96..a99c94592b30 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -614,6 +614,8 @@ fn register_internals(store: &mut LintStore) { store.register_late_mod_pass(|_| Box::new(PassByValue)); store.register_lints(&SpanUseEqCtxt::lint_vec()); store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt)); + store.register_lints(&SymbolInternStringLiteral::lint_vec()); + store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral)); // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and // these lints will trigger all of the time - change this once migration to diagnostic structs diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index dce6010a2c10..f669026b3db7 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -907,6 +907,11 @@ pub(crate) struct QueryUntracked { #[diag(lint_span_use_eq_ctxt)] pub(crate) struct SpanUseEqCtxtDiag; +#[derive(LintDiagnostic)] +#[diag(lint_symbol_intern_string_literal)] +#[help] +pub(crate) struct SymbolInternStringLiteralDiag; + #[derive(LintDiagnostic)] #[diag(lint_tykind_kind)] pub(crate) struct TykindKind { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5252c446e1d3..bbbfb51b0783 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -315,6 +315,7 @@ symbols! { StructuralPartialEq, SubdiagMessage, Subdiagnostic, + SymbolIntern, Sync, SyncUnsafeCell, T, @@ -2401,6 +2402,7 @@ impl Symbol { } /// Maps a string to its interned representation. + #[rustc_diagnostic_item = "SymbolIntern"] pub fn intern(string: &str) -> Self { with_session_globals(|session_globals| session_globals.symbol_interner.intern(string)) } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 0688a1d68928..13f351de20e8 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1030,6 +1030,15 @@ impl Builder<'_> { if mode == Mode::Rustc { rustflags.arg("-Wrustc::internal"); + // cfg(bootstrap) - remove this check when lint is in bootstrap compiler + if stage != 0 { + // Lint is allow by default so downstream tools don't get a lit + // they can do nothing about + // We shouldn't be preinterning symbols used by tests + if cmd_kind != Kind::Test { + rustflags.arg("-Drustc::symbol_intern_string_literal"); + } + } // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all // of the individual lints are satisfied. rustflags.arg("-Wkeyword_idents_2024"); From 71b698c0b81c2e35c852ebcdf1f5cbe9e9162a50 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 27 Nov 2024 17:52:57 +0000 Subject: [PATCH 169/330] Replace `Symbol::intern` calls with preinterned symbols --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 +++-- compiler/rustc_borrowck/src/universal_regions.rs | 10 ++++------ compiler/rustc_codegen_cranelift/src/driver/jit.rs | 9 ++------- compiler/rustc_codegen_cranelift/src/lib.rs | 9 ++------- .../rustc_hir_analysis/src/collect/generics_of.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_metadata/src/creader.rs | 9 +++++---- compiler/rustc_metadata/src/rmeta/decoder.rs | 1 + compiler/rustc_parse/src/parser/ty.rs | 4 ++-- compiler/rustc_resolve/src/late/diagnostics.rs | 1 + compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_session/src/output.rs | 2 +- compiler/rustc_span/src/symbol.rs | 14 ++++++++++++++ .../src/traits/dyn_compatibility.rs | 3 +-- 15 files changed, 40 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 8cdc7133cc07..bfe7625e85ba 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -4,9 +4,9 @@ use rustc_ast::{NodeId, PatKind, attr, token}; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue}; use rustc_session::Session; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::symbol::{Symbol, sym}; use rustc_target::spec::abi; use thin_vec::ThinVec; @@ -690,6 +690,7 @@ fn check_new_solver_banned_features(sess: &Session, features: &Features) { .find(|feat| feat.gate_name == sym::generic_const_exprs) .map(|feat| feat.attr_sp) { + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] sess.dcx().emit_err(errors::IncompatibleFeatures { spans: vec![gce_span], f1: Symbol::intern("-Znext-solver=globally"), diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index f1c23aa26a97..baff65475015 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -33,8 +33,8 @@ use rustc_middle::ty::{ TyCtxt, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; +use rustc_span::ErrorGuaranteed; use rustc_span::symbol::{kw, sym}; -use rustc_span::{ErrorGuaranteed, Symbol}; use tracing::{debug, instrument}; use crate::BorrowckInferCtxt; @@ -524,7 +524,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let reg_vid = self .infcx - .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic"))) + .next_nll_region_var(FR, || RegionCtxt::Free(sym::c_dash_variadic)) .as_var(); let region = ty::Region::new_var(self.infcx.tcx, reg_vid); @@ -540,10 +540,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } } - let fr_fn_body = self - .infcx - .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body"))) - .as_var(); + let fr_fn_body = + self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(sym::fn_body)).as_var(); let num_universals = self.infcx.num_region_vars(); diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 0d62a13b4724..ae9578eeffb6 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -74,7 +74,7 @@ fn create_jit_module( jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8); let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false); - let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, Symbol::intern("dummy_cgu_name")); + let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); crate::allocator::codegen(tcx, &mut jit_module); @@ -276,12 +276,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> jit_module.module.prepare_for_function_redefine(func_id).unwrap(); - let mut cx = crate::CodegenCx::new( - tcx, - jit_module.isa(), - false, - Symbol::intern("dummy_cgu_name"), - ); + let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name); codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance); assert!(cx.global_asm.is_empty()); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index e6f6ae305816..cac9975f04ce 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -189,18 +189,13 @@ impl CodegenBackend for CraneliftCodegenBackend { // 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")] + vec![sym::fsxr, sym::sse, sym::sse2] } else if sess.target.arch == "aarch64" { match &*sess.target.os { "none" => vec![], // On macOS the aes, sha2 and sha3 features are enabled by default and ring // fails to compile on macOS when they are not present. - "macos" => vec![ - sym::neon, - Symbol::intern("aes"), - Symbol::intern("sha2"), - Symbol::intern("sha3"), - ], + "macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3], // AArch64 mandates Neon support _ => vec![sym::neon], } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c31bff28fd34..111dee744fd9 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -419,7 +419,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if let Node::ConstBlock(_) = node { own_params.push(ty::GenericParamDef { index: next_index(), - name: Symbol::intern(""), + name: rustc_span::sym::const_ty_placeholder, def_id: def_id.to_def_id(), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cff2aa689939..6b1a288510ac 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| { tcx.is_diagnostic_item(sym::write_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id) - }) && item_name.name == Symbol::intern("write_fmt"); + }) && item_name.name == sym::write_fmt; let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_missing_writer(rcvr_ty, rcvr_expr) } else { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index e1a0e1ec5791..b775cd374091 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1563,7 +1563,7 @@ impl UnusedImportBraces { } rename.unwrap_or(orig_ident).name } - ast::UseTreeKind::Glob => Symbol::intern("*"), + ast::UseTreeKind::Glob => sym::asterisk, ast::UseTreeKind::Nested { .. } => return, }; diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index a18c6baec00f..29dba2bca614 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -861,8 +861,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // First up we check for global allocators. Look at the crate graph here // and see what's a global allocator, including if we ourselves are a // global allocator. - let mut global_allocator = - self.cstore.has_global_allocator.then(|| Symbol::intern("this crate")); + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + let this_crate = Symbol::intern("this crate"); + + let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate); for (_, data) in self.cstore.iter_crate_data() { if data.has_global_allocator() { match global_allocator { @@ -876,8 +878,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } } - let mut alloc_error_handler = - self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate")); + let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate); for (_, data) in self.cstore.iter_crate_data() { if data.has_alloc_error_handler() { match alloc_error_handler { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 56beff5aa642..f3f5af494123 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -872,6 +872,7 @@ impl MetadataBlob { let def_kind = root.tables.def_kind.get(blob, item).unwrap(); let def_key = root.tables.def_keys.get(blob, item).unwrap().decode(blob); + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] let def_name = if item == CRATE_DEF_INDEX { rustc_span::symbol::kw::Crate } else { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index c561ea3823d0..4ddf791f70b1 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -9,7 +9,7 @@ use rustc_ast::{ }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{Ident, kw, sym}; -use rustc_span::{ErrorGuaranteed, Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span}; use thin_vec::{ThinVec, thin_vec}; use super::{Parser, PathStyle, SeqSep, TokenType, Trailing}; @@ -1139,7 +1139,7 @@ impl<'a> Parser<'a> { Some(ast::Path { span: fn_token_span.to(self.prev_token.span), segments: thin_vec![ast::PathSegment { - ident: Ident::new(Symbol::intern("Fn"), fn_token_span), + ident: Ident::new(sym::Fn, fn_token_span), id: DUMMY_NODE_ID, args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs { span: args_lo.to(self.prev_token.span), diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 663c3ac0045a..09f3e8487668 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3113,6 +3113,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } + #[cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] let existing_name = match &in_scope_lifetimes[..] { [] => Symbol::intern("'a"), [(existing, _)] => existing.name, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e382295b8f6d..a26c64169ae0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2270,7 +2270,7 @@ fn module_to_string(module: Module<'_>) -> Option { collect_mod(names, parent); } } else { - names.push(Symbol::intern("")); + names.push(sym::opaque_module_name_placeholder); collect_mod(names, module.parent.unwrap()); } } diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 357d746c1846..2b2ba50d3fb7 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -87,7 +87,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol { } } - Symbol::intern("rust_out") + sym::rust_out } pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bbbfb51b0783..81a768cc7075 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -297,6 +297,7 @@ symbols! { Return, Right, Rust, + RustaceansAreAwesome, RustcDecodable, RustcEncodable, RwLock, @@ -377,6 +378,7 @@ symbols! { adt_const_params, advanced_slice_patterns, adx_target_feature, + aes, aggregate_raw_ptr, alias, align, @@ -439,6 +441,7 @@ symbols! { associated_types, assume, assume_init, + asterisk: "*", async_await, async_call, async_call_mut, @@ -519,6 +522,7 @@ symbols! { btreeset_iter, builtin_syntax, c, + c_dash_variadic, c_str, c_str_literals, c_unwind, @@ -649,6 +653,7 @@ symbols! { const_trait_bound_opt_out, const_trait_impl, const_try, + const_ty_placeholder: "", constant, constructor, convert_identity, @@ -778,6 +783,7 @@ symbols! { drop_types_in_const, dropck_eyepatch, dropck_parametricity, + dummy_cgu_name, dylib, dyn_compatible_for_dispatch, dyn_metadata, @@ -921,6 +927,7 @@ symbols! { fmuladdf32, fmuladdf64, fn_align, + fn_body, fn_delegation, fn_must_use, fn_mut, @@ -961,6 +968,7 @@ symbols! { fs_create_dir, fsub_algebraic, fsub_fast, + fsxr, full, fundamental, fused_iterator, @@ -1384,6 +1392,7 @@ symbols! { on, on_unimplemented, opaque, + opaque_module_name_placeholder: "", open_options_new, ops, opt_out_copy, @@ -1652,6 +1661,7 @@ symbols! { rust_eh_catch_typeinfo, rust_eh_personality, rust_logo, + rust_out, rustc, rustc_abi, rustc_allocator, @@ -1774,6 +1784,8 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, + sha2, + sha3, sha512_sm_x86, shadow_call_stack, shallow, @@ -1887,6 +1899,7 @@ symbols! { sreg, sreg_low16, sse, + sse2, sse4a_target_feature, stable, staged_api, @@ -2173,6 +2186,7 @@ symbols! { wrapping_sub, wreg, write_bytes, + write_fmt, write_macro, write_str, write_via_move, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e0a9ddf1876e..993bc2e9b940 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::{ TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_span::Span; -use rustc_span::symbol::Symbol; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -679,7 +678,7 @@ fn receiver_is_dispatchable<'tcx>( // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = - Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); + Ty::new_param(tcx, u32::MAX, rustc_span::sym::RustaceansAreAwesome); // `Receiver[Self => U]` let unsized_receiver_ty = From 8574f374e2cc27b53c8b81dc4031c59ca3035284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 28 Nov 2024 17:55:52 +0000 Subject: [PATCH 170/330] Do not call `extern_crate` on current trait on crate mismatch errors When we encounter an error caused by traits/types of different versions of the same crate, filter out the current crate when collecting spans to add to the context so we don't call `extern_crate` on the `DefId` of the current crate, which is meaningless and ICEs. Produced output with this filter: ``` error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied --> y.rs:13:19 | 13 | check_trait::(); | ^^^^^^^^^^^ the trait `Trait` is not implemented for `foo::Struct` | note: there are multiple different versions of crate `foo` in the dependency graph --> y.rs:7:1 | 4 | extern crate foo; | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate 5 | 6 | pub struct Struct; | ----------------- this type implements the required trait 7 | pub trait Trait {} | ^^^^^^^^^^^^^^^ this is the required trait | ::: x.rs:4:1 | 4 | pub struct Struct; | ----------------- this type doesn't implement the required trait 5 | pub trait Trait {} | --------------- this is the found trait = note: two types coming from two different versions of the same crate are different types even if they look the same = help: you can use `cargo tree` to explore your dependency tree note: required by a bound in `check_trait` --> y.rs:10:19 | 10 | fn check_trait() {} | ^^^^^ required by this bound in `check_trait` ``` Fix #133563. --- .../traits/fulfillment_errors.rs | 4 +++ .../foo-current.rs | 14 ++++++++ .../foo-prev.rs | 6 ++++ .../rmake.rs | 32 +++++++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs create mode 100644 tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs create mode 100644 tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 751918945259..9b969dd3e43a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1731,6 +1731,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); for (sp, label) in [trait_def_id, other_trait_def_id] .iter() + // The current crate-version might depend on another version of the same crate + // (Think "semver-trick"). Do not call `extern_crate` in that case for the local + // crate as that doesn't make sense and ICEs (#133563). + .filter(|def_id| !def_id.is_local()) .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) .map(|data| { let dependency = if data.dependency_of == LOCAL_CRATE { diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs b/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs new file mode 100644 index 000000000000..71b27cd85bfe --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![crate_name = "foo"] + +extern crate foo; + +pub struct Struct; +pub trait Trait {} +impl Trait for Struct {} + +fn check_trait() {} + +fn ice() { + check_trait::(); +} diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs b/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs new file mode 100644 index 000000000000..19d3f3c972b0 --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] +#![crate_name = "foo"] + +pub struct Struct; +pub trait Trait {} +impl Trait for Struct {} diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs new file mode 100644 index 000000000000..f52f3d791a71 --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -0,0 +1,32 @@ +//@ only-linux +//@ ignore-wasm32 +//@ ignore-wasm64 +// ignore-tidy-linelength + +// Verify that if the current crate depends on a different version of the same crate, *and* types +// and traits of the different versions are mixed, we produce diagnostic output and not an ICE. +// #133563 + +use run_make_support::{rust_lib_name, rustc}; + +fn main() { + rustc().input("foo-prev.rs").run(); + + rustc() + .extra_filename("current") + .metadata("current") + .input("foo-current.rs") + .extern_("foo", rust_lib_name("foo")) + .run_fail() + .assert_stderr_contains(r#" +note: there are multiple different versions of crate `foo` in the dependency graph + --> foo-current.rs:7:1 + | +4 | extern crate foo; + | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate +5 | +6 | pub struct Struct; + | ----------------- this type implements the required trait +7 | pub trait Trait {} + | ^^^^^^^^^^^^^^^ this is the required trait"#); +} From 3c9daca1d159930adada5ac843b00b24e7bd0d24 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 28 Nov 2024 18:57:00 +0100 Subject: [PATCH 171/330] Bump nightly version -> 2024-11-28 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 0a2e9d89b6e8..fb159ca2ae03 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2024-11-14" +channel = "nightly-2024-11-28" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" From 5fb924f3340cdacb4e67ff3e6e0ab42857c0ab5f Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 28 Nov 2024 18:57:52 +0100 Subject: [PATCH 172/330] Bump Clippy version -> 0.1.85 --- Cargo.toml | 4 ++-- clippy_config/Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_utils/Cargo.toml | 2 +- clippy_utils/README.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 79b9af7b0bf3..bb259c77ee37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy" # begin autogenerated version -version = "0.1.84" +version = "0.1.85" # end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" @@ -29,7 +29,7 @@ rustc_tools_util = "0.4.0" tempfile = { version = "3.3", optional = true } termize = "0.1" color-print = "0.3.4" -anstream = "0.6.0" +anstream = "0.6.18" [dev-dependencies] cargo_metadata = "0.18.1" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index d1158b48e921..3f18a0bc7d25 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_config" # begin autogenerated version -version = "0.1.84" +version = "0.1.85" # end autogenerated version edition = "2021" publish = false diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index be99dcc2c7c5..c1f8e82f6988 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin autogenerated version -version = "0.1.84" +version = "0.1.85" # end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 4f95889a53a7..945827c98c17 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_utils" # begin autogenerated version -version = "0.1.84" +version = "0.1.85" # end autogenerated version edition = "2021" description = "Helpful tools for writing lints, provided as they are used in Clippy" diff --git a/clippy_utils/README.md b/clippy_utils/README.md index fb1a3f13f8cb..61476a82ba00 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2024-11-14 +nightly-2024-11-28 ``` From 0c8e36bb3052b217aebcd8bd2154cc31618caf4f Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 29 Nov 2024 03:01:33 +0900 Subject: [PATCH 173/330] Fix target_feature handling in freg of LoongArch inline assembly --- compiler/rustc_target/src/asm/loongarch.rs | 2 +- .../bad-reg.loongarch64_lp64d.stderr | 38 ++++++++++++ .../bad-reg.loongarch64_lp64s.stderr | 62 +++++++++++++++++++ tests/ui/asm/loongarch/bad-reg.rs | 45 ++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr create mode 100644 tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr create mode 100644 tests/ui/asm/loongarch/bad-reg.rs diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs index b1c01d27cadd..b4ea6fc592a8 100644 --- a/compiler/rustc_target/src/asm/loongarch.rs +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -38,7 +38,7 @@ impl LoongArchInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, - Self::freg => types! { _: F32, F64; }, + Self::freg => types! { f: F32; d: F64; }, } } } diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr new file mode 100644 index 000000000000..0e5441196501 --- /dev/null +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr @@ -0,0 +1,38 @@ +error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:22:18 + | +LL | asm!("", out("$r0") _); + | ^^^^^^^^^^^^ + +error: invalid register `$tp`: reserved for TLS + --> $DIR/bad-reg.rs:24:18 + | +LL | asm!("", out("$tp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:26:18 + | +LL | asm!("", out("$sp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r21`: reserved by the ABI + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", out("$r21") _); + | ^^^^^^^^^^^^^ + +error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("$fp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("$r31") _); + | ^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr new file mode 100644 index 000000000000..6d0410dc6a13 --- /dev/null +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr @@ -0,0 +1,62 @@ +error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:22:18 + | +LL | asm!("", out("$r0") _); + | ^^^^^^^^^^^^ + +error: invalid register `$tp`: reserved for TLS + --> $DIR/bad-reg.rs:24:18 + | +LL | asm!("", out("$tp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:26:18 + | +LL | asm!("", out("$sp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r21`: reserved by the ABI + --> $DIR/bad-reg.rs:28:18 + | +LL | asm!("", out("$r21") _); + | ^^^^^^^^^^^^^ + +error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:30:18 + | +LL | asm!("", out("$fp") _); + | ^^^^^^^^^^^^ + +error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm + --> $DIR/bad-reg.rs:32:18 + | +LL | asm!("", out("$r31") _); + | ^^^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:36:26 + | +LL | asm!("/* {} */", in(freg) f); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:38:26 + | +LL | asm!("/* {} */", out(freg) _); + | ^^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:40:26 + | +LL | asm!("/* {} */", in(freg) d); + | ^^^^^^^^^^ + +error: register class `freg` requires at least one of the following target features: d, f + --> $DIR/bad-reg.rs:42:26 + | +LL | asm!("/* {} */", out(freg) d); + | ^^^^^^^^^^^ + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs new file mode 100644 index 000000000000..c5288cc78b71 --- /dev/null +++ b/tests/ui/asm/loongarch/bad-reg.rs @@ -0,0 +1,45 @@ +//@ add-core-stubs +//@ needs-asm-support +//@ revisions: loongarch64_lp64d loongarch64_lp64s +//@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu +//@[loongarch64_lp64d] needs-llvm-components: loongarch +//@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat +//@[loongarch64_lp64s] needs-llvm-components: loongarch + +#![crate_type = "lib"] +#![feature(no_core, rustc_attrs)] +#![no_core] + +extern crate minicore; +use minicore::*; + +fn f() { + let mut x = 0; + let mut f = 0.0_f32; + let mut d = 0.0_f64; + unsafe { + // Unsupported registers + asm!("", out("$r0") _); + //~^ ERROR constant zero cannot be used as an operand for inline asm + asm!("", out("$tp") _); + //~^ ERROR invalid register `$tp`: reserved for TLS + asm!("", out("$sp") _); + //~^ ERROR invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm + asm!("", out("$r21") _); + //~^ ERROR invalid register `$r21`: reserved by the ABI + asm!("", out("$fp") _); + //~^ ERROR invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm + asm!("", out("$r31") _); + //~^ ERROR invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm + + asm!("", out("$f0") _); // ok + asm!("/* {} */", in(freg) f); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", out(freg) _); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", in(freg) d); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + asm!("/* {} */", out(freg) d); + //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f + } +} From df8feb5067f99e20059c7ee8021d9ba5273bfe68 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 29 Nov 2024 03:10:07 +0900 Subject: [PATCH 174/330] Support floats in input/output in vector registers of PowerPC inline assembly --- compiler/rustc_codegen_llvm/src/asm.rs | 42 ++++++++++++ compiler/rustc_target/src/asm/powerpc.rs | 4 +- .../asm-experimental-arch.md | 2 +- tests/assembly/asm/powerpc-types.rs | 66 +++++++++++++++++++ tests/ui/asm/powerpc/bad-reg.aix64.stderr | 6 +- tests/ui/asm/powerpc/bad-reg.powerpc64.stderr | 6 +- .../ui/asm/powerpc/bad-reg.powerpc64le.stderr | 6 +- 7 files changed, 120 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 1483d576362b..d1804cb49ad1 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1040,6 +1040,26 @@ fn llvm_fixup_input<'ll, 'tcx>( let value = bx.or(value, bx.const_u32(0xFFFF_0000)); bx.bitcast(value, bx.type_f32()) } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + let value = bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_f32(), 4)), + value, + bx.const_usize(0), + ); + bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + let value = bx.insert_element( + bx.const_undef(bx.type_vector(bx.type_f64(), 2)), + value, + bx.const_usize(0), + ); + bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)) + } _ => value, } } @@ -1175,6 +1195,18 @@ fn llvm_fixup_output<'ll, 'tcx>( let value = bx.trunc(value, bx.type_i16()); bx.bitcast(value, bx.type_f16()) } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + let value = bx.bitcast(value, bx.type_vector(bx.type_f32(), 4)); + bx.extract_element(value, bx.const_usize(0)) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + let value = bx.bitcast(value, bx.type_vector(bx.type_f64(), 2)); + bx.extract_element(value, bx.const_usize(0)) + } _ => value, } } @@ -1299,6 +1331,16 @@ fn llvm_fixup_output_type<'ll, 'tcx>( { cx.type_f32() } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F32) => + { + cx.type_vector(cx.type_f32(), 4) + } + (PowerPC(PowerPCInlineAsmRegClass::vreg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F64) => + { + cx.type_vector(cx.type_f64(), 2) + } _ => layout.llvm_type(cx), } } diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index a5a96b87e367..f3934afa6d94 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -51,10 +51,10 @@ impl PowerPCInlineAsmRegClass { } } Self::freg => types! { _: F32, F64; }, - // FIXME: vsx also supports integers and floats: https://github.com/rust-lang/rust/pull/131551#discussion_r1797651773 + // FIXME: vsx also supports integers?: https://github.com/rust-lang/rust/pull/131551#discussion_r1862535963 Self::vreg => types! { altivec: VecI8(16), VecI16(8), VecI32(4), VecF32(4); - vsx: VecI64(2), VecF64(2); + vsx: F32, F64, VecI64(2), VecF64(2); }, Self::cr | Self::xer => &[], } diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index f2d0caa5e37c..c2f4170d7d29 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -76,7 +76,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) | | PowerPC | `freg` | None | `f32`, `f64` | | PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` | -| PowerPC | `vreg` | `vsx` | `i64x2`, `f64x2` | +| PowerPC | `vreg` | `vsx` | `f32`, `f64`, `i64x2`, `f64x2` | | PowerPC | `cr` | N/A | Only clobbers | | PowerPC | `xer` | N/A | Only clobbers | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index d67e0f66f66f..aa35c4d88658 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -225,6 +225,28 @@ check!(vreg_f32x4, f32x4, vreg, "vmr"); #[cfg(vsx)] check!(vreg_f64x2, f64x2, vreg, "vmr"); +// powerpc_vsx-LABEL: vreg_f32: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f32, f32, vreg, "vmr"); + +// powerpc_vsx-LABEL: vreg_f64: +// powerpc_vsx: #APP +// powerpc_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr {{[0-9]+}}, {{[0-9]+}} +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check!(vreg_f64, f64, vreg, "vmr"); + // CHECK-LABEL: reg_i8_r0: // CHECK: #APP // CHECK: mr 0, 0 @@ -365,6 +387,28 @@ check_reg!(vreg_f32x4_v0, f32x4, "0", "v0", "vmr"); #[cfg(vsx)] check_reg!(vreg_f64x2_v0, f64x2, "0", "v0", "vmr"); +// powerpc_vsx-LABEL: vreg_f32_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f32_v0, f32, "0", "v0", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64_v0: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 0, 0 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64_v0: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 0, 0 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64_v0, f64, "0", "v0", "vmr"); + // powerpc_altivec-LABEL: vreg_i8x16_v18: // powerpc_altivec: #APP // powerpc_altivec: vmr 18, 18 @@ -430,3 +474,25 @@ check_reg!(vreg_f32x4_v18, f32x4, "18", "v18", "vmr"); // powerpc64_vsx: #NO_APP #[cfg(vsx)] check_reg!(vreg_f64x2_v18, f64x2, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f32_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f32_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f32_v18, f32, "18", "v18", "vmr"); + +// powerpc_vsx-LABEL: vreg_f64_v18: +// powerpc_vsx: #APP +// powerpc_vsx: vmr 18, 18 +// powerpc_vsx: #NO_APP +// powerpc64_vsx-LABEL: vreg_f64_v18: +// powerpc64_vsx: #APP +// powerpc64_vsx: vmr 18, 18 +// powerpc64_vsx: #NO_APP +#[cfg(vsx)] +check_reg!(vreg_f64_v18, f64, "18", "v18", "vmr"); diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr index 332bdf0ff546..036641951cc9 100644 --- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -170,7 +170,7 @@ error: type `i32` cannot be used with this register class LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:79:28 @@ -178,7 +178,7 @@ error: type `i32` cannot be used with this register class LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:87:35 @@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:109:27 diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr index 9e0dd80b3dca..6a9d552bfe29 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:79:28 @@ -194,7 +194,7 @@ error: type `i32` cannot be used with this register class LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: `vsx` target feature is not enabled --> $DIR/bad-reg.rs:84:35 @@ -210,7 +210,7 @@ error: type `i32` cannot be used with this register class LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:109:27 diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr index 332bdf0ff546..036641951cc9 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -170,7 +170,7 @@ error: type `i32` cannot be used with this register class LL | asm!("", in("v0") x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:79:28 @@ -178,7 +178,7 @@ error: type `i32` cannot be used with this register class LL | asm!("", out("v0") x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:87:35 @@ -186,7 +186,7 @@ error: type `i32` cannot be used with this register class LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is available | ^ | - = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, i64x2, f64x2 + = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f32, f64, i64x2, f64x2 error: type `i32` cannot be used with this register class --> $DIR/bad-reg.rs:109:27 From 315b47ece33ed7c05e021f9cdf66b0431335f310 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 28 Nov 2024 19:39:15 +0100 Subject: [PATCH 175/330] Update Cargo.lock --- Cargo.lock | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29176a3ae8e2..a5fdcba0e637 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -536,7 +536,7 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clippy" -version = "0.1.84" +version = "0.1.85" dependencies = [ "anstream", "cargo_metadata", @@ -567,8 +567,9 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.84" +version = "0.1.85" dependencies = [ + "clippy_utils", "itertools", "serde", "toml 0.7.8", @@ -580,6 +581,7 @@ name = "clippy_dev" version = "0.0.1" dependencies = [ "aho-corasick", + "chrono", "clap", "indoc", "itertools", @@ -590,7 +592,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.84" +version = "0.1.85" dependencies = [ "arrayvec", "cargo_metadata", @@ -613,12 +615,12 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.84" +version = "0.1.85" dependencies = [ "arrayvec", - "clippy_config", "itertools", "rustc_apfloat", + "serde", ] [[package]] From 4a216a25d143e88eefac2655c1fce042571e1f6e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 23 Nov 2024 13:19:17 -0500 Subject: [PATCH 176/330] Share inline(never) generics across crates This reduces code sizes and better respects programmer intent when marking inline(never). Previously such a marking was essentially ignored for generic functions, as we'd still inline them in remote crates. --- Cargo.lock | 1 + compiler/rustc_codegen_llvm/src/callee.rs | 5 ++- .../src/back/symbol_export.rs | 12 ++++++- compiler/rustc_middle/src/mir/mono.rs | 7 ++++ compiler/rustc_middle/src/ty/context.rs | 2 -- compiler/rustc_middle/src/ty/instance.rs | 18 +++++++---- compiler/rustc_monomorphize/Cargo.toml | 1 + .../rustc_monomorphize/src/partitioning.rs | 32 ++++++++++++++----- library/alloc/src/raw_vec.rs | 4 ++- library/std/src/lib.rs | 1 + library/std/src/panicking.rs | 16 ++++++++++ .../auxiliary/cgu_generic_function.rs | 11 +++++++ tests/codegen/avr/avr-func-addrspace.rs | 2 +- tests/codegen/issues/issue-13018.rs | 5 ++- .../naked-symbol-visibility/a_rust_dylib.rs | 4 +-- .../run-make/naked-symbol-visibility/rmake.rs | 6 ++-- .../ui/panics/issue-47429-short-backtraces.rs | 11 ++++--- ...> issue-47429-short-backtraces.run.stderr} | 2 +- ...issue-47429-short-backtraces.v0.run.stderr | 6 ---- tests/ui/panics/runtime-switch.rs | 11 ++++--- ...y.run.stderr => runtime-switch.run.stderr} | 2 +- tests/ui/panics/runtime-switch.v0.run.stderr | 6 ---- .../short-ice-remove-middle-frames-2.rs | 5 +++ ...hort-ice-remove-middle-frames-2.run.stderr | 2 +- .../panics/short-ice-remove-middle-frames.rs | 5 +++ .../short-ice-remove-middle-frames.run.stderr | 2 +- 26 files changed, 127 insertions(+), 52 deletions(-) rename tests/ui/panics/{issue-47429-short-backtraces.legacy.run.stderr => issue-47429-short-backtraces.run.stderr} (98%) delete mode 100644 tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr rename tests/ui/panics/{runtime-switch.legacy.run.stderr => runtime-switch.run.stderr} (76%) delete mode 100644 tests/ui/panics/runtime-switch.v0.run.stderr diff --git a/Cargo.lock b/Cargo.lock index 29176a3ae8e2..351998a1846c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4137,6 +4137,7 @@ name = "rustc_monomorphize" version = "0.0.0" dependencies = [ "rustc_abi", + "rustc_attr", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index e0a2de3366c0..ec77f32caf49 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -104,7 +104,10 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t let is_hidden = if is_generic { // This is a monomorphization of a generic function. - if !cx.tcx.sess.opts.share_generics() { + if !(cx.tcx.sess.opts.share_generics() + || tcx.codegen_fn_attrs(instance_def_id).inline + == rustc_attr::InlineAttr::Never) + { // When not sharing generics, all instances are in the same // crate and have hidden visibility. true diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d9152c5d0807..788a8a13b3ee 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -282,7 +282,7 @@ fn exported_symbols_provider_local( })); } - if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() { + if tcx.local_crate_exports_generics() { use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; use rustc_middle::ty::InstanceKind; @@ -310,6 +310,16 @@ fn exported_symbols_provider_local( continue; } + if !tcx.sess.opts.share_generics() { + if tcx.codegen_fn_attrs(mono_item.def_id()).inline == rustc_attr::InlineAttr::Never + { + // this is OK, we explicitly allow sharing inline(never) across crates even + // without share-generics. + } else { + continue; + } + } + match *mono_item { MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => { if args.non_erasable_generics().next().is_some() { diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 244d22d082f4..161716610fe6 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -111,6 +111,13 @@ impl<'tcx> MonoItem<'tcx> { return InstantiationMode::GloballyShared { may_conflict: false }; } + if let InlineAttr::Never = tcx.codegen_fn_attrs(instance.def_id()).inline + && self.is_generic_fn() + { + // Upgrade inline(never) to a globally shared instance. + return InstantiationMode::GloballyShared { may_conflict: true }; + } + // At this point we don't have explicit linkage and we're an // inlined function. If we're inlining into all CGUs then we'll // be creating a local copy per CGU. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5bf62a17c8e0..c3712271921c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1946,8 +1946,6 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn local_crate_exports_generics(self) -> bool { - debug_assert!(self.sess.opts.share_generics()); - self.crate_types().iter().any(|crate_type| { match crate_type { CrateType::Executable diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 73fd8aa5b6c2..3d4ce112a64a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -190,19 +190,23 @@ impl<'tcx> Instance<'tcx> { /// This method already takes into account the global `-Zshare-generics` /// setting, always returning `None` if `share-generics` is off. pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option { - // If we are not in share generics mode, we don't link to upstream - // monomorphizations but always instantiate our own internal versions - // instead. - if !tcx.sess.opts.share_generics() { - return None; - } - // If this is an item that is defined in the local crate, no upstream // crate can know about it/provide a monomorphization. if self.def_id().is_local() { return None; } + // If we are not in share generics mode, we don't link to upstream + // monomorphizations but always instantiate our own internal versions + // instead. + if !tcx.sess.opts.share_generics() + // However, if the def_id is marked inline(never), then it's fine to just reuse the + // upstream monomorphization. + && tcx.codegen_fn_attrs(self.def_id()).inline != rustc_attr::InlineAttr::Never + { + return None; + } + // If this a non-generic instance, it cannot be a shared monomorphization. self.args.non_erasable_generics().next()?; diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 6c881fd7e06b..e18441ea7fc9 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } +rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7240cfce0f7f..7ea4ded2b052 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -208,8 +208,8 @@ where // available to downstream crates. This depends on whether we are in // share-generics mode and whether the current crate can even have // downstream crates. - let export_generics = - cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics(); + let can_export_generics = cx.tcx.local_crate_exports_generics(); + let always_export_generics = can_export_generics && cx.tcx.sess.opts.share_generics(); let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx); let cgu_name_cache = &mut UnordMap::default(); @@ -249,7 +249,8 @@ where cx.tcx, &mono_item, &mut can_be_internalized, - export_generics, + can_export_generics, + always_export_generics, ); if visibility == Visibility::Hidden && can_be_internalized { internalization_candidates.insert(mono_item); @@ -739,12 +740,19 @@ fn mono_item_linkage_and_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, - export_generics: bool, + can_export_generics: bool, + always_export_generics: bool, ) -> (Linkage, Visibility) { if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) { return (explicit_linkage, Visibility::Default); } - let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics); + let vis = mono_item_visibility( + tcx, + mono_item, + can_be_internalized, + can_export_generics, + always_export_generics, + ); (Linkage::External, vis) } @@ -767,7 +775,8 @@ fn mono_item_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, - export_generics: bool, + can_export_generics: bool, + always_export_generics: bool, ) -> Visibility { let instance = match mono_item { // This is pretty complicated; see below. @@ -826,7 +835,11 @@ fn mono_item_visibility<'tcx>( // Upstream `DefId` instances get different handling than local ones. let Some(def_id) = def_id.as_local() else { - return if export_generics && is_generic { + return if is_generic + && (always_export_generics + || (can_export_generics + && tcx.codegen_fn_attrs(def_id).inline == rustc_attr::InlineAttr::Never)) + { // If it is an upstream monomorphization and we export generics, we must make // it available to downstream crates. *can_be_internalized = false; @@ -837,7 +850,10 @@ fn mono_item_visibility<'tcx>( }; if is_generic { - if export_generics { + if always_export_generics + || (can_export_generics + && tcx.codegen_fn_attrs(def_id).inline == rustc_attr::InlineAttr::Never) + { if tcx.is_unreachable_local_definition(def_id) { // This instance cannot be used from another crate. Visibility::Hidden diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 85a9120c7e25..51b2a0570d90 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -757,7 +757,9 @@ impl RawVecInner { } } -#[inline(never)] +// not marked inline(never) since we want optimizers to be able to observe the specifics of this +// function, see tests/codegen/vec-reserve-extend.rs. +#[cold] fn finish_grow( new_layout: Layout, current_memory: Option<(NonNull, Layout)>, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index cf99a618e552..314d9203ca10 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -362,6 +362,7 @@ #![feature(strict_provenance_atomic_ptr)] #![feature(sync_unsafe_cell)] #![feature(ub_checks)] +#![feature(used_with_arg)] // tidy-alphabetical-end // // Library features (alloc): diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index ac1f547c9143..97f800dddaa4 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -27,6 +27,22 @@ use crate::sys::backtrace; use crate::sys::stdio::panic_output; use crate::{fmt, intrinsics, process, thread}; +// This forces codegen of the function called by panic!() inside the std crate, rather than in +// downstream crates. Primarily this is useful for rustc's codegen tests, which rely on noticing +// complete removal of panic from generated IR. Since begin_panic is inline(never), it's only +// codegen'd once per crate-graph so this pushes that to std rather than our codegen test crates. +// +// (See https://github.com/rust-lang/rust/pull/123244 for more info on why). +// +// If this is causing problems we can also modify those codegen tests to use a crate type like +// cdylib which doesn't export "Rust" symbols to downstream linkage units. +#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")] +#[doc(hidden)] +#[allow(dead_code)] +#[used(compiler)] +pub static EMPTY_PANIC: fn(&'static str) -> ! = + begin_panic::<&'static str> as fn(&'static str) -> !; + // Binary interface to the panic runtime that the standard library depends on. // // The standard library is tagged with `#![needs_panic_runtime]` (introduced in diff --git a/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs b/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs index 3926f295742b..8bb78eb788a2 100644 --- a/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs +++ b/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs @@ -11,10 +11,21 @@ pub fn foo(x: T) -> (T, u32, i8) { #[inline(never)] fn bar(x: T) -> (T, Struct) { let _ = not_exported_and_not_generic(0); + exported_and_generic::(0); (x, Struct(1)) } +pub static F: fn(u32) -> u32 = exported_and_generic::; + // These should not contribute to the codegen items of other crates. + +// This is generic, but it's only instantiated with a u32 argument and that instantiation is present +// in the local crate (see F above). +#[inline(never)] +pub fn exported_and_generic(x: T) -> T { + x +} + #[inline(never)] pub fn exported_but_not_generic(x: i32) -> i64 { x as i64 diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index a2dcb1c09247..7a36490fe93b 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -86,7 +86,7 @@ pub extern "C" fn test() { // A call through the Fn trait must use address space 1. // - // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait() + // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait({{.*}}) call_through_fn_trait(&mut update_bar_value); // A call through a global variable must use address space 1. diff --git a/tests/codegen/issues/issue-13018.rs b/tests/codegen/issues/issue-13018.rs index 66282dc42749..a29452436d2c 100644 --- a/tests/codegen/issues/issue-13018.rs +++ b/tests/codegen/issues/issue-13018.rs @@ -2,7 +2,10 @@ // A drop([...].clone()) sequence on an Rc should be a no-op // In particular, no call to __rust_dealloc should be emitted -#![crate_type = "lib"] +// +// We use a cdylib since it's a leaf unit for Rust purposes, so doesn't codegen -Zshare-generics +// code. +#![crate_type = "cdylib"] use std::rc::Rc; pub fn foo(t: &Rc>) { diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs index 8dd19e613bff..f98a2036544c 100644 --- a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs @@ -1,4 +1,4 @@ -#![feature(naked_functions, asm_const, linkage)] +#![feature(naked_functions, linkage)] #![crate_type = "dylib"] use std::arch::naked_asm; @@ -38,7 +38,7 @@ pub extern "C" fn public_vanilla() -> u32 { #[naked] #[no_mangle] -pub extern "C" fn public_naked() -> u32 { +pub extern "C" fn public_naked_nongeneric() -> u32 { unsafe { naked_asm!("mov rax, 42", "ret") } } diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs index d026196f43ba..c69a9ef9eeb0 100644 --- a/tests/run-make/naked-symbol-visibility/rmake.rs +++ b/tests/run-make/naked-symbol-visibility/rmake.rs @@ -17,10 +17,12 @@ fn main() { not_exported(&rdylib, "private_naked"); global_function(&rdylib, "public_vanilla"); - global_function(&rdylib, "public_naked"); + global_function(&rdylib, "public_naked_nongeneric"); not_exported(&rdylib, "public_vanilla_generic"); - not_exported(&rdylib, "public_naked_generic"); + // #[naked] functions are implicitly #[inline(never)], so they get shared regardless of + // -Zshare-generics. + global_function(&rdylib, "public_naked_generic"); global_function(&rdylib, "vanilla_external_linkage"); global_function(&rdylib, "naked_external_linkage"); diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs index 97d2e22574af..0d216fdd6530 100644 --- a/tests/ui/panics/issue-47429-short-backtraces.rs +++ b/tests/ui/panics/issue-47429-short-backtraces.rs @@ -6,6 +6,12 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=1 +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" + //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test //@ ignore-android FIXME #17520 //@ ignore-openbsd no support for libbacktrace without filename @@ -14,11 +20,6 @@ //@ ignore-sgx no subprocess support //@ ignore-fuchsia Backtraces not symbolized -// NOTE(eddyb) output differs between symbol mangling schemes -//@ revisions: legacy v0 -//@ [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy -//@ [v0] compile-flags: -Csymbol-mangling-version=v0 - fn main() { panic!() } diff --git a/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.run.stderr similarity index 98% rename from tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr rename to tests/ui/panics/issue-47429-short-backtraces.run.stderr index dce91ce59e3a..1078a2fbc902 100644 --- a/tests/ui/panics/issue-47429-short-backtraces.legacy.run.stderr +++ b/tests/ui/panics/issue-47429-short-backtraces.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:23:5: +thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:24:5: explicit panic stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr deleted file mode 100644 index f458c7acb39f..000000000000 --- a/tests/ui/panics/issue-47429-short-backtraces.v0.run.stderr +++ /dev/null @@ -1,6 +0,0 @@ -thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:23:5: -explicit panic -stack backtrace: - 0: std::panicking::begin_panic::<&str> - 1: issue_47429_short_backtraces::main -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs index a4ef0dcd8a23..10dce2509093 100644 --- a/tests/ui/panics/runtime-switch.rs +++ b/tests/ui/panics/runtime-switch.rs @@ -6,6 +6,12 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=0 +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" + //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test //@ ignore-android FIXME #17520 //@ ignore-openbsd no support for libbacktrace without filename @@ -14,11 +20,6 @@ //@ ignore-sgx no subprocess support //@ ignore-fuchsia Backtrace not symbolized -// NOTE(eddyb) output differs between symbol mangling schemes -//@ revisions: legacy v0 -//@ [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy -//@ [v0] compile-flags: -Csymbol-mangling-version=v0 - #![feature(panic_backtrace_config)] fn main() { diff --git a/tests/ui/panics/runtime-switch.legacy.run.stderr b/tests/ui/panics/runtime-switch.run.stderr similarity index 76% rename from tests/ui/panics/runtime-switch.legacy.run.stderr rename to tests/ui/panics/runtime-switch.run.stderr index bd05b6cc00fb..abbb91eba60e 100644 --- a/tests/ui/panics/runtime-switch.legacy.run.stderr +++ b/tests/ui/panics/runtime-switch.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/runtime-switch.rs:26:5: +thread 'main' panicked at $DIR/runtime-switch.rs:27:5: explicit panic stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/runtime-switch.v0.run.stderr b/tests/ui/panics/runtime-switch.v0.run.stderr deleted file mode 100644 index 2078c356d5cd..000000000000 --- a/tests/ui/panics/runtime-switch.v0.run.stderr +++ /dev/null @@ -1,6 +0,0 @@ -thread 'main' panicked at $DIR/runtime-switch.rs:26:5: -explicit panic -stack backtrace: - 0: std::panicking::begin_panic::<&str> - 1: runtime_switch::main -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs index 6caad2212d49..c2f04cd122c7 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs @@ -9,6 +9,11 @@ //@ ignore-sgx Backtraces not symbolized //@ ignore-fuchsia Backtraces not symbolized //@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable. +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" /// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace` diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr index 2b648a0cad2e..67577f3568e9 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:61:5: debug!!! stack backtrace: 0: std::panicking::begin_panic diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs index 5f275d13cc4c..c035e7e69bc6 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.rs +++ b/tests/ui/panics/short-ice-remove-middle-frames.rs @@ -10,6 +10,11 @@ //@ ignore-fuchsia Backtraces not symbolized //@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable. +// This is needed to avoid test output differences across std being built with v0 symbols vs legacy +// symbols. +//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic" +// And this is for differences between std with and without debuginfo. +//@ normalize-stderr-test: "\n +at [^\n]+" -> "" #[inline(never)] fn __rust_begin_short_backtrace T>(f: F) -> T { diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr index 5b3726840967..63fa466ab24a 100644 --- a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr +++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5: +thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:57:5: debug!!! stack backtrace: 0: std::panicking::begin_panic From 76adf05cfbffd78fc3f9e123634e992a70798e8f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 29 Nov 2024 06:05:56 +1100 Subject: [PATCH 177/330] Rename `-Zparse-only`. I was surprised to find that running with `-Zparse-only` only parses the crate root file. Other files aren't parsed because that happens later during expansion. This commit renames the option and updates the help message to make this clearer. --- compiler/rustc_driver_impl/src/lib.rs | 4 +++- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/config.rs | 4 ++-- compiler/rustc_session/src/options.rs | 5 +++-- tests/ui/generic-associated-types/parse/in-trait-impl.rs | 2 +- tests/ui/generic-associated-types/parse/in-trait.rs | 2 +- tests/ui/impl-trait/impl-trait-plus-priority.rs | 2 +- tests/ui/parser/assoc/assoc-oddities-1.rs | 2 +- tests/ui/parser/assoc/assoc-oddities-2.rs | 2 +- tests/ui/parser/bounds-type.rs | 2 +- tests/ui/parser/impl-qpath.rs | 2 +- tests/ui/parser/issues/issue-17904.rs | 2 +- tests/ui/traits/const-traits/syntax.rs | 2 +- tests/ui/traits/const-traits/tilde-const-syntax.rs | 2 +- tests/ui/traits/const-traits/tilde-twice.rs | 2 +- 15 files changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 256266d2965d..ee5a05a0b9de 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -425,7 +425,9 @@ fn run_compiler( return early_exit(); } - if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() { + if sess.opts.unstable_opts.parse_crate_root_only + || sess.opts.unstable_opts.show_span.is_some() + { return early_exit(); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 6beae14100d9..c1b2d8562522 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -712,7 +712,7 @@ fn test_unstable_options_tracking_hash() { untracked!(no_analysis, true); untracked!(no_leak_check, true); untracked!(no_parallel_backend, true); - untracked!(parse_only, true); + untracked!(parse_crate_root_only, true); // `pre_link_arg` is omitted because it just forwards to `pre_link_args`. untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]); untracked!(print_codegen_stats, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0124397ea46f..cb6d539cdf94 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1208,7 +1208,7 @@ impl Options { /// Returns `true` if there will be an output file generated. pub fn will_create_output_file(&self) -> bool { - !self.unstable_opts.parse_only && // The file is just being parsed + !self.unstable_opts.parse_crate_root_only && // The file is just being parsed self.unstable_opts.ls.is_empty() // The file is just being queried } @@ -1864,7 +1864,7 @@ fn parse_output_types( matches: &getopts::Matches, ) -> OutputTypes { let mut output_types = BTreeMap::new(); - if !unstable_opts.parse_only { + if !unstable_opts.parse_crate_root_only { for list in matches.opt_strs("emit") { for output_type in list.split(',') { let (shorthand, path) = split_out_file_name(output_type); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a2d75917c826..47c191e67baa 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1937,8 +1937,9 @@ options! { "support compiling tests with panic=abort (default: no)"), panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], "panic strategy for panics in drops"), - parse_only: bool = (false, parse_bool, [UNTRACKED], - "parse only; do not compile, assemble, or link (default: no)"), + parse_crate_root_only: bool = (false, parse_bool, [UNTRACKED], + "parse the crate root file only; do not parse other files, compile, assemble, or link \ + (default: no)"), patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED], "nop padding at function entry"), plt: Option = (None, parse_opt_bool, [TRACKED], diff --git a/tests/ui/generic-associated-types/parse/in-trait-impl.rs b/tests/ui/generic-associated-types/parse/in-trait-impl.rs index 5ba42be35831..ef67fb18228f 100644 --- a/tests/ui/generic-associated-types/parse/in-trait-impl.rs +++ b/tests/ui/generic-associated-types/parse/in-trait-impl.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only impl Baz for T where T: Foo { type Quux<'a> = ::Bar<'a, 'static>; diff --git a/tests/ui/generic-associated-types/parse/in-trait.rs b/tests/ui/generic-associated-types/parse/in-trait.rs index 913eceec0dac..2add908d727d 100644 --- a/tests/ui/generic-associated-types/parse/in-trait.rs +++ b/tests/ui/generic-associated-types/parse/in-trait.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only use std::ops::Deref; use std::fmt::Debug; diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.rs b/tests/ui/impl-trait/impl-trait-plus-priority.rs index 5441a015ac0a..5575493a17d3 100644 --- a/tests/ui/impl-trait/impl-trait-plus-priority.rs +++ b/tests/ui/impl-trait/impl-trait-plus-priority.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only fn f() -> impl A + {} // OK fn f() -> impl A + B {} // OK diff --git a/tests/ui/parser/assoc/assoc-oddities-1.rs b/tests/ui/parser/assoc/assoc-oddities-1.rs index 246546ac0342..c1b305a4eeb2 100644 --- a/tests/ui/parser/assoc/assoc-oddities-1.rs +++ b/tests/ui/parser/assoc/assoc-oddities-1.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only fn main() { // following lines below parse and must not fail diff --git a/tests/ui/parser/assoc/assoc-oddities-2.rs b/tests/ui/parser/assoc/assoc-oddities-2.rs index aee2af41d62a..82cf7d79c0d5 100644 --- a/tests/ui/parser/assoc/assoc-oddities-2.rs +++ b/tests/ui/parser/assoc/assoc-oddities-2.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only fn main() { // see assoc-oddities-1 for explanation diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs index 7cee6def32f8..ec0e83c314e1 100644 --- a/tests/ui/parser/bounds-type.rs +++ b/tests/ui/parser/bounds-type.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only //@ edition: 2021 struct S< diff --git a/tests/ui/parser/impl-qpath.rs b/tests/ui/parser/impl-qpath.rs index d7c4989b6e4c..fed026792c9d 100644 --- a/tests/ui/parser/impl-qpath.rs +++ b/tests/ui/parser/impl-qpath.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only impl <*const u8>::AssocTy {} // OK impl ::AssocTy {} // OK diff --git a/tests/ui/parser/issues/issue-17904.rs b/tests/ui/parser/issues/issue-17904.rs index 6f77d4bb086f..99a3b1398988 100644 --- a/tests/ui/parser/issues/issue-17904.rs +++ b/tests/ui/parser/issues/issue-17904.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zparse-only +//@ compile-flags: -Zparse-crate-root-only struct Baz where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. struct Baz where U: Eq(U) -> R; // Notice this parses as well. diff --git a/tests/ui/traits/const-traits/syntax.rs b/tests/ui/traits/const-traits/syntax.rs index 1064713ac592..cfac6e0a93e3 100644 --- a/tests/ui/traits/const-traits/syntax.rs +++ b/tests/ui/traits/const-traits/syntax.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only //@ check-pass #![feature(const_trait_bound_opt_out)] diff --git a/tests/ui/traits/const-traits/tilde-const-syntax.rs b/tests/ui/traits/const-traits/tilde-const-syntax.rs index d65ecae3d067..f9944c426cce 100644 --- a/tests/ui/traits/const-traits/tilde-const-syntax.rs +++ b/tests/ui/traits/const-traits/tilde-const-syntax.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only //@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/tilde-twice.rs b/tests/ui/traits/const-traits/tilde-twice.rs index c3f9f8e67648..d341513b8a81 100644 --- a/tests/ui/traits/const-traits/tilde-twice.rs +++ b/tests/ui/traits/const-traits/tilde-twice.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Z parse-only +//@ compile-flags: -Z parse-crate-root-only #![feature(const_trait_impl)] From accdfa1e526af99c4c60412a12a9a8253eab5984 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 29 Nov 2024 06:08:48 +1100 Subject: [PATCH 178/330] Update `-Zshow-span` help message. To clarify how it works. --- compiler/rustc_session/src/options.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 47c191e67baa..25f75ae12e8e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2037,7 +2037,7 @@ written to standard error output)"), shell_argfiles: bool = (false, parse_bool, [UNTRACKED], "allow argument files to be specified with POSIX \"shell-style\" argument quoting"), show_span: Option = (None, parse_opt_string, [TRACKED], - "show spans for compiler debugging (expr|pat|ty)"), + "show spans in the crate root file, for compiler debugging (expr|pat|ty)"), simulate_remapped_rust_src_base: Option = (None, parse_opt_pathbuf, [TRACKED], "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \ to rust's source base directory. only meant for testing purposes"), From 7cf3f8ba7a4a7c8b9dc7a44ccc1702fa7d0d2d1c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Nov 2024 21:22:06 +0100 Subject: [PATCH 179/330] Do not emit `missing_doc_code_examples` rustdoc lint on module and a few other items --- .../passes/check_doc_test_visibility.rs | 11 ++++++-- .../coverage/doc-examples-json.stdout | 2 +- tests/rustdoc-ui/coverage/doc-examples.stdout | 4 +-- tests/rustdoc-ui/coverage/json.stdout | 2 +- tests/rustdoc-ui/lints/check.rs | 1 - tests/rustdoc-ui/lints/check.stderr | 28 ++++++------------- .../rustdoc-ui/lints/doc-without-codeblock.rs | 3 +- .../lints/doc-without-codeblock.stderr | 26 +++-------------- .../lints/lint-missing-doc-code-example.rs | 2 +- .../lint-missing-doc-code-example.stderr | 14 +++------- tests/rustdoc-ui/show-coverage-json.stdout | 2 +- tests/rustdoc-ui/show-coverage.stdout | 4 +-- 12 files changed, 35 insertions(+), 64 deletions(-) diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index bf851b278b82..c288a3cf2a47 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -60,8 +60,6 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - item.kind, clean::StructFieldItem(_) | clean::VariantItem(_) - | clean::AssocConstItem(..) - | clean::AssocTypeItem(..) | clean::TypeAliasItem(_) | clean::StaticItem(_) | clean::ConstantItem(..) @@ -69,6 +67,15 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::ImportItem(_) | clean::PrimitiveItem(_) | clean::KeywordItem + | clean::ModuleItem(_) + | clean::TraitAliasItem(_) + | clean::ForeignFunctionItem(..) + | clean::ForeignStaticItem(..) + | clean::ForeignTypeItem + | clean::AssocConstItem(..) + | clean::AssocTypeItem(..) + | clean::TyAssocConstItem(..) + | clean::TyAssocTypeItem(..) // check for trait impl | clean::ImplItem(box clean::Impl { trait_: Some(_), .. }) ) diff --git a/tests/rustdoc-ui/coverage/doc-examples-json.stdout b/tests/rustdoc-ui/coverage/doc-examples-json.stdout index 92f58556975a..070fed0783e7 100644 --- a/tests/rustdoc-ui/coverage/doc-examples-json.stdout +++ b/tests/rustdoc-ui/coverage/doc-examples-json.stdout @@ -1 +1 @@ -{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":2,"with_examples":1}} +{"$DIR/doc-examples-json.rs":{"total":3,"with_docs":2,"total_examples":1,"with_examples":1}} diff --git a/tests/rustdoc-ui/coverage/doc-examples.stdout b/tests/rustdoc-ui/coverage/doc-examples.stdout index 8188740f8739..793adeb35180 100644 --- a/tests/rustdoc-ui/coverage/doc-examples.stdout +++ b/tests/rustdoc-ui/coverage/doc-examples.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 1 | 25.0% | +| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 1 | 33.3% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 4 | 100.0% | 1 | 25.0% | +| Total | 4 | 100.0% | 1 | 33.3% | +-------------------------------------+------------+------------+------------+------------+ diff --git a/tests/rustdoc-ui/coverage/json.stdout b/tests/rustdoc-ui/coverage/json.stdout index c2be73ce3edd..25fd896baf1d 100644 --- a/tests/rustdoc-ui/coverage/json.stdout +++ b/tests/rustdoc-ui/coverage/json.stdout @@ -1 +1 @@ -{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":15,"with_examples":6}} +{"$DIR/json.rs":{"total":17,"with_docs":12,"total_examples":13,"with_examples":6}} diff --git a/tests/rustdoc-ui/lints/check.rs b/tests/rustdoc-ui/lints/check.rs index 391ba517077c..058c5d6c468f 100644 --- a/tests/rustdoc-ui/lints/check.rs +++ b/tests/rustdoc-ui/lints/check.rs @@ -4,7 +4,6 @@ #![feature(rustdoc_missing_doc_code_examples)] //~^ WARN -//~^^ WARN #![warn(missing_docs)] #![warn(rustdoc::missing_doc_code_examples)] diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr index acdb8128443f..f1f36e8830d6 100644 --- a/tests/rustdoc-ui/lints/check.stderr +++ b/tests/rustdoc-ui/lints/check.stderr @@ -4,19 +4,20 @@ warning: missing documentation for the crate LL | / #![feature(rustdoc_missing_doc_code_examples)] LL | | LL | | +LL | | #![warn(missing_docs)] ... | LL | | LL | | pub fn foo() {} | |_______________^ | note: the lint level is defined here - --> $DIR/check.rs:9:9 + --> $DIR/check.rs:8:9 | LL | #![warn(missing_docs)] | ^^^^^^^^^^^^ warning: missing documentation for a function - --> $DIR/check.rs:13:1 + --> $DIR/check.rs:12:1 | LL | pub fn foo() {} | ^^^^^^^^^^^^ @@ -26,34 +27,23 @@ warning: no documentation found for this crate's top-level module = help: The following guide may be of use: https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html note: the lint level is defined here - --> $DIR/check.rs:11:9 + --> $DIR/check.rs:10:9 | LL | #![warn(rustdoc::all)] | ^^^^^^^^^^^^ = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]` warning: missing code example in this documentation - --> $DIR/check.rs:5:1 + --> $DIR/check.rs:12:1 | -LL | / #![feature(rustdoc_missing_doc_code_examples)] -LL | | -LL | | -... | -LL | | -LL | | pub fn foo() {} - | |_______________^ +LL | pub fn foo() {} + | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/check.rs:10:9 + --> $DIR/check.rs:9:9 | LL | #![warn(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: missing code example in this documentation - --> $DIR/check.rs:13:1 - | -LL | pub fn foo() {} - | ^^^^^^^^^^^^^^^ - -warning: 5 warnings emitted +warning: 4 warnings emitted diff --git a/tests/rustdoc-ui/lints/doc-without-codeblock.rs b/tests/rustdoc-ui/lints/doc-without-codeblock.rs index 86d7c83d3359..ccb241d4037e 100644 --- a/tests/rustdoc-ui/lints/doc-without-codeblock.rs +++ b/tests/rustdoc-ui/lints/doc-without-codeblock.rs @@ -1,4 +1,4 @@ -#![feature(rustdoc_missing_doc_code_examples)] //~ ERROR missing code example in this documentation +#![feature(rustdoc_missing_doc_code_examples)] #![deny(rustdoc::missing_doc_code_examples)] /// Some docs. @@ -6,7 +6,6 @@ pub struct Foo; /// And then, the princess died. -//~^ ERROR missing code example in this documentation pub mod foo { /// Or maybe not because she saved herself! //~^ ERROR missing code example in this documentation diff --git a/tests/rustdoc-ui/lints/doc-without-codeblock.stderr b/tests/rustdoc-ui/lints/doc-without-codeblock.stderr index ebf2a2d54f75..d230f1606935 100644 --- a/tests/rustdoc-ui/lints/doc-without-codeblock.stderr +++ b/tests/rustdoc-ui/lints/doc-without-codeblock.stderr @@ -1,14 +1,8 @@ error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:1:1 + --> $DIR/doc-without-codeblock.rs:10:5 | -LL | / #![feature(rustdoc_missing_doc_code_examples)] -LL | | #![deny(rustdoc::missing_doc_code_examples)] -LL | | -LL | | /// Some docs. -... | -LL | | } -LL | | } - | |_^ +LL | /// Or maybe not because she saved herself! + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/doc-without-codeblock.rs:2:9 @@ -16,23 +10,11 @@ note: the lint level is defined here LL | #![deny(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:8:1 - | -LL | /// And then, the princess died. - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:11:5 - | -LL | /// Or maybe not because she saved herself! - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: missing code example in this documentation --> $DIR/doc-without-codeblock.rs:4:1 | LL | /// Some docs. | ^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs index 40f35728d79b..8e5c31d50edc 100644 --- a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs +++ b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.rs @@ -17,7 +17,7 @@ pub fn test() { } #[allow(missing_docs)] -pub mod module1 { //~ ERROR +pub mod module1 { } #[allow(rustdoc::missing_doc_code_examples)] diff --git a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr index f9331250154d..22533b9816a7 100644 --- a/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr +++ b/tests/rustdoc-ui/lints/lint-missing-doc-code-example.stderr @@ -1,8 +1,8 @@ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:20:1 + --> $DIR/lint-missing-doc-code-example.rs:38:3 | -LL | pub mod module1 { - | ^^^^^^^^^^^^^^^ +LL | /// doc + | ^^^^^^^ | note: the lint level is defined here --> $DIR/lint-missing-doc-code-example.rs:3:9 @@ -10,12 +10,6 @@ note: the lint level is defined here LL | #![deny(rustdoc::missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:38:3 - | -LL | /// doc - | ^^^^^^^ - error: missing code example in this documentation --> $DIR/lint-missing-doc-code-example.rs:50:1 | @@ -34,5 +28,5 @@ error: missing code example in this documentation LL | /// Doc | ^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/rustdoc-ui/show-coverage-json.stdout b/tests/rustdoc-ui/show-coverage-json.stdout index ed5b5a60212e..e6e882b2c57f 100644 --- a/tests/rustdoc-ui/show-coverage-json.stdout +++ b/tests/rustdoc-ui/show-coverage-json.stdout @@ -1 +1 @@ -{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":2,"with_examples":1}} +{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":1,"with_examples":1}} diff --git a/tests/rustdoc-ui/show-coverage.stdout b/tests/rustdoc-ui/show-coverage.stdout index b3b7679771f2..b9e0316545e7 100644 --- a/tests/rustdoc-ui/show-coverage.stdout +++ b/tests/rustdoc-ui/show-coverage.stdout @@ -1,7 +1,7 @@ +-------------------------------------+------------+------------+------------+------------+ | File | Documented | Percentage | Examples | Percentage | +-------------------------------------+------------+------------+------------+------------+ -| ...ests/rustdoc-ui/show-coverage.rs | 1 | 50.0% | 1 | 50.0% | +| ...ests/rustdoc-ui/show-coverage.rs | 1 | 50.0% | 1 | 100.0% | +-------------------------------------+------------+------------+------------+------------+ -| Total | 1 | 50.0% | 1 | 50.0% | +| Total | 1 | 50.0% | 1 | 100.0% | +-------------------------------------+------------+------------+------------+------------+ From c52d952a6aae3c850dba192a79662b990eb8dc11 Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Thu, 28 Nov 2024 20:31:08 +0100 Subject: [PATCH 180/330] add instructions for generating `flake.lock` to `envrc-flake` Previous setup instructions did not work without. (i.e. the envrc would not do anything, `nix flake show..` would provide unhelpful error) --- src/tools/nix-dev-shell/envrc-flake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/nix-dev-shell/envrc-flake b/src/tools/nix-dev-shell/envrc-flake index 218d88d8721f..9def420f05cb 100644 --- a/src/tools/nix-dev-shell/envrc-flake +++ b/src/tools/nix-dev-shell/envrc-flake @@ -1,7 +1,7 @@ # If you want to use this as an .envrc file to create a shell with necessery components # to develop rustc, use the following command in the root of the rusr checkout: # -# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && echo .envrc >> .git/info/exclude +# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && nix flake update --flake ./src/tools/nix-dev-shell && echo .envrc >> .git/info/exclude if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then use flake path:./src/tools/nix-dev-shell From 33f13f2ab575bb9d702217f25b9ea45fc527bbf2 Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Thu, 28 Nov 2024 20:34:30 +0100 Subject: [PATCH 181/330] ignore `/build` instead of `build/` in gitignore this does two things: 1. allows making `build` a symlink (which is not considered a directory by git, thus removal of trailing `/`). 2. removes the need to special case `rustc_mir_build/src/build` (leading `/` makes git only ignore the `build` in the root) --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 948133cd76e4..ce9db8b861d0 100644 --- a/.gitignore +++ b/.gitignore @@ -46,8 +46,7 @@ no_llvm_build /inst/ /llvm/ /mingw-build/ -build/ -!/compiler/rustc_mir_build/src/build/ +/build /build-rust-analyzer/ /dist/ /unicode-downloads From 8e7734978245522cbbd14e53e08e888faf031ded Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Thu, 28 Nov 2024 21:54:27 +0100 Subject: [PATCH 182/330] fix a comment with uneven number of backticks in rustc_mir_build this is funny though! apparently tidy parsed `.gitignore`, but did not recognize unignore lines (`!...`), so tidy was ignoring `rustc_mir_build` this whole time (at least for some lints?). --- compiler/rustc_mir_build/src/build/expr/as_rvalue.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3f89e337781e..c66af118453e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -231,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr }; let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> { - // We can use `ty::TypingEnv::fully_monomorphized()`` here + // We can use `ty::TypingEnv::fully_monomorphized()` here // as we only need it to compute the layout of a primitive. let range_val = Const::from_bits( this.tcx, From 727f6a6d132f24f3b72af57adf07c50c9d1721af Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 28 Nov 2024 21:41:34 +0000 Subject: [PATCH 183/330] Add +forced-atomics feature to esp32s2 --- .../rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs index 34d8383a6047..ae7bfbd03940 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs @@ -19,6 +19,7 @@ pub(crate) fn target() -> Target { cpu: "esp32-s2".into(), linker: Some("xtensa-esp32s2-elf-gcc".into()), max_atomic_width: Some(32), + features: "+forced-atomics".into(), ..xtensa::opts() }, } From d599d5a381ecceabd0b662af73982257545cbe1a Mon Sep 17 00:00:00 2001 From: Sanchith Hegde Date: Fri, 29 Nov 2024 03:50:26 +0530 Subject: [PATCH 184/330] fix: fix codeblocks in `PathBuf` example --- library/std/src/path.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 33a3e4332f37..d50e7f1b5e9b 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1158,6 +1158,7 @@ impl FusedIterator for Ancestors<'_> {} /// Note that `PathBuf` does not always sanitize arguments, for example /// [`push`] allows paths built from strings which include separators: /// +/// ``` /// use std::path::PathBuf; /// /// let mut path = PathBuf::new(); @@ -1166,6 +1167,7 @@ impl FusedIterator for Ancestors<'_> {} /// path.push("windows"); /// path.push(r"..\otherdir"); /// path.push("system32"); +/// ``` /// /// The behavior of `PathBuf` may be changed to a panic on such inputs /// in the future. [`Extend::extend`] should be used to add multi-part paths. From 6005d1c9f792f402afa6e355bf25615d05954a00 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 28 Nov 2024 09:47:37 -0800 Subject: [PATCH 185/330] Update more 2024 tests to remove -Zunstable-options --- .../doctest/doctest-output-include-fail.rs | 2 +- tests/rustdoc-ui/doctest/doctest-output.rs | 2 +- .../relative-path-include-bytes-132203.rs | 2 +- tests/ui/coroutine/async-gen-deduce-yield.rs | 2 +- .../coroutine/async-gen-yield-ty-is-unit.rs | 2 +- tests/ui/drop/drop_order.rs | 1 - ...nt-if-let-rescope-gated.edition2021.stderr | 6 ++--- tests/ui/drop/lint-if-let-rescope-gated.rs | 1 - ...xpr-drop-order-negative.edition2024.stderr | 2 +- .../ui/drop/tail-expr-drop-order-negative.rs | 1 - .../never-type-fallback-breaking.e2021.fixed | 1 - .../never-type-fallback-breaking.e2021.stderr | 12 +++++----- .../never-type-fallback-breaking.e2024.stderr | 10 ++++---- .../editions/never-type-fallback-breaking.rs | 1 - tests/ui/editions/never-type-fallback.rs | 1 - tests/ui/hello.rs | 2 -- tests/ui/impl-trait/variance.e2024.stderr | 8 +++---- tests/ui/impl-trait/variance.new.stderr | 8 +++---- tests/ui/impl-trait/variance.old.stderr | 8 +++---- tests/ui/impl-trait/variance.rs | 1 - tests/ui/lifetimes/raw/gen-lt.e2024.stderr | 2 +- tests/ui/lifetimes/raw/gen-lt.rs | 1 - .../refcell-in-tail-expr.edition2021.stderr | 2 +- tests/ui/lifetimes/refcell-in-tail-expr.rs | 1 - ...rter-tail-expr-lifetime.edition2021.stderr | 2 +- .../lifetimes/shorter-tail-expr-lifetime.rs | 1 - .../ui/lifetimes/tail-expr-lock-poisoning.rs | 1 - .../lifetimes/temporary-lifetime-extension.rs | 1 - tests/ui/lint/static-mut-refs.e2021.stderr | 24 +++++++++---------- tests/ui/lint/static-mut-refs.e2024.stderr | 24 +++++++++---------- tests/ui/lint/static-mut-refs.rs | 1 - .../macro-missing-fragment.e2015.stderr | 22 ++++++++--------- .../macro-missing-fragment.e2024.stderr | 8 +++---- tests/ui/macros/macro-missing-fragment.rs | 1 - tests/ui/mir/mir_let_chains_drop_order.rs | 1 - ...-fallback-flowing-into-unsafe.e2015.stderr | 20 ++++++++-------- ...-fallback-flowing-into-unsafe.e2024.stderr | 22 ++++++++--------- ...never-type-fallback-flowing-into-unsafe.rs | 1 - .../issue-54556-niconii.edition2021.stderr | 2 +- tests/ui/nll/issue-54556-niconii.rs | 1 - .../proc-macro/macro_rules_edition_from_pm.rs | 1 - .../future-poll-already-future.rs | 1 - .../future-poll-async-block.e2021.fixed | 1 - .../future-poll-async-block.e2021.stderr | 4 ++-- .../future-poll-async-block.rs | 1 - .../future-poll-not-future-pinned.e2021.fixed | 1 - ...future-poll-not-future-pinned.e2021.stderr | 4 ++-- .../future-poll-not-future-pinned.rs | 1 - .../future-poll-not-future.rs | 1 - .../into-future-adt.e2021.fixed | 1 - .../into-future-adt.e2021.stderr | 4 ++-- .../prelude-migration/into-future-adt.rs | 1 - .../into-future-already-into-future.rs | 1 - .../into-future-not-into-future.e2021.fixed | 1 - .../into-future-not-into-future.e2021.stderr | 4 ++-- .../into-future-not-into-future.rs | 1 - .../unsafe-attribute-marked.rs | 1 - .../unsafe-attributes-from-pm.rs | 1 - .../unsafe-attributes.edition2024.stderr | 2 +- .../unsafe-attributes/unsafe-attributes.rs | 1 - .../rust-2024/unsafe-before_exec.e2024.stderr | 2 +- tests/ui/rust-2024/unsafe-before_exec.rs | 1 - tests/ui/rust-2024/unsafe-env.e2021.stderr | 12 +++++----- tests/ui/rust-2024/unsafe-env.e2024.stderr | 20 ++++++++-------- tests/ui/rust-2024/unsafe-env.rs | 1 - .../extern-items-unsafe.edition2021.stderr | 4 ++-- .../extern-items-unsafe.edition2024.stderr | 4 ++-- .../extern-items-unsafe.rs | 1 - .../extern-items.edition2024.stderr | 2 +- .../unsafe-extern-blocks/extern-items.rs | 1 - .../unsafe-extern-blocks/safe-items.rs | 1 - ...-unadorned-extern-block.edition2021.stderr | 4 ++-- ...-unadorned-extern-block.edition2024.stderr | 6 ++--- .../safe-unsafe-on-unadorned-extern-block.rs | 1 - .../unsafe-items.edition2021.stderr | 4 ++-- .../unsafe-items.edition2024.stderr | 4 ++-- .../unsafe-extern-blocks/unsafe-items.rs | 1 - 77 files changed, 136 insertions(+), 177 deletions(-) diff --git a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs index bae61992eb21..58612b682a00 100644 --- a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs +++ b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs @@ -1,5 +1,5 @@ //@ edition:2024 -//@ compile-flags:--test --test-args=--test-threads=1 -Z unstable-options +//@ compile-flags:--test --test-args=--test-threads=1 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 diff --git a/tests/rustdoc-ui/doctest/doctest-output.rs b/tests/rustdoc-ui/doctest/doctest-output.rs index 0e5ccf0b090b..946bc550b12f 100644 --- a/tests/rustdoc-ui/doctest/doctest-output.rs +++ b/tests/rustdoc-ui/doctest/doctest-output.rs @@ -4,7 +4,7 @@ //@[edition2015]compile-flags:--test --test-args=--test-threads=1 //@[edition2024]edition:2015 //@[edition2024]aux-build:extern_macros.rs -//@[edition2024]compile-flags:--test --test-args=--test-threads=1 -Z unstable-options +//@[edition2024]compile-flags:--test --test-args=--test-threads=1 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ check-pass diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs index b393d126306a..5a1d4d0a60dd 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs @@ -6,7 +6,7 @@ //@[edition2015]compile-flags:--test --test-args=--test-threads=1 //@[edition2024]edition:2024 //@[edition2024]check-pass -//@[edition2024]compile-flags:--test --test-args=--test-threads=1 -Z unstable-options +//@[edition2024]compile-flags:--test --test-args=--test-threads=1 //@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs index aee920e97737..f85e4a52e9b9 100644 --- a/tests/ui/coroutine/async-gen-deduce-yield.rs +++ b/tests/ui/coroutine/async-gen-deduce-yield.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 -Zunstable-options +//@ compile-flags: --edition 2024 //@ check-pass #![feature(async_iterator, gen_blocks)] diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index 62b9bafcd60a..3875e26b544c 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 -Zunstable-options +//@ compile-flags: --edition 2024 //@ check-pass #![feature(async_iterator, gen_blocks, noop_waker)] diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index 7a999c7c330a..d1a5b9bc5e26 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -2,7 +2,6 @@ //@ compile-flags: -Z validate-mir //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 -//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] edition: 2024 #![feature(let_chains)] diff --git a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr index 48b7f3e11a68..7f9a01599505 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr @@ -1,5 +1,5 @@ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:27:8 + --> $DIR/lint-if-let-rescope-gated.rs:26:8 | LL | if let Some(_value) = Droppy.get() { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -9,12 +9,12 @@ LL | if let Some(_value) = Droppy.get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:31:5 + --> $DIR/lint-if-let-rescope-gated.rs:30:5 | LL | } else { | ^ note: the lint level is defined here - --> $DIR/lint-if-let-rescope-gated.rs:11:9 + --> $DIR/lint-if-let-rescope-gated.rs:10:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs index ba0246573b40..f5538a37eef8 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.rs +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -5,7 +5,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] check-pass #![deny(if_let_rescope)] diff --git a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr index bcce796570e2..2c0b238eb5f2 100644 --- a/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr +++ b/tests/ui/drop/tail-expr-drop-order-negative.edition2024.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/tail-expr-drop-order-negative.rs:9:15 + --> $DIR/tail-expr-drop-order-negative.rs:8:15 | LL | x.replace(std::cell::RefCell::new(123).borrow()).is_some() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement diff --git a/tests/ui/drop/tail-expr-drop-order-negative.rs b/tests/ui/drop/tail-expr-drop-order-negative.rs index 5ad04d0a67ef..3b20691f8eaa 100644 --- a/tests/ui/drop/tail-expr-drop-order-negative.rs +++ b/tests/ui/drop/tail-expr-drop-order-negative.rs @@ -1,5 +1,4 @@ //@ revisions: edition2021 edition2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] edition: 2024 //@ [edition2021] check-pass diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed index 75bc598d17bd..91d30de74c7c 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -2,7 +2,6 @@ // //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options // //@[e2021] run-pass //@[e2021] run-rustfix diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 454e88d4569b..6fdb548c4317 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -1,5 +1,5 @@ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:17:1 + --> $DIR/never-type-fallback-breaking.rs:16:1 | LL | fn m() { | ^^^^^^ @@ -8,7 +8,7 @@ LL | fn m() { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:21:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | let x: () = match true { | ++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:29:1 + --> $DIR/never-type-fallback-breaking.rs:28:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | fn q() -> Option<()> { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:36:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | deserialize::<()>()?; | ++++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:46:1 + --> $DIR/never-type-fallback-breaking.rs:45:1 | LL | fn meow() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | fn meow() -> Result<(), ()> { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `(): From` will fail - --> $DIR/never-type-fallback-breaking.rs:49:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index 6258247f8b28..9d79dfb4099f 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:21:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -8,7 +8,7 @@ LL | true => Default::default(), = help: did you intend to use the type `()` here instead? error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:36:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -16,13 +16,13 @@ LL | deserialize()?; = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `deserialize` - --> $DIR/never-type-fallback-breaking.rs:32:23 + --> $DIR/never-type-fallback-breaking.rs:31:23 | LL | fn deserialize() -> Option { | ^^^^^^^ required by this bound in `deserialize` error[E0277]: the trait bound `(): From` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:49:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ the trait `From` is not implemented for `()` @@ -39,7 +39,7 @@ LL | help(1)?; and 4 others = note: required for `!` to implement `Into<()>` note: required by a bound in `help` - --> $DIR/never-type-fallback-breaking.rs:43:20 + --> $DIR/never-type-fallback-breaking.rs:42:20 | LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { | ^^^^^^^^ required by this bound in `help` diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 32e83e741393..24e33ff6bf6b 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -2,7 +2,6 @@ // //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options // //@[e2021] run-pass //@[e2021] run-rustfix diff --git a/tests/ui/editions/never-type-fallback.rs b/tests/ui/editions/never-type-fallback.rs index a5b75219295c..987fb305763f 100644 --- a/tests/ui/editions/never-type-fallback.rs +++ b/tests/ui/editions/never-type-fallback.rs @@ -2,7 +2,6 @@ // //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options // //@ run-pass //@ check-run-results diff --git a/tests/ui/hello.rs b/tests/ui/hello.rs index d23cbb611571..f329ee086f90 100644 --- a/tests/ui/hello.rs +++ b/tests/ui/hello.rs @@ -5,8 +5,6 @@ //@[e2021] edition:2021 //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options - fn main() { println!("hello"); } diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr index 011ab3259c47..361a165da66f 100644 --- a/tests/ui/impl-trait/variance.e2024.stderr +++ b/tests/ui/impl-trait/variance.e2024.stderr @@ -1,23 +1,23 @@ error: ['a: *, 'a: o] - --> $DIR/variance.rs:14:36 + --> $DIR/variance.rs:13:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ error: ['a: *, 'a: o] - --> $DIR/variance.rs:19:32 + --> $DIR/variance.rs:18:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:21:40 + --> $DIR/variance.rs:20:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:26:36 + --> $DIR/variance.rs:25:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr index 011ab3259c47..361a165da66f 100644 --- a/tests/ui/impl-trait/variance.new.stderr +++ b/tests/ui/impl-trait/variance.new.stderr @@ -1,23 +1,23 @@ error: ['a: *, 'a: o] - --> $DIR/variance.rs:14:36 + --> $DIR/variance.rs:13:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ error: ['a: *, 'a: o] - --> $DIR/variance.rs:19:32 + --> $DIR/variance.rs:18:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:21:40 + --> $DIR/variance.rs:20:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:26:36 + --> $DIR/variance.rs:25:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.old.stderr b/tests/ui/impl-trait/variance.old.stderr index ac3bcd2723fb..578d6fd14cd2 100644 --- a/tests/ui/impl-trait/variance.old.stderr +++ b/tests/ui/impl-trait/variance.old.stderr @@ -1,23 +1,23 @@ error: ['a: *] - --> $DIR/variance.rs:14:36 + --> $DIR/variance.rs:13:36 | LL | fn not_captured_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ error: ['a: *, 'a: o] - --> $DIR/variance.rs:19:32 + --> $DIR/variance.rs:18:32 | LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: [] - --> $DIR/variance.rs:21:40 + --> $DIR/variance.rs:20:40 | LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ error: ['a: o] - --> $DIR/variance.rs:26:36 + --> $DIR/variance.rs:25:36 | LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs index 43f7207a9042..1e359f033ff5 100644 --- a/tests/ui/impl-trait/variance.rs +++ b/tests/ui/impl-trait/variance.rs @@ -1,6 +1,5 @@ //@ revisions: old new e2024 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Z unstable-options #![cfg_attr(new, feature(lifetime_capture_rules_2024))] diff --git a/tests/ui/lifetimes/raw/gen-lt.e2024.stderr b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr index 232453df8ef6..0f184853ecef 100644 --- a/tests/ui/lifetimes/raw/gen-lt.e2024.stderr +++ b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr @@ -1,5 +1,5 @@ error: lifetimes cannot use keyword names - --> $DIR/gen-lt.rs:11:11 + --> $DIR/gen-lt.rs:10:11 | LL | fn gen_lt<'gen>() {} | ^^^^ diff --git a/tests/ui/lifetimes/raw/gen-lt.rs b/tests/ui/lifetimes/raw/gen-lt.rs index 4f3ede5b4a2e..3c33dc285f07 100644 --- a/tests/ui/lifetimes/raw/gen-lt.rs +++ b/tests/ui/lifetimes/raw/gen-lt.rs @@ -2,7 +2,6 @@ //@[e2021] edition:2021 //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2021] check-pass diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr index 157a1c5e09b0..6d7000a1370e 100644 --- a/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr +++ b/tests/ui/lifetimes/refcell-in-tail-expr.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `cell` does not live long enough - --> $DIR/refcell-in-tail-expr.rs:10:27 + --> $DIR/refcell-in-tail-expr.rs:9:27 | LL | let cell = std::cell::RefCell::new(0u8); | ---- binding `cell` declared here diff --git a/tests/ui/lifetimes/refcell-in-tail-expr.rs b/tests/ui/lifetimes/refcell-in-tail-expr.rs index 595e951f3731..2cca7acbf5a4 100644 --- a/tests/ui/lifetimes/refcell-in-tail-expr.rs +++ b/tests/ui/lifetimes/refcell-in-tail-expr.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] check-pass fn main() { diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr index 3c074c5c3a2c..ac23c67a8e11 100644 --- a/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr +++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `c` does not live long enough - --> $DIR/shorter-tail-expr-lifetime.rs:8:5 + --> $DIR/shorter-tail-expr-lifetime.rs:7:5 | LL | let c = std::cell::RefCell::new(".."); | - binding `c` declared here diff --git a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs index 4195a8b6c32b..25c530d43919 100644 --- a/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs +++ b/tests/ui/lifetimes/shorter-tail-expr-lifetime.rs @@ -1,5 +1,4 @@ //@ revisions: edition2021 edition2024 -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] edition: 2024 //@ [edition2024] run-pass diff --git a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs index ec74596a08da..6af6655149bd 100644 --- a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs +++ b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs @@ -1,6 +1,5 @@ //@ revisions: edition2021 edition2024 //@ ignore-wasm no panic or subprocess support -//@ [edition2024] compile-flags: -Zunstable-options //@ [edition2024] edition: 2024 //@ run-pass //@ needs-unwind diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs index d03027cf4a32..86c478af317c 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension.rs +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -15,7 +15,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Z unstable-options fn temp() -> (String, i32) { (String::from("Hello"), 1) diff --git a/tests/ui/lint/static-mut-refs.e2021.stderr b/tests/ui/lint/static-mut-refs.e2021.stderr index 09f560652e7b..5a4e712b3c0d 100644 --- a/tests/ui/lint/static-mut-refs.e2021.stderr +++ b/tests/ui/lint/static-mut-refs.e2021.stderr @@ -1,5 +1,5 @@ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:39:18 + --> $DIR/static-mut-refs.rs:38:18 | LL | let _y = &X; | ^^ shared reference to mutable static @@ -13,7 +13,7 @@ LL | let _y = &raw const X; | ~~~~~~~~~~ warning: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:43:18 + --> $DIR/static-mut-refs.rs:42:18 | LL | let _y = &mut X; | ^^^^^^ mutable reference to mutable static @@ -26,7 +26,7 @@ LL | let _y = &raw mut X; | ~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:51:22 + --> $DIR/static-mut-refs.rs:50:22 | LL | let ref _a = X; | ^ shared reference to mutable static @@ -35,7 +35,7 @@ LL | let ref _a = X; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:25 + --> $DIR/static-mut-refs.rs:54:25 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -48,7 +48,7 @@ LL | let (_b, _c) = (&raw const X, &Y); | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:29 + --> $DIR/static-mut-refs.rs:54:29 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -61,7 +61,7 @@ LL | let (_b, _c) = (&X, &raw const Y); | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:61:13 + --> $DIR/static-mut-refs.rs:60:13 | LL | foo(&X); | ^^ shared reference to mutable static @@ -74,7 +74,7 @@ LL | foo(&raw const X); | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:67:17 + --> $DIR/static-mut-refs.rs:66:17 | LL | let _ = Z.len(); | ^^^^^^^ shared reference to mutable static @@ -83,7 +83,7 @@ LL | let _ = Z.len(); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:73:33 + --> $DIR/static-mut-refs.rs:72:33 | LL | let _ = format!("{:?}", Z); | ^ shared reference to mutable static @@ -92,7 +92,7 @@ LL | let _ = format!("{:?}", Z); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:77:18 + --> $DIR/static-mut-refs.rs:76:18 | LL | let _v = &A.value; | ^^^^^^^^ shared reference to mutable static @@ -105,7 +105,7 @@ LL | let _v = &raw const A.value; | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:81:18 + --> $DIR/static-mut-refs.rs:80:18 | LL | let _s = &A.s.value; | ^^^^^^^^^^ shared reference to mutable static @@ -118,7 +118,7 @@ LL | let _s = &raw const A.s.value; | ~~~~~~~~~~ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:85:22 + --> $DIR/static-mut-refs.rs:84:22 | LL | let ref _v = A.value; | ^^^^^^^ shared reference to mutable static @@ -127,7 +127,7 @@ LL | let ref _v = A.value; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives warning: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:15:14 + --> $DIR/static-mut-refs.rs:14:14 | LL | &mut ($x.0) | ^^^^^^ mutable reference to mutable static diff --git a/tests/ui/lint/static-mut-refs.e2024.stderr b/tests/ui/lint/static-mut-refs.e2024.stderr index 2d2a4f7afe00..1b549272bd5f 100644 --- a/tests/ui/lint/static-mut-refs.e2024.stderr +++ b/tests/ui/lint/static-mut-refs.e2024.stderr @@ -1,5 +1,5 @@ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:39:18 + --> $DIR/static-mut-refs.rs:38:18 | LL | let _y = &X; | ^^ shared reference to mutable static @@ -13,7 +13,7 @@ LL | let _y = &raw const X; | ~~~~~~~~~~ error: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:43:18 + --> $DIR/static-mut-refs.rs:42:18 | LL | let _y = &mut X; | ^^^^^^ mutable reference to mutable static @@ -26,7 +26,7 @@ LL | let _y = &raw mut X; | ~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:51:22 + --> $DIR/static-mut-refs.rs:50:22 | LL | let ref _a = X; | ^ shared reference to mutable static @@ -35,7 +35,7 @@ LL | let ref _a = X; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:25 + --> $DIR/static-mut-refs.rs:54:25 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -48,7 +48,7 @@ LL | let (_b, _c) = (&raw const X, &Y); | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:55:29 + --> $DIR/static-mut-refs.rs:54:29 | LL | let (_b, _c) = (&X, &Y); | ^^ shared reference to mutable static @@ -61,7 +61,7 @@ LL | let (_b, _c) = (&X, &raw const Y); | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:61:13 + --> $DIR/static-mut-refs.rs:60:13 | LL | foo(&X); | ^^ shared reference to mutable static @@ -74,7 +74,7 @@ LL | foo(&raw const X); | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:67:17 + --> $DIR/static-mut-refs.rs:66:17 | LL | let _ = Z.len(); | ^^^^^^^ shared reference to mutable static @@ -83,7 +83,7 @@ LL | let _ = Z.len(); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:73:33 + --> $DIR/static-mut-refs.rs:72:33 | LL | let _ = format!("{:?}", Z); | ^ shared reference to mutable static @@ -92,7 +92,7 @@ LL | let _ = format!("{:?}", Z); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:77:18 + --> $DIR/static-mut-refs.rs:76:18 | LL | let _v = &A.value; | ^^^^^^^^ shared reference to mutable static @@ -105,7 +105,7 @@ LL | let _v = &raw const A.value; | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:81:18 + --> $DIR/static-mut-refs.rs:80:18 | LL | let _s = &A.s.value; | ^^^^^^^^^^ shared reference to mutable static @@ -118,7 +118,7 @@ LL | let _s = &raw const A.s.value; | ~~~~~~~~~~ error: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:85:22 + --> $DIR/static-mut-refs.rs:84:22 | LL | let ref _v = A.value; | ^^^^^^^ shared reference to mutable static @@ -127,7 +127,7 @@ LL | let ref _v = A.value; = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives error: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-refs.rs:15:14 + --> $DIR/static-mut-refs.rs:14:14 | LL | &mut ($x.0) | ^^^^^^ mutable reference to mutable static diff --git a/tests/ui/lint/static-mut-refs.rs b/tests/ui/lint/static-mut-refs.rs index 3d84d7dbf40d..1040dfcae7a9 100644 --- a/tests/ui/lint/static-mut-refs.rs +++ b/tests/ui/lint/static-mut-refs.rs @@ -6,7 +6,6 @@ //@ [e2021] run-pass //@ [e2024] edition:2024 -//@ [e2024] compile-flags: -Zunstable-options static mut FOO: (u32, u32) = (1, 2); diff --git a/tests/ui/macros/macro-missing-fragment.e2015.stderr b/tests/ui/macros/macro-missing-fragment.e2015.stderr index a068dc5c054f..3d32f203d4a2 100644 --- a/tests/ui/macros/macro-missing-fragment.e2015.stderr +++ b/tests/ui/macros/macro-missing-fragment.e2015.stderr @@ -1,11 +1,11 @@ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | ( $( any_token $field_rust_type )* ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:19:7 + --> $DIR/macro-missing-fragment.rs:18:7 | LL | ( $name ) => {}; | ^^^^^ @@ -28,7 +28,7 @@ LL | ( $name ) => {}; = note: for more information, see issue #40107 warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:26:7 + --> $DIR/macro-missing-fragment.rs:25:7 | LL | ( $name ) => {}; | ^^^^^ @@ -40,7 +40,7 @@ error: aborting due to 1 previous error; 3 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -48,14 +48,14 @@ LL | ( $( any_token $field_rust_type )* ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:19:7 + --> $DIR/macro-missing-fragment.rs:18:7 | LL | ( $name ) => {}; | ^^^^^ @@ -63,14 +63,14 @@ LL | ( $name ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Future breakage diagnostic: warning: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:26:7 + --> $DIR/macro-missing-fragment.rs:25:7 | LL | ( $name ) => {}; | ^^^^^ @@ -78,7 +78,7 @@ LL | ( $name ) => {}; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 note: the lint level is defined here - --> $DIR/macro-missing-fragment.rs:6:9 + --> $DIR/macro-missing-fragment.rs:5:9 | LL | #![warn(missing_fragment_specifier)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/macro-missing-fragment.e2024.stderr b/tests/ui/macros/macro-missing-fragment.e2024.stderr index 0dc48e0c7b21..a9195063a5b9 100644 --- a/tests/ui/macros/macro-missing-fragment.e2024.stderr +++ b/tests/ui/macros/macro-missing-fragment.e2024.stderr @@ -1,5 +1,5 @@ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | ( $( any_token $field_rust_type:spec )* ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:19:7 + --> $DIR/macro-missing-fragment.rs:18:7 | LL | ( $name ) => {}; | ^^^^^ @@ -25,7 +25,7 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:26:7 + --> $DIR/macro-missing-fragment.rs:25:7 | LL | ( $name ) => {}; | ^^^^^ @@ -38,7 +38,7 @@ LL | ( $name:spec ) => {}; | +++++ error: missing fragment specifier - --> $DIR/macro-missing-fragment.rs:9:20 + --> $DIR/macro-missing-fragment.rs:8:20 | LL | ( $( any_token $field_rust_type )* ) => {}; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs index b7da87ae610f..42387e8dbbf4 100644 --- a/tests/ui/macros/macro-missing-fragment.rs +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -1,7 +1,6 @@ //@ revisions: e2015 e2024 //@[e2015] edition:2015 //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options #![warn(missing_fragment_specifier)] diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index 92199625207e..8991c6db7b98 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -2,7 +2,6 @@ //@ needs-unwind //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 -//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] edition: 2024 // See `mir_drop_order.rs` for more information diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr index 03bb0ca5f3a0..ec1483b0aaeb 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr @@ -1,5 +1,5 @@ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | unsafe { mem::zeroed::<()>() } | ++++++ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:30:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | core::mem::transmute::<_, ()>(Zst) | +++++++++ warning: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:47:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | unsafe { Union { a: () }.b } = help: specify the type explicitly warning: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:58:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | unsafe { *ptr::from_ref(&()).cast::<()>() } | ++++++ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | unsafe { internally_create::<()>(x) } | ++++++ warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:97:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -80,7 +80,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:92:22 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:115:17 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let f = internally_create::<()>; | ++++++ warning: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:140:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | S(marker::PhantomData).create_out_of_thin_air() = help: specify the type explicitly warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:158:19 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr index cf12d699f2e9..790facee09e6 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr @@ -1,5 +1,5 @@ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | unsafe { mem::zeroed::<()>() } | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:30:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | core::mem::transmute::<_, ()>(Zst) | +++++++++ error: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:47:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | unsafe { Union { a: () }.b } = help: specify the type explicitly error: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:58:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | unsafe { *ptr::from_ref(&()).cast::<()>() } | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | unsafe { internally_create::<()>(x) } | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:97:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -80,7 +80,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:92:22 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:115:17 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL | let f = internally_create::<()>; | ++++++ error: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:140:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ LL | S(marker::PhantomData).create_out_of_thin_air() = help: specify the type explicitly error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:158:19 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | match send_message::<() /* ?0 */>() { | ~~ warning: the type `!` does not permit zero-initialization - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ this code causes undefined behavior when executed diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs index 19b51eea2f57..97e7a2f56bda 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs @@ -2,7 +2,6 @@ //@[e2015] check-pass //@[e2024] check-fail //@[e2024] edition:2024 -//@[e2024] compile-flags: -Zunstable-options use std::{marker, mem, ptr}; diff --git a/tests/ui/nll/issue-54556-niconii.edition2021.stderr b/tests/ui/nll/issue-54556-niconii.edition2021.stderr index abee09ed9503..8bd559034b09 100644 --- a/tests/ui/nll/issue-54556-niconii.edition2021.stderr +++ b/tests/ui/nll/issue-54556-niconii.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `counter` does not live long enough - --> $DIR/issue-54556-niconii.rs:28:20 + --> $DIR/issue-54556-niconii.rs:27:20 | LL | let counter = Mutex; | ------- binding `counter` declared here diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs index f01e0523cbf9..9d37adede6ad 100644 --- a/tests/ui/nll/issue-54556-niconii.rs +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -9,7 +9,6 @@ //@ revisions: edition2021 edition2024 //@ [edition2021] edition: 2021 //@ [edition2024] edition: 2024 -//@ [edition2024] compile-flags: -Z unstable-options //@ [edition2024] check-pass struct Mutex; diff --git a/tests/ui/proc-macro/macro_rules_edition_from_pm.rs b/tests/ui/proc-macro/macro_rules_edition_from_pm.rs index 57ed54fd1dfb..8fc7d9097493 100644 --- a/tests/ui/proc-macro/macro_rules_edition_from_pm.rs +++ b/tests/ui/proc-macro/macro_rules_edition_from_pm.rs @@ -6,7 +6,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ check-pass // This checks how the expr fragment specifier works. diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs index 7bf5118c3402..0f0120b721ff 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@ check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed index 44850c8c45bb..ff8c4beca6b2 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr index 496b3197c340..15a3fa114147 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `poll` will become ambiguous in Rust 2024 - --> $DIR/future-poll-async-block.rs:14:5 + --> $DIR/future-poll-async-block.rs:13:5 | LL | core::pin::pin!(async {}).poll(&mut context()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())` @@ -7,7 +7,7 @@ LL | core::pin::pin!(async {}).poll(&mut context()); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see note: the lint level is defined here - --> $DIR/future-poll-async-block.rs:8:9 + --> $DIR/future-poll-async-block.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs index 614e4c786c53..60b0b2689c2a 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed index c96d1dcecc21..f68729e483a5 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr index 020a00ccdec0..633731c2a5a5 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `poll` will become ambiguous in Rust 2024 - --> $DIR/future-poll-not-future-pinned.rs:18:5 + --> $DIR/future-poll-not-future-pinned.rs:17:5 | LL | core::pin::pin!(()).poll(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(()))` @@ -7,7 +7,7 @@ LL | core::pin::pin!(()).poll(); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see note: the lint level is defined here - --> $DIR/future-poll-not-future-pinned.rs:8:9 + --> $DIR/future-poll-not-future-pinned.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs index 21b170a5f1db..4845ef779e01 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs index 899b69ebfc24..36578e28b807 100644 --- a/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@ check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed index 0b0873eb2384..03bf4ab19c1b 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr index b74e80e2a4a0..e67f07b4e465 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `into_future` will become ambiguous in Rust 2024 - --> $DIR/into-future-adt.rs:26:5 + --> $DIR/into-future-adt.rs:25:5 | LL | Cat.into_future(); | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)` @@ -7,7 +7,7 @@ LL | Cat.into_future(); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see note: the lint level is defined here - --> $DIR/into-future-adt.rs:8:9 + --> $DIR/into-future-adt.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.rs b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs index 0db70930bc75..65edc88baabc 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-adt.rs +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs index 6bc2ea317059..16ac89759f38 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs +++ b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@ check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed index a798014d93d3..4e0828833950 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr index 6ea4580ca72e..0588f5bf3f55 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr @@ -1,5 +1,5 @@ error: trait method `into_future` will become ambiguous in Rust 2024 - --> $DIR/into-future-not-into-future.rs:20:5 + --> $DIR/into-future-not-into-future.rs:19:5 | LL | Cat.into_future(); | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)` @@ -7,7 +7,7 @@ LL | Cat.into_future(); = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! = note: for more information, see note: the lint level is defined here - --> $DIR/into-future-not-into-future.rs:8:9 + --> $DIR/into-future-not-into-future.rs:7:9 | LL | #![deny(rust_2024_prelude_collisions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs index 23e81cfe6b48..f640d9b50bbb 100644 --- a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs @@ -2,7 +2,6 @@ //@[e2021] edition: 2021 //@[e2021] run-rustfix //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options //@[e2024] check-pass #![deny(rust_2024_prelude_collisions)] diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs index 7c919fed976f..79fba46c77f8 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ check-pass diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs index 4f369a8305bc..e2c504e708c5 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm.rs @@ -5,7 +5,6 @@ //@ check-pass //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ proc-macro: unsafe-attributes-pm.rs unsafe_attributes_pm::missing_unsafe!(); diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr index fb697e14ef1c..5c3927a09280 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes.rs:8:3 + --> $DIR/unsafe-attributes.rs:7:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs index f6f2994bb6de..4b161bc34ea0 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs @@ -2,7 +2,6 @@ //@[edition2021] edition:2021 //@[edition2021] check-pass //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options #[no_mangle] //[edition2024]~ ERROR: unsafe attribute used without unsafe diff --git a/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr index 2798ccdefd0c..10d0e8b830c9 100644 --- a/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr +++ b/tests/ui/rust-2024/unsafe-before_exec.e2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `before_exec` is unsafe and requires unsafe block - --> $DIR/unsafe-before_exec.rs:14:5 + --> $DIR/unsafe-before_exec.rs:13:5 | LL | cmd.before_exec(|| Ok(())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/rust-2024/unsafe-before_exec.rs b/tests/ui/rust-2024/unsafe-before_exec.rs index 540394da80ef..44a955e229d8 100644 --- a/tests/ui/rust-2024/unsafe-before_exec.rs +++ b/tests/ui/rust-2024/unsafe-before_exec.rs @@ -3,7 +3,6 @@ //@[e2021] edition: 2021 //@[e2021] check-pass //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options use std::process::Command; use std::os::unix::process::CommandExt; diff --git a/tests/ui/rust-2024/unsafe-env.e2021.stderr b/tests/ui/rust-2024/unsafe-env.e2021.stderr index 90c1df192aa0..6f9618eb14bf 100644 --- a/tests/ui/rust-2024/unsafe-env.e2021.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:15:9 + --> $DIR/unsafe-env.rs:14:9 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -7,18 +7,18 @@ LL | unsafe_fn(); = note: for more information, see issue #71668 = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/unsafe-env.rs:9:1 + --> $DIR/unsafe-env.rs:8:1 | LL | unsafe fn unsafe_fn() { | ^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/unsafe-env.rs:8:8 + --> $DIR/unsafe-env.rs:7:8 | LL | #[deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe function or block - --> $DIR/unsafe-env.rs:33:5 + --> $DIR/unsafe-env.rs:32:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -26,13 +26,13 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:36:5 + --> $DIR/unsafe-env.rs:35:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:21:8 + --> $DIR/unsafe-env.rs:20:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-env.e2024.stderr b/tests/ui/rust-2024/unsafe-env.e2024.stderr index 5ecdf3cd7a74..04a35933c79b 100644 --- a/tests/ui/rust-2024/unsafe-env.e2024.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `std::env::set_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:10:5 + --> $DIR/unsafe-env.rs:9:5 | LL | env::set_var("FOO", "BAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,18 +7,18 @@ LL | env::set_var("FOO", "BAR"); = note: for more information, see issue #71668 = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/unsafe-env.rs:9:1 + --> $DIR/unsafe-env.rs:8:1 | LL | unsafe fn unsafe_fn() { | ^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/unsafe-env.rs:8:8 + --> $DIR/unsafe-env.rs:7:8 | LL | #[deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error[E0133]: call to unsafe function `std::env::remove_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:12:5 + --> $DIR/unsafe-env.rs:11:5 | LL | env::remove_var("FOO"); | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -27,7 +27,7 @@ LL | env::remove_var("FOO"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:15:9 + --> $DIR/unsafe-env.rs:14:9 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -36,7 +36,7 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:23:5 + --> $DIR/unsafe-env.rs:22:5 | LL | env::set_var("FOO", "BAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -44,7 +44,7 @@ LL | env::set_var("FOO", "BAR"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `remove_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:25:5 + --> $DIR/unsafe-env.rs:24:5 | LL | env::remove_var("FOO"); | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -52,7 +52,7 @@ LL | env::remove_var("FOO"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:33:5 + --> $DIR/unsafe-env.rs:32:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -60,13 +60,13 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:36:5 + --> $DIR/unsafe-env.rs:35:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:21:8 + --> $DIR/unsafe-env.rs:20:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-env.rs b/tests/ui/rust-2024/unsafe-env.rs index 601f44e1d3ec..4a7c646323a6 100644 --- a/tests/ui/rust-2024/unsafe-env.rs +++ b/tests/ui/rust-2024/unsafe-env.rs @@ -1,7 +1,6 @@ //@ revisions: e2021 e2024 //@[e2021] edition: 2021 //@[e2024] edition: 2024 -//@[e2024] compile-flags: -Zunstable-options use std::env; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr index 77554da10e60..50201140cdaf 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:12:5 + --> $DIR/extern-items-unsafe.rs:11:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:12:11 + --> $DIR/extern-items-unsafe.rs:11:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr index 33b752782d59..fa79d76546a1 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:12:5 + --> $DIR/extern-items-unsafe.rs:11:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:12:11 + --> $DIR/extern-items-unsafe.rs:11:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs index 721e07acca58..7bb4f666924d 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options unsafe extern "C" { static TEST1: i32; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr index 8ef7c2caf21e..17b49d8ed5c3 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/extern-items.rs:7:1 + --> $DIR/extern-items.rs:6:1 | LL | / extern "C" { LL | | diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index 08805c363476..8c0b8bc88990 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -2,7 +2,6 @@ //@[edition2021] edition:2021 //@[edition2021] check-pass //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs index b0b8a8b012a6..2b2d58c3eb3d 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options //@ check-pass unsafe extern "C" { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index ddc5477116f7..07d934da24b1 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,5 +1,5 @@ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:7:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | unsafe extern "C" { | ++++++ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:9:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index ae7b4cd47c07..cceb3bddef43 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:5:1 | LL | / extern "C" { LL | | @@ -11,7 +11,7 @@ LL | | } | |_^ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:7:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | unsafe extern "C" { | ++++++ error: items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:9:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index 89415a69f08f..a5a6ccdffa0c 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr index e3626bb497e4..9433dd1f2e59 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:18:5 + --> $DIR/unsafe-items.rs:17:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:18:11 + --> $DIR/unsafe-items.rs:17:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr index 89bc501b7b5a..af86b4c58052 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:18:5 + --> $DIR/unsafe-items.rs:17:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:18:11 + --> $DIR/unsafe-items.rs:17:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs index dc2bae892a98..50c97b51768e 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -1,7 +1,6 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 //@[edition2024] edition:2024 -//@[edition2024] compile-flags: -Zunstable-options unsafe extern "C" { unsafe static TEST1: i32; From b36dcc1a382d1a05099b80a8fe59279656ffed12 Mon Sep 17 00:00:00 2001 From: Orion Gonzalez Date: Wed, 27 Nov 2024 15:06:40 +0100 Subject: [PATCH 186/330] Improve the diagnostic of fn item in variadic fn --- compiler/rustc_hir_typeck/messages.ftl | 5 +++++ compiler/rustc_hir_typeck/src/errors.rs | 10 ++++++++++ compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 +++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 3669100ed916..6001816ffbec 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -79,6 +79,11 @@ hir_typeck_field_multiply_specified_in_initializer = .label = used more than once .previous_use_label = first use of `{$ident}` +hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function + .suggestion = use a function pointer instead + .help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + .note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html + hir_typeck_fru_expr = this expression does not end in a comma... hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 4f579b05d83b..936f80c75fa4 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -797,3 +797,13 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> { #[note(hir_typeck_teach_help)] pub(crate) teach: bool, } + +#[derive(Diagnostic)] +#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)] +pub(crate) struct PassFnItemToVariadicFunction { + #[primary_span] + pub span: Span, + #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")] + pub sugg_span: Span, + pub replace: String, +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f8f6564cf14d..63777f82f1ae 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -472,9 +472,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variadic_error(tcx.sess, arg.span, arg_ty, "c_uint"); } ty::FnDef(..) => { - let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); - let ptr_ty = self.resolve_vars_if_possible(ptr_ty); - variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string()); + let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx)); + let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string(); + + let fn_item_spa = arg.span; + tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction { + span: fn_item_spa, + sugg_span: fn_item_spa.shrink_to_hi(), + replace: fn_ptr, + }); } _ => {} } From 1e4817cd33a59f1e0ddb1a3e66bdc0794d0785be Mon Sep 17 00:00:00 2001 From: Orion Gonzalez Date: Wed, 27 Nov 2024 15:37:27 +0100 Subject: [PATCH 187/330] bless the tests and add a new one --- compiler/rustc_hir_typeck/src/errors.rs | 2 ++ .../c-variadic/fn-item-diagnostic-issue-69232.rs | 13 +++++++++++++ .../fn-item-diagnostic-issue-69232.stderr | 16 ++++++++++++++++ tests/ui/c-variadic/issue-32201.rs | 5 +++-- tests/ui/c-variadic/issue-32201.stderr | 11 +++++++++-- tests/ui/error-codes/E0617.rs | 5 +++-- tests/ui/error-codes/E0617.stderr | 8 +++++--- 7 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs create mode 100644 tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 936f80c75fa4..fa27abd270ff 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -800,6 +800,8 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)] +#[help] +#[note] pub(crate) struct PassFnItemToVariadicFunction { #[primary_span] pub span: Span, diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs new file mode 100644 index 000000000000..d0ef91b22b23 --- /dev/null +++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs @@ -0,0 +1,13 @@ +// https://github.com/rust-lang/rust/issues/69232 + +extern "C" { + fn foo(x: usize, ...); +} + +fn test() -> u8 { + 127 +} + +fn main() { + unsafe { foo(1, test) }; //~ ERROR can't pass a function item to a variadic function +} diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr new file mode 100644 index 000000000000..6aa1c8a10915 --- /dev/null +++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr @@ -0,0 +1,16 @@ +error[E0617]: can't pass a function item to a variadic function + --> $DIR/fn-item-diagnostic-issue-69232.rs:12:21 + | +LL | unsafe { foo(1, test) }; + | ^^^^ + | + = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html +help: use a function pointer instead + | +LL | unsafe { foo(1, test as fn() -> u8) }; + | +++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0617`. diff --git a/tests/ui/c-variadic/issue-32201.rs b/tests/ui/c-variadic/issue-32201.rs index f27bb1c2eb5b..434711b75236 100644 --- a/tests/ui/c-variadic/issue-32201.rs +++ b/tests/ui/c-variadic/issue-32201.rs @@ -7,7 +7,8 @@ fn bar(_: *const u8) {} fn main() { unsafe { foo(0, bar); - //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function - //~| HELP cast the value to `fn(*const u8)` + //~^ ERROR can't pass a function item to a variadic function + //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + ////~| HELP use a function pointer instead } } diff --git a/tests/ui/c-variadic/issue-32201.stderr b/tests/ui/c-variadic/issue-32201.stderr index 352db9f62f6d..1cd85d7f07af 100644 --- a/tests/ui/c-variadic/issue-32201.stderr +++ b/tests/ui/c-variadic/issue-32201.stderr @@ -1,8 +1,15 @@ -error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function +error[E0617]: can't pass a function item to a variadic function --> $DIR/issue-32201.rs:9:16 | LL | foo(0, bar); - | ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)` + | ^^^ + | + = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html +help: use a function pointer instead + | +LL | foo(0, bar as fn(*const u8)); + | ++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0617.rs b/tests/ui/error-codes/E0617.rs index b71ba0ed88b9..4a38174bc6fe 100644 --- a/tests/ui/error-codes/E0617.rs +++ b/tests/ui/error-codes/E0617.rs @@ -20,7 +20,8 @@ fn main() { //~^ ERROR can't pass `u16` to variadic function //~| HELP cast the value to `c_uint` printf(::std::ptr::null(), printf); - //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function - //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)` + //~^ ERROR can't pass a function item to a variadic function + //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + //~| HELP use a function pointer instead } } diff --git a/tests/ui/error-codes/E0617.stderr b/tests/ui/error-codes/E0617.stderr index ea91ad082923..7193463e0283 100644 --- a/tests/ui/error-codes/E0617.stderr +++ b/tests/ui/error-codes/E0617.stderr @@ -28,16 +28,18 @@ error[E0617]: can't pass `u16` to variadic function LL | printf(::std::ptr::null(), 0u16); | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` -error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function +error[E0617]: can't pass a function item to a variadic function --> $DIR/E0617.rs:22:36 | LL | printf(::std::ptr::null(), printf); | ^^^^^^ | -help: cast the value to `unsafe extern "C" fn(*const i8, ...)` + = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI + = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html +help: use a function pointer instead | LL | printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...)); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | +++++++++++++++++++++++++++++++++++++++ error: aborting due to 6 previous errors From 9461f4296ffcbd75440ec211ead7bff6fb86012c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 29 Nov 2024 14:52:41 +1100 Subject: [PATCH 188/330] Revert "Rollup merge of #133418 - Zalathar:spans, r=jieyouxu" This reverts commit adf9b5fcd1de43eaf0a779e10612caee8b47bede, reversing changes made to af1ca153d4aed5ffe22445273aa388a8d3f8f4ae. Reverting due to . --- .../src/coverageinfo/ffi.rs | 36 ++-- .../src/coverageinfo/map_data.rs | 14 +- .../src/coverageinfo/mapgen.rs | 127 +++++++------- .../src/coverageinfo/mapgen/spans.rs | 124 ------------- compiler/rustc_codegen_llvm/src/lib.rs | 1 - compiler/rustc_middle/src/mir/coverage.rs | 18 +- compiler/rustc_middle/src/mir/pretty.rs | 4 +- .../rustc_mir_transform/src/coverage/mod.rs | 166 ++++++++++++++++-- ...ch_match_arms.main.InstrumentCoverage.diff | 12 +- ...ument_coverage.bar.InstrumentCoverage.diff | 2 +- ...ment_coverage.main.InstrumentCoverage.diff | 10 +- ...rage_cleanup.main.CleanupPostBorrowck.diff | 10 +- ...erage_cleanup.main.InstrumentCoverage.diff | 10 +- 13 files changed, 284 insertions(+), 250 deletions(-) delete mode 100644 compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 19d6726002c4..a6e07ea2a60e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,4 +1,6 @@ -use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId}; +use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion}; + +use crate::coverageinfo::mapgen::LocalFileId; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -124,23 +126,37 @@ pub(crate) struct CoverageSpan { /// Local index into the function's local-to-global file ID table. /// The value at that index is itself an index into the coverage filename /// table in the CGU's `__llvm_covmap` section. - pub(crate) file_id: u32, + file_id: u32, /// 1-based starting line of the source code span. - pub(crate) start_line: u32, + start_line: u32, /// 1-based starting column of the source code span. - pub(crate) start_col: u32, + start_col: u32, /// 1-based ending line of the source code span. - pub(crate) end_line: u32, + end_line: u32, /// 1-based ending column of the source code span. High bit must be unset. - pub(crate) end_col: u32, + end_col: u32, +} + +impl CoverageSpan { + pub(crate) fn from_source_region( + local_file_id: LocalFileId, + code_region: &SourceRegion, + ) -> Self { + let file_id = local_file_id.as_u32(); + let &SourceRegion { start_line, start_col, end_line, end_col } = code_region; + // Internally, LLVM uses the high bit of `end_col` to distinguish between + // code regions and gap regions, so it can't be used by the column number. + assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}"); + Self { file_id, start_line, start_col, end_line, end_col } + } } /// Must match the layout of `LLVMRustCoverageCodeRegion`. #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct CodeRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) counter: Counter, } @@ -148,7 +164,7 @@ pub(crate) struct CodeRegion { #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct BranchRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) true_counter: Counter, pub(crate) false_counter: Counter, } @@ -157,7 +173,7 @@ pub(crate) struct BranchRegion { #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct MCDCBranchRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) true_counter: Counter, pub(crate) false_counter: Counter, pub(crate) mcdc_branch_params: mcdc::BranchParameters, @@ -167,6 +183,6 @@ pub(crate) struct MCDCBranchRegion { #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct MCDCDecisionRegion { - pub(crate) cov_span: CoverageSpan, + pub(crate) span: CoverageSpan, pub(crate) mcdc_decision_params: mcdc::DecisionParameters, } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 95746b88cedb..e3c0df278836 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -3,9 +3,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, + SourceRegion, }; use rustc_middle::ty::Instance; -use rustc_span::Span; use tracing::{debug, instrument}; use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; @@ -220,16 +220,16 @@ impl<'tcx> FunctionCoverage<'tcx> { }) } - /// Yields all this function's coverage mappings, after simplifying away - /// unused counters and counter expressions. - pub(crate) fn mapping_spans( + /// Converts this function's coverage mappings into an intermediate form + /// that will be used by `mapgen` when preparing for FFI. + pub(crate) fn counter_regions( &self, - ) -> impl Iterator + ExactSizeIterator + Captures<'_> { + ) -> impl Iterator + ExactSizeIterator { self.function_coverage_info.mappings.iter().map(move |mapping| { - let &Mapping { ref kind, span } = mapping; + let Mapping { kind, source_region } = mapping; let kind = kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term }); - (kind, span) + (kind, source_region) }) } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index ed881418cb00..b582dd967a70 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,14 +1,12 @@ -mod spans; - use std::ffi::CString; -use std::sync::Arc; +use std::iter; use itertools::Itertools as _; use rustc_abi::Align; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::IndexVec; use rustc_middle::mir::coverage::MappingKind; @@ -17,7 +15,7 @@ use rustc_middle::{bug, mir}; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; use rustc_span::def_id::DefIdSet; -use rustc_span::{SourceFile, StableSourceFileId}; +use rustc_span::{Span, Symbol}; use rustc_target::spec::HasTargetSpec; use tracing::debug; @@ -74,11 +72,11 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { .map(|(instance, function_coverage)| (instance, function_coverage.into_finished())) .collect::>(); - let all_files = function_coverage_entries + let all_file_names = function_coverage_entries .iter() .map(|(_, fn_cov)| fn_cov.function_coverage_info.body_span) - .map(|span| tcx.sess.source_map().lookup_source_file(span.lo())); - let global_file_table = GlobalFileTable::new(all_files); + .map(|span| span_file_name(tcx, span)); + let global_file_table = GlobalFileTable::new(all_file_names); // Encode all filenames referenced by coverage mappings in this CGU. let filenames_buffer = global_file_table.make_filenames_buffer(tcx); @@ -105,8 +103,15 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { encode_mappings_for_function(tcx, &global_file_table, &function_coverage); if coverage_mapping_buffer.is_empty() { - debug!("function has no mappings to embed; skipping"); - continue; + if function_coverage.is_used() { + bug!( + "A used function should have had coverage mapping data but did not: {}", + mangled_function_name + ); + } else { + debug!("unused function had no coverage mapping data: {}", mangled_function_name); + continue; + } } if !is_used { @@ -143,34 +148,29 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { } } -/// Maps "global" (per-CGU) file ID numbers to their underlying source files. +/// Maps "global" (per-CGU) file ID numbers to their underlying filenames. struct GlobalFileTable { - /// This "raw" table doesn't include the working dir, so a file's + /// This "raw" table doesn't include the working dir, so a filename's /// global ID is its index in this set **plus one**. - raw_file_table: FxIndexMap>, + raw_file_table: FxIndexSet, } impl GlobalFileTable { - fn new(all_files: impl IntoIterator>) -> Self { - // Collect all of the files into a set. Files usually come in contiguous - // runs, so we can dedup adjacent ones to save work. - let mut raw_file_table = all_files - .into_iter() - .dedup_by(|a, b| a.stable_id == b.stable_id) - .map(|f| (f.stable_id, f)) - .collect::>>(); + fn new(all_file_names: impl IntoIterator) -> Self { + // Collect all of the filenames into a set. Filenames usually come in + // contiguous runs, so we can dedup adjacent ones to save work. + let mut raw_file_table = all_file_names.into_iter().dedup().collect::>(); - // Sort the file table by its underlying filenames. - raw_file_table.sort_unstable_by(|_, a, _, b| { - Ord::cmp(&a.name, &b.name).then_with(|| Ord::cmp(&a.stable_id, &b.stable_id)) - }); + // Sort the file table by its actual string values, not the arbitrary + // ordering of its symbols. + raw_file_table.sort_unstable_by(|a, b| a.as_str().cmp(b.as_str())); Self { raw_file_table } } - fn global_file_id_for_file(&self, file: &SourceFile) -> GlobalFileId { - let raw_id = self.raw_file_table.get_index_of(&file.stable_id).unwrap_or_else(|| { - bug!("file not found in prepared global file table: {:?}", file.name); + fn global_file_id_for_file_name(&self, file_name: Symbol) -> GlobalFileId { + let raw_id = self.raw_file_table.get_index_of(&file_name).unwrap_or_else(|| { + bug!("file name not found in prepared global file table: {file_name}"); }); // The raw file table doesn't include an entry for the working dir // (which has ID 0), so add 1 to get the correct ID. @@ -178,27 +178,24 @@ impl GlobalFileTable { } fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec { - let mut table = Vec::with_capacity(self.raw_file_table.len() + 1); - // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) // requires setting the first filename to the compilation directory. // Since rustc generates coverage maps with relative paths, the // compilation directory can be combined with the relative paths // to get absolute paths, if needed. - table.push( - tcx.sess - .opts - .working_dir - .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) - .to_string_lossy(), - ); + use rustc_session::RemapFileNameExt; + use rustc_session::config::RemapPathScopeComponents; + let working_dir: &str = &tcx + .sess + .opts + .working_dir + .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) + .to_string_lossy(); - // Add the regular entries after the base directory. - table.extend(self.raw_file_table.values().map(|file| { - file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy() - })); - - llvm_cov::write_filenames_to_buffer(table.iter().map(|f| f.as_ref())) + // Insert the working dir at index 0, before the other filenames. + let filenames = + iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str)); + llvm_cov::write_filenames_to_buffer(filenames) } } @@ -211,7 +208,7 @@ rustc_index::newtype_index! { /// An index into a function's list of global file IDs. That underlying list /// of local-to-global mappings will be embedded in the function's record in /// the `__llvm_covfun` linker section. - struct LocalFileId {} + pub(crate) struct LocalFileId {} } /// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) @@ -237,6 +234,13 @@ impl VirtualFileMapping { } } +fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol { + let source_file = tcx.sess.source_map().lookup_source_file(span.lo()); + let name = + source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(); + Symbol::intern(&name) +} + /// Using the expressions and counter regions collected for a single function, /// generate the variable-sized payload of its corresponding `__llvm_covfun` /// entry. The payload is returned as a vector of bytes. @@ -247,13 +251,11 @@ fn encode_mappings_for_function( global_file_table: &GlobalFileTable, function_coverage: &FunctionCoverage<'_>, ) -> Vec { - let mapping_spans = function_coverage.mapping_spans(); - if mapping_spans.is_empty() { + let counter_regions = function_coverage.counter_regions(); + if counter_regions.is_empty() { return Vec::new(); } - let fn_cov_info = function_coverage.function_coverage_info; - let expressions = function_coverage.counter_expressions().collect::>(); let mut virtual_file_mapping = VirtualFileMapping::default(); @@ -263,39 +265,34 @@ fn encode_mappings_for_function( let mut mcdc_decision_regions = vec![]; // Currently a function's mappings must all be in the same file as its body span. - let source_map = tcx.sess.source_map(); - let source_file = source_map.lookup_source_file(fn_cov_info.body_span.lo()); + let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span); - // Look up the global file ID for that file. - let global_file_id = global_file_table.global_file_id_for_file(&source_file); + // Look up the global file ID for that filename. + let global_file_id = global_file_table.global_file_id_for_file_name(file_name); // Associate that global file ID with a local file ID for this function. let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); + debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'"); - let make_cov_span = |span| { - spans::make_coverage_span(local_file_id, source_map, fn_cov_info, &source_file, span) - }; - - // For each coverage mapping span in this function+file, convert it to a + // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. - for (mapping_kind, span) in mapping_spans { - debug!("Adding counter {mapping_kind:?} to map for {span:?}"); - let Some(cov_span) = make_cov_span(span) else { continue }; + for (mapping_kind, region) in counter_regions { + debug!("Adding counter {mapping_kind:?} to map for {region:?}"); + let span = ffi::CoverageSpan::from_source_region(local_file_id, region); match mapping_kind { MappingKind::Code(term) => { - code_regions - .push(ffi::CodeRegion { cov_span, counter: ffi::Counter::from_term(term) }); + code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); } MappingKind::Branch { true_term, false_term } => { branch_regions.push(ffi::BranchRegion { - cov_span, + span, true_counter: ffi::Counter::from_term(true_term), false_counter: ffi::Counter::from_term(false_term), }); } MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { mcdc_branch_regions.push(ffi::MCDCBranchRegion { - cov_span, + span, true_counter: ffi::Counter::from_term(true_term), false_counter: ffi::Counter::from_term(false_term), mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), @@ -303,7 +300,7 @@ fn encode_mappings_for_function( } MappingKind::MCDCDecision(mcdc_decision_params) => { mcdc_decision_regions.push(ffi::MCDCDecisionRegion { - cov_span, + span, mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params), }); } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs deleted file mode 100644 index 4a7721879fd0..000000000000 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs +++ /dev/null @@ -1,124 +0,0 @@ -use rustc_middle::mir::coverage::FunctionCoverageInfo; -use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, Pos, SourceFile, Span}; -use tracing::debug; - -use crate::coverageinfo::ffi; -use crate::coverageinfo::mapgen::LocalFileId; - -/// Converts the span into its start line and column, and end line and column. -/// -/// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by -/// the compiler, these column numbers are denoted in **bytes**, because that's what -/// LLVM's `llvm-cov` tool expects to see in coverage maps. -/// -/// Returns `None` if the conversion failed for some reason. This shouldn't happen, -/// but it's hard to rule out entirely (especially in the presence of complex macros -/// or other expansions), and if it does happen then skipping a span or function is -/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -pub(crate) fn make_coverage_span( - file_id: LocalFileId, - source_map: &SourceMap, - fn_cov_info: &FunctionCoverageInfo, - file: &SourceFile, - span: Span, -) -> Option { - let span = ensure_non_empty_span(source_map, fn_cov_info, span)?; - - let lo = span.lo(); - let hi = span.hi(); - - // Column numbers need to be in bytes, so we can't use the more convenient - // `SourceMap` methods for looking up file coordinates. - let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { - let rpos = file.relative_position(pos); - let line_index = file.lookup_line(rpos)?; - let line_start = file.lines()[line_index]; - // Line numbers and column numbers are 1-based, so add 1 to each. - Some((line_index + 1, (rpos - line_start).to_usize() + 1)) - }; - - let (mut start_line, start_col) = line_and_byte_column(lo)?; - let (mut end_line, end_col) = line_and_byte_column(hi)?; - - // Apply an offset so that code in doctests has correct line numbers. - // FIXME(#79417): Currently we have no way to offset doctest _columns_. - start_line = source_map.doctest_offset_line(&file.name, start_line); - end_line = source_map.doctest_offset_line(&file.name, end_line); - - check_coverage_span(ffi::CoverageSpan { - file_id: file_id.as_u32(), - start_line: start_line as u32, - start_col: start_col as u32, - end_line: end_line as u32, - end_col: end_col as u32, - }) -} - -fn ensure_non_empty_span( - source_map: &SourceMap, - fn_cov_info: &FunctionCoverageInfo, - span: Span, -) -> Option { - if !span.is_empty() { - return Some(span); - } - - let lo = span.lo(); - let hi = span.hi(); - - // The span is empty, so try to expand it to cover an adjacent '{' or '}', - // but only within the bounds of the body span. - let try_next = hi < fn_cov_info.body_span.hi(); - let try_prev = fn_cov_info.body_span.lo() < lo; - if !(try_next || try_prev) { - return None; - } - - source_map - .span_to_source(span, |src, start, end| try { - // We're only checking for specific ASCII characters, so we don't - // have to worry about multi-byte code points. - if try_next && src.as_bytes()[end] == b'{' { - Some(span.with_hi(hi + BytePos(1))) - } else if try_prev && src.as_bytes()[start - 1] == b'}' { - Some(span.with_lo(lo - BytePos(1))) - } else { - None - } - }) - .ok()? -} - -/// If `llvm-cov` sees a source region that is improperly ordered (end < start), -/// it will immediately exit with a fatal error. To prevent that from happening, -/// discard regions that are improperly ordered, or might be interpreted in a -/// way that makes them improperly ordered. -fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option { - let ffi::CoverageSpan { file_id: _, start_line, start_col, end_line, end_col } = cov_span; - - // Line/column coordinates are supposed to be 1-based. If we ever emit - // coordinates of 0, `llvm-cov` might misinterpret them. - let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); - // Coverage mappings use the high bit of `end_col` to indicate that a - // region is actually a "gap" region, so make sure it's unset. - let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; - // If a region is improperly ordered (end < start), `llvm-cov` will exit - // with a fatal error, which is inconvenient for users and hard to debug. - let is_ordered = (start_line, start_col) <= (end_line, end_col); - - if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(cov_span) - } else { - debug!( - ?cov_span, - ?all_nonzero, - ?end_col_has_high_bit_unset, - ?is_ordered, - "Skipping source region that would be misinterpreted or rejected by LLVM" - ); - // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper source region: {cov_span:?}"); - None - } -} diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 9f398107fc61..3dfb86d422dd 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -17,7 +17,6 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(rustdoc_internals)] -#![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 33f9a2bdca6b..11a4e7f89a7c 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -155,6 +155,22 @@ impl Debug for CoverageKind { } } +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct SourceRegion { + pub start_line: u32, + pub start_col: u32, + pub end_line: u32, + pub end_col: u32, +} + +impl Debug for SourceRegion { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + let &Self { start_line, start_col, end_line, end_col } = self; + write!(fmt, "{start_line}:{start_col} - {end_line}:{end_col}") + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum Op { @@ -216,7 +232,7 @@ impl MappingKind { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct Mapping { pub kind: MappingKind, - pub span: Span, + pub source_region: SourceRegion, } /// Stores per-function coverage information attached to a `mir::Body`, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ece468947c25..2bfcd0a62274 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -603,8 +603,8 @@ fn write_function_coverage_info( for (id, expression) in expressions.iter_enumerated() { writeln!(w, "{INDENT}coverage {id:?} => {expression:?};")?; } - for coverage::Mapping { kind, span } in mappings { - writeln!(w, "{INDENT}coverage {kind:?} => {span:?};")?; + for coverage::Mapping { kind, source_region } in mappings { + writeln!(w, "{INDENT}coverage {kind:?} => {source_region:?};")?; } writeln!(w)?; diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 02fd289b6ef6..e8b3d80be021 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -13,15 +13,16 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::mir::coverage::{ - CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, + CoverageKind, DecisionInfo, FunctionCoverageInfo, Mapping, MappingKind, SourceRegion, }; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; -use rustc_span::Span; use rustc_span::def_id::LocalDefId; +use rustc_span::source_map::SourceMap; +use rustc_span::{BytePos, Pos, SourceFile, Span}; use tracing::{debug, debug_span, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; @@ -96,7 +97,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: let coverage_counters = CoverageCounters::make_bcb_counters(&basic_coverage_blocks, &bcbs_with_counter_mappings); - let mappings = create_mappings(&extracted_mappings, &coverage_counters); + let mappings = create_mappings(tcx, &hir_info, &extracted_mappings, &coverage_counters); if mappings.is_empty() { // No spans could be converted into valid mappings, so skip this function. debug!("no spans could be converted into valid mappings; skipping"); @@ -135,12 +136,18 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: /// /// Precondition: All BCBs corresponding to those spans have been given /// coverage counters. -fn create_mappings( +fn create_mappings<'tcx>( + tcx: TyCtxt<'tcx>, + hir_info: &ExtractedHirInfo, extracted_mappings: &ExtractedMappings, coverage_counters: &CoverageCounters, ) -> Vec { + let source_map = tcx.sess.source_map(); + let file = source_map.lookup_source_file(hir_info.body_span.lo()); + let term_for_bcb = |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); + let region_for_span = |span: Span| make_source_region(source_map, hir_info, &file, span); // Fully destructure the mappings struct to make sure we don't miss any kinds. let ExtractedMappings { @@ -153,20 +160,22 @@ fn create_mappings( } = extracted_mappings; let mut mappings = Vec::new(); - mappings.extend(code_mappings.iter().map( + mappings.extend(code_mappings.iter().filter_map( // Ordinary code mappings are the simplest kind. |&mappings::CodeMapping { span, bcb }| { + let source_region = region_for_span(span)?; let kind = MappingKind::Code(term_for_bcb(bcb)); - Mapping { kind, span } + Some(Mapping { kind, source_region }) }, )); - mappings.extend(branch_pairs.iter().map( + mappings.extend(branch_pairs.iter().filter_map( |&mappings::BranchPair { span, true_bcb, false_bcb }| { let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); let kind = MappingKind::Branch { true_term, false_term }; - Mapping { kind, span } + let source_region = region_for_span(span)?; + Some(Mapping { kind, source_region }) }, )); @@ -174,7 +183,7 @@ fn create_mappings( |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); // MCDC branch mappings are appended with their decisions in case decisions were ignored. - mappings.extend(mcdc_degraded_branches.iter().map( + mappings.extend(mcdc_degraded_branches.iter().filter_map( |&mappings::MCDCBranch { span, true_bcb, @@ -183,9 +192,10 @@ fn create_mappings( true_index: _, false_index: _, }| { + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - Mapping { kind: MappingKind::Branch { true_term, false_term }, span } + Some(Mapping { kind: MappingKind::Branch { true_term, false_term }, source_region }) }, )); @@ -193,7 +203,7 @@ fn create_mappings( let num_conditions = branches.len() as u16; let conditions = branches .into_iter() - .map( + .filter_map( |&mappings::MCDCBranch { span, true_bcb, @@ -202,29 +212,31 @@ fn create_mappings( true_index: _, false_index: _, }| { + let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - Mapping { + Some(Mapping { kind: MappingKind::MCDCBranch { true_term, false_term, mcdc_params: condition_info, }, - span, - } + source_region, + }) }, ) .collect::>(); - if conditions.len() == num_conditions as usize { + if conditions.len() == num_conditions as usize + && let Some(source_region) = region_for_span(decision.span) + { // LLVM requires end index for counter mapping regions. let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32, num_conditions, }); mappings.extend( - std::iter::once(Mapping { kind, span: decision.span }) - .chain(conditions.into_iter()), + std::iter::once(Mapping { kind, source_region }).chain(conditions.into_iter()), ); } else { mappings.extend(conditions.into_iter().map(|mapping| { @@ -233,7 +245,10 @@ fn create_mappings( else { unreachable!("all mappings here are MCDCBranch as shown above"); }; - Mapping { kind: MappingKind::Branch { true_term, false_term }, span: mapping.span } + Mapping { + kind: MappingKind::Branch { true_term, false_term }, + source_region: mapping.source_region, + } })) } } @@ -376,6 +391,121 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb data.statements.insert(0, statement); } +fn ensure_non_empty_span( + source_map: &SourceMap, + hir_info: &ExtractedHirInfo, + span: Span, +) -> Option { + if !span.is_empty() { + return Some(span); + } + + let lo = span.lo(); + let hi = span.hi(); + + // The span is empty, so try to expand it to cover an adjacent '{' or '}', + // but only within the bounds of the body span. + let try_next = hi < hir_info.body_span.hi(); + let try_prev = hir_info.body_span.lo() < lo; + if !(try_next || try_prev) { + return None; + } + + source_map + .span_to_source(span, |src, start, end| try { + // We're only checking for specific ASCII characters, so we don't + // have to worry about multi-byte code points. + if try_next && src.as_bytes()[end] == b'{' { + Some(span.with_hi(hi + BytePos(1))) + } else if try_prev && src.as_bytes()[start - 1] == b'}' { + Some(span.with_lo(lo - BytePos(1))) + } else { + None + } + }) + .ok()? +} + +/// Converts the span into its start line and column, and end line and column. +/// +/// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by +/// the compiler, these column numbers are denoted in **bytes**, because that's what +/// LLVM's `llvm-cov` tool expects to see in coverage maps. +/// +/// Returns `None` if the conversion failed for some reason. This shouldn't happen, +/// but it's hard to rule out entirely (especially in the presence of complex macros +/// or other expansions), and if it does happen then skipping a span or function is +/// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. +fn make_source_region( + source_map: &SourceMap, + hir_info: &ExtractedHirInfo, + file: &SourceFile, + span: Span, +) -> Option { + let span = ensure_non_empty_span(source_map, hir_info, span)?; + + let lo = span.lo(); + let hi = span.hi(); + + // Column numbers need to be in bytes, so we can't use the more convenient + // `SourceMap` methods for looking up file coordinates. + let line_and_byte_column = |pos: BytePos| -> Option<(usize, usize)> { + let rpos = file.relative_position(pos); + let line_index = file.lookup_line(rpos)?; + let line_start = file.lines()[line_index]; + // Line numbers and column numbers are 1-based, so add 1 to each. + Some((line_index + 1, (rpos - line_start).to_usize() + 1)) + }; + + let (mut start_line, start_col) = line_and_byte_column(lo)?; + let (mut end_line, end_col) = line_and_byte_column(hi)?; + + // Apply an offset so that code in doctests has correct line numbers. + // FIXME(#79417): Currently we have no way to offset doctest _columns_. + start_line = source_map.doctest_offset_line(&file.name, start_line); + end_line = source_map.doctest_offset_line(&file.name, end_line); + + check_source_region(SourceRegion { + start_line: start_line as u32, + start_col: start_col as u32, + end_line: end_line as u32, + end_col: end_col as u32, + }) +} + +/// If `llvm-cov` sees a source region that is improperly ordered (end < start), +/// it will immediately exit with a fatal error. To prevent that from happening, +/// discard regions that are improperly ordered, or might be interpreted in a +/// way that makes them improperly ordered. +fn check_source_region(source_region: SourceRegion) -> Option { + let SourceRegion { start_line, start_col, end_line, end_col } = source_region; + + // Line/column coordinates are supposed to be 1-based. If we ever emit + // coordinates of 0, `llvm-cov` might misinterpret them. + let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); + // Coverage mappings use the high bit of `end_col` to indicate that a + // region is actually a "gap" region, so make sure it's unset. + let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; + // If a region is improperly ordered (end < start), `llvm-cov` will exit + // with a fatal error, which is inconvenient for users and hard to debug. + let is_ordered = (start_line, start_col) <= (end_line, end_col); + + if all_nonzero && end_col_has_high_bit_unset && is_ordered { + Some(source_region) + } else { + debug!( + ?source_region, + ?all_nonzero, + ?end_col_has_high_bit_unset, + ?is_ordered, + "Skipping source region that would be misinterpreted or rejected by LLVM" + ); + // If this happens in a debug build, ICE to make it easier to notice. + debug_assert!(false, "Improper source region: {source_region:?}"); + None + } +} + /// Function information extracted from HIR by the coverage instrumentor. #[derive(Debug)] struct ExtractedHirInfo { diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index 39d52ba698a4..cbb11d50f797 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -33,12 +33,12 @@ + coverage ExpressionId(3) => Expression { lhs: Counter(3), op: Add, rhs: Counter(2) }; + coverage ExpressionId(4) => Expression { lhs: Expression(3), op: Add, rhs: Counter(1) }; + coverage ExpressionId(5) => Expression { lhs: Expression(4), op: Add, rhs: Expression(2) }; -+ coverage Code(Counter(0)) => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); -+ coverage Code(Counter(3)) => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); -+ coverage Code(Counter(2)) => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); -+ coverage Code(Counter(1)) => $DIR/branch_match_arms.rs:18:17: 18:33 (#0); -+ coverage Code(Expression(2)) => $DIR/branch_match_arms.rs:19:17: 19:33 (#0); -+ coverage Code(Expression(5)) => $DIR/branch_match_arms.rs:21:2: 21:2 (#0); ++ coverage Code(Counter(0)) => 14:1 - 15:21; ++ coverage Code(Counter(3)) => 16:17 - 16:33; ++ coverage Code(Counter(2)) => 17:17 - 17:33; ++ coverage Code(Counter(1)) => 18:17 - 18:33; ++ coverage Code(Expression(2)) => 19:17 - 19:33; ++ coverage Code(Expression(5)) => 21:1 - 21:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 148ff86354b5..2efb1fd0a17a 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -5,7 +5,7 @@ let mut _0: bool; + coverage body span: $DIR/instrument_coverage.rs:19:18: 21:2 (#0) -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:19:1: 21:2 (#0); ++ coverage Code(Counter(0)) => 19:1 - 21:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index b480d1ac13a7..a179824d6c73 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage.rs:10:11: 16:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Add, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:10:1: 10:11 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:12:12: 12:17 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:13:13: 13:18 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:14:10: 14:10 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:16:2: 16:2 (#0); ++ coverage Code(Counter(0)) => 10:1 - 10:11; ++ coverage Code(Expression(0)) => 12:12 - 12:17; ++ coverage Code(Counter(0)) => 13:13 - 13:18; ++ coverage Code(Counter(1)) => 14:9 - 14:10; ++ coverage Code(Counter(0)) => 16:1 - 16:2; + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 2c7ec6e85eb0..082539369f70 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -9,11 +9,11 @@ coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); - coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); - coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); - coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); - coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); + coverage Code(Counter(0)) => 13:1 - 14:36; + coverage Code(Expression(0)) => 14:37 - 14:39; + coverage Code(Counter(1)) => 14:38 - 14:39; + coverage Code(Counter(0)) => 15:1 - 15:2; + coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; bb0: { Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index c08265eb0e95..8635818c6a7a 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -9,11 +9,11 @@ + coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0); -+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0); ++ coverage Code(Counter(0)) => 13:1 - 14:36; ++ coverage Code(Expression(0)) => 14:37 - 14:39; ++ coverage Code(Counter(1)) => 14:38 - 14:39; ++ coverage Code(Counter(0)) => 15:1 - 15:2; ++ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => 14:8 - 14:36; + bb0: { + Coverage::CounterIncrement(0); From 15b24c46b462d7baf5b1b80656d3ec3c46c73a60 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 23 Nov 2024 13:28:30 +1100 Subject: [PATCH 189/330] Clarify `ChunkSize` invariants. `ChunkedBitSet::is_empty` currently does an unnecessary check. This commit removes that check and adds clarifying comments and an assertion that demonstrate why it's unnecessary. --- compiler/rustc_index/src/bit_set.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index a92394892224..4295ec3f63fd 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -369,9 +369,11 @@ pub struct ChunkedBitSet { #[derive(Clone, Debug, PartialEq, Eq)] enum Chunk { /// A chunk that is all zeros; we don't represent the zeros explicitly. + /// The `ChunkSize` is always non-zero. Zeros(ChunkSize), /// A chunk that is all ones; we don't represent the ones explicitly. + /// `ChunkSize` is always non-zero. Ones(ChunkSize), /// A chunk that has a mix of zeros and ones, which are represented @@ -384,8 +386,10 @@ enum Chunk { /// words are always be zero, as are any excess bits in the final in-use /// word. /// - /// The second field is the count of 1s set in the chunk, and must satisfy - /// `0 < count < chunk_domain_size`. + /// The first `ChunkSize` field is always non-zero. + /// + /// The second `ChunkSize` field is the count of 1s set in the chunk, and + /// must satisfy `0 < count < chunk_domain_size`. /// /// The words are within an `Rc` because it's surprisingly common to /// duplicate an entire chunk, e.g. in `ChunkedBitSet::clone_from()`, or @@ -461,7 +465,7 @@ impl ChunkedBitSet { } pub fn is_empty(&self) -> bool { - self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..) | Chunk::Ones(0))) + self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..))) } /// Returns `true` if `self` contains `elem`. @@ -1005,7 +1009,7 @@ impl Chunk { } fn new(chunk_domain_size: usize, is_empty: bool) -> Self { - debug_assert!(chunk_domain_size <= CHUNK_BITS); + debug_assert!(0 < chunk_domain_size && chunk_domain_size <= CHUNK_BITS); let chunk_domain_size = chunk_domain_size as ChunkSize; if is_empty { Zeros(chunk_domain_size) } else { Ones(chunk_domain_size) } } From ff780025663189ac7ec81d40a7cf309e45bd056a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 23 Nov 2024 13:14:29 +1100 Subject: [PATCH 190/330] Tiny `ChunkedBitSet` improvements. - Fix a typo in a comment. - Remove unnecessary `Chunk::` qualifiers. - Rename `ChunkedBitIter::bitset` as `ChunkedBitIter::bit_set`, because `bit_set` is the form used everywhere else. - Avoid some unnecessary local variables. --- compiler/rustc_index/src/bit_set.rs | 35 +++++++++++++---------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 4295ec3f63fd..0d52e7173919 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -383,8 +383,7 @@ enum Chunk { /// turns out to be both simpler and have better performance than /// allocating the minimum number of words, largely because we avoid having /// to store the length, which would make this type larger. These excess - /// words are always be zero, as are any excess bits in the final in-use - /// word. + /// words are always zero, as are any excess bits in the final in-use word. /// /// The first `ChunkSize` field is always non-zero. /// @@ -465,7 +464,7 @@ impl ChunkedBitSet { } pub fn is_empty(&self) -> bool { - self.chunks.iter().all(|chunk| matches!(chunk, Chunk::Zeros(..))) + self.chunks.iter().all(|chunk| matches!(chunk, Zeros(..))) } /// Returns `true` if `self` contains `elem`. @@ -855,7 +854,7 @@ impl BitRelations> for BitSet { words = &mut words[..CHUNK_WORDS]; } match chunk { - Chunk::Zeros(..) => { + Zeros(..) => { for word in words { if *word != 0 { changed = true; @@ -863,8 +862,8 @@ impl BitRelations> for BitSet { } } } - Chunk::Ones(..) => (), - Chunk::Mixed(_, _, data) => { + Ones(..) => (), + Mixed(_, _, data) => { for (i, word) in words.iter_mut().enumerate() { let new_val = *word & data[i]; if new_val != *word { @@ -902,22 +901,22 @@ impl Clone for ChunkedBitSet { pub struct ChunkedBitIter<'a, T: Idx> { index: usize, - bitset: &'a ChunkedBitSet, + bit_set: &'a ChunkedBitSet, } impl<'a, T: Idx> ChunkedBitIter<'a, T> { #[inline] - fn new(bitset: &'a ChunkedBitSet) -> ChunkedBitIter<'a, T> { - ChunkedBitIter { index: 0, bitset } + fn new(bit_set: &'a ChunkedBitSet) -> ChunkedBitIter<'a, T> { + ChunkedBitIter { index: 0, bit_set } } } impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> { type Item = T; fn next(&mut self) -> Option { - while self.index < self.bitset.domain_size() { + while self.index < self.bit_set.domain_size() { let elem = T::new(self.index); - let chunk = &self.bitset.chunks[chunk_index(elem)]; + let chunk = &self.bit_set.chunks[chunk_index(elem)]; match &chunk { Zeros(chunk_domain_size) => { self.index += *chunk_domain_size as usize; @@ -954,17 +953,17 @@ impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> { init = f(init, item); } let start_chunk = self.index / CHUNK_BITS; - let chunks = &self.bitset.chunks[start_chunk..]; + let chunks = &self.bit_set.chunks[start_chunk..]; for (i, chunk) in chunks.iter().enumerate() { let base = (start_chunk + i) * CHUNK_BITS; match chunk { - Chunk::Zeros(_) => (), - Chunk::Ones(limit) => { + Zeros(_) => (), + Ones(limit) => { for j in 0..(*limit as usize) { init = f(init, T::new(base + j)); } } - Chunk::Mixed(_, _, words) => { + Mixed(_, _, words) => { init = BitIter::new(&**words).fold(init, |val, mut item: T| { item.increment_by(base); f(val, item) @@ -1302,15 +1301,13 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> { // Get the position of the next set bit in the current word, // then clear the bit. let bit_pos = self.word.trailing_zeros() as usize; - let bit = 1 << bit_pos; - self.word ^= bit; + self.word ^= 1 << bit_pos; return Some(T::new(bit_pos + self.offset)); } // Move onto the next word. `wrapping_add()` is needed to handle // the degenerate initial value given to `offset` in `new()`. - let word = self.iter.next()?; - self.word = *word; + self.word = *self.iter.next()?; self.offset = self.offset.wrapping_add(WORD_BITS); } } From ded4dfde19d0bbe526e64edb32931a2b42b2b848 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 07:30:20 +1100 Subject: [PATCH 191/330] Speed up `ChunkedBitIter` The current implementation is slow because it does an operation for every bit in the set, even zero bits. So if you have a large bitset with many zero bits (which is common) it's very slow. This commit improves the iterator to skip over `Zeros` chunks in a single step, and uses the fast `BitIter` for `Mixed` chunks. It also removes the existing `fold` implementation, which was only there because the old iterator was slow. --- compiler/rustc_index/src/bit_set.rs | 95 ++++++++++++----------------- 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 0d52e7173919..0930e3d830ce 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -613,6 +613,18 @@ impl ChunkedBitSet { } } + fn chunk_iter(&self, chunk_index: usize) -> ChunkIter<'_> { + match self.chunks.get(chunk_index) { + Some(Zeros(_chunk_domain_size)) => ChunkIter::Zeros, + Some(Ones(chunk_domain_size)) => ChunkIter::Ones(0..*chunk_domain_size as usize), + Some(Mixed(chunk_domain_size, _, ref words)) => { + let num_words = num_words(*chunk_domain_size as usize); + ChunkIter::Mixed(BitIter::new(&words[0..num_words])) + } + None => ChunkIter::Finished, + } + } + bit_relations_inherent_impls! {} } @@ -900,78 +912,44 @@ impl Clone for ChunkedBitSet { } pub struct ChunkedBitIter<'a, T: Idx> { - index: usize, bit_set: &'a ChunkedBitSet, + + // The index of the current chunk. + chunk_index: usize, + + // The sub-iterator for the current chunk. + chunk_iter: ChunkIter<'a>, } impl<'a, T: Idx> ChunkedBitIter<'a, T> { #[inline] fn new(bit_set: &'a ChunkedBitSet) -> ChunkedBitIter<'a, T> { - ChunkedBitIter { index: 0, bit_set } + ChunkedBitIter { bit_set, chunk_index: 0, chunk_iter: bit_set.chunk_iter(0) } } } impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> { type Item = T; - fn next(&mut self) -> Option { - while self.index < self.bit_set.domain_size() { - let elem = T::new(self.index); - let chunk = &self.bit_set.chunks[chunk_index(elem)]; - match &chunk { - Zeros(chunk_domain_size) => { - self.index += *chunk_domain_size as usize; - } - Ones(_chunk_domain_size) => { - self.index += 1; - return Some(elem); - } - Mixed(_chunk_domain_size, _, words) => loop { - let elem = T::new(self.index); - self.index += 1; - let (word_index, mask) = chunk_word_index_and_mask(elem); - if (words[word_index] & mask) != 0 { - return Some(elem); - } - if self.index % CHUNK_BITS == 0 { - break; - } - }, - } - } - None - } - fn fold(mut self, mut init: B, mut f: F) -> B - where - F: FnMut(B, Self::Item) -> B, - { - // If `next` has already been called, we may not be at the start of a chunk, so we first - // advance the iterator to the start of the next chunk, before proceeding in chunk sized - // steps. - while self.index % CHUNK_BITS != 0 { - let Some(item) = self.next() else { return init }; - init = f(init, item); - } - let start_chunk = self.index / CHUNK_BITS; - let chunks = &self.bit_set.chunks[start_chunk..]; - for (i, chunk) in chunks.iter().enumerate() { - let base = (start_chunk + i) * CHUNK_BITS; - match chunk { - Zeros(_) => (), - Ones(limit) => { - for j in 0..(*limit as usize) { - init = f(init, T::new(base + j)); + fn next(&mut self) -> Option { + loop { + match &mut self.chunk_iter { + ChunkIter::Zeros => {} + ChunkIter::Ones(iter) => { + if let Some(next) = iter.next() { + return Some(T::new(next + self.chunk_index * CHUNK_BITS)); } } - Mixed(_, _, words) => { - init = BitIter::new(&**words).fold(init, |val, mut item: T| { - item.increment_by(base); - f(val, item) - }); + ChunkIter::Mixed(iter) => { + if let Some(next) = iter.next() { + return Some(T::new(next + self.chunk_index * CHUNK_BITS)); + } } + ChunkIter::Finished => return None, } + self.chunk_index += 1; + self.chunk_iter = self.bit_set.chunk_iter(self.chunk_index); } - init } } @@ -1023,6 +1001,13 @@ impl Chunk { } } +enum ChunkIter<'a> { + Zeros, + Ones(Range), + Mixed(BitIter<'a, usize>), + Finished, +} + // Applies a function to mutate a bitset, and returns true if any // of the applications return true fn sequential_update( From 346929cb809bed10de1f69a1c62fcdb63860ecd6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 23 Nov 2024 09:03:35 +1100 Subject: [PATCH 192/330] Remove unused `HybridBitSet` methods from `BitSetExt`. --- .../src/framework/lattice.rs | 16 +-------------- .../rustc_mir_dataflow/src/framework/mod.rs | 20 +------------------ 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 6d2a7a099a09..e2b56aedca3a 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -40,7 +40,7 @@ use std::iter; -use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::{Idx, IndexVec}; use crate::framework::BitSetExt; @@ -227,20 +227,6 @@ impl> BitSetExt for MaybeReachable { fn contains(&self, elem: T) -> bool { self.contains(elem) } - - fn union(&mut self, other: &HybridBitSet) { - match self { - MaybeReachable::Unreachable => {} - MaybeReachable::Reachable(set) => set.union(other), - } - } - - fn subtract(&mut self, other: &HybridBitSet) { - match self { - MaybeReachable::Unreachable => {} - MaybeReachable::Reachable(set) => set.subtract(other), - } - } } impl Clone for MaybeReachable { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index bb652a75caa3..f1ea94e16893 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -35,7 +35,7 @@ use std::cmp::Ordering; use rustc_data_structures::work_queue::WorkQueue; -use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::{Idx, IndexVec}; use rustc_middle::bug; use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal}; @@ -63,36 +63,18 @@ pub use self::visitor::{ResultsVisitor, visit_results}; /// operations needed by all of them. pub trait BitSetExt { fn contains(&self, elem: T) -> bool; - fn union(&mut self, other: &HybridBitSet); - fn subtract(&mut self, other: &HybridBitSet); } impl BitSetExt for BitSet { fn contains(&self, elem: T) -> bool { self.contains(elem) } - - fn union(&mut self, other: &HybridBitSet) { - self.union(other); - } - - fn subtract(&mut self, other: &HybridBitSet) { - self.subtract(other); - } } impl BitSetExt for ChunkedBitSet { fn contains(&self, elem: T) -> bool { self.contains(elem) } - - fn union(&mut self, other: &HybridBitSet) { - self.union(other); - } - - fn subtract(&mut self, other: &HybridBitSet) { - self.subtract(other); - } } /// A dataflow problem with an arbitrarily complex transfer function. From 0df6a018e163e0e5e8536bcc4bfc30e1b4ba2be0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 13:08:03 +1100 Subject: [PATCH 193/330] Stop using `HybridBitSet` in dataflow diffs. As part of the larger goal of reducing `HybridBitSet` use in general. This code is for debugging only and isn't performance sensitive, so `ChunkedBitSet` should be fine. --- compiler/rustc_mir_dataflow/src/framework/fmt.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs index c177d98106f3..dc176ba2d03e 100644 --- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs +++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs @@ -4,7 +4,7 @@ use std::fmt; use rustc_index::Idx; -use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet}; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use super::lattice::MaybeReachable; @@ -85,8 +85,8 @@ where let size = self.domain_size(); assert_eq!(size, old.domain_size()); - let mut set_in_self = HybridBitSet::new_empty(size); - let mut cleared_in_self = HybridBitSet::new_empty(size); + let mut set_in_self = ChunkedBitSet::new_empty(size); + let mut cleared_in_self = ChunkedBitSet::new_empty(size); for i in (0..size).map(T::new) { match (self.contains(i), old.contains(i)) { @@ -112,8 +112,8 @@ where let size = self.domain_size(); assert_eq!(size, old.domain_size()); - let mut set_in_self = HybridBitSet::new_empty(size); - let mut cleared_in_self = HybridBitSet::new_empty(size); + let mut set_in_self = ChunkedBitSet::new_empty(size); + let mut cleared_in_self = ChunkedBitSet::new_empty(size); for i in (0..size).map(T::new) { match (self.contains(i), old.contains(i)) { @@ -159,8 +159,8 @@ where } fn fmt_diff( - inserted: &HybridBitSet, - removed: &HybridBitSet, + inserted: &ChunkedBitSet, + removed: &ChunkedBitSet, ctxt: &C, f: &mut fmt::Formatter<'_>, ) -> fmt::Result From 688f28d67065be8d67648dc395e288fcaababbb0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 13:08:54 +1100 Subject: [PATCH 194/330] Stop using `HybridBitSet` in clippy. The compiler uses `BitSet`, because the number of locals doesn't get that high, so clippy should do likewise. --- .../clippy/clippy_utils/src/mir/possible_borrower.rs | 10 +++++----- .../clippy/clippy_utils/src/mir/possible_origin.rs | 4 ++-- .../clippy/clippy_utils/src/mir/transitive_relation.rs | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 6b3078f52aff..17e6558a41c4 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -2,7 +2,7 @@ use super::possible_origin::PossibleOriginVisitor; use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::{BitSet, HybridBitSet}; +use rustc_index::bit_set::BitSet; use rustc_lint::LateContext; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{self, Mutability}; @@ -21,14 +21,14 @@ struct PossibleBorrowerVisitor<'a, 'b, 'tcx> { possible_borrower: TransitiveRelation, body: &'b mir::Body<'tcx>, cx: &'a LateContext<'tcx>, - possible_origin: FxHashMap>, + possible_origin: FxHashMap>, } impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> { fn new( cx: &'a LateContext<'tcx>, body: &'b mir::Body<'tcx>, - possible_origin: FxHashMap>, + possible_origin: FxHashMap>, ) -> Self { Self { possible_borrower: TransitiveRelation::default(), @@ -119,7 +119,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> { let mut mutable_variables: Vec = mutable_borrowers .iter() .filter_map(|r| self.possible_origin.get(r)) - .flat_map(HybridBitSet::iter) + .flat_map(BitSet::iter) .collect(); if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() { @@ -171,7 +171,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { #[allow(clippy::module_name_repetitions)] pub struct PossibleBorrowerMap<'b, 'tcx> { /// Mapping `Local -> its possible borrowers` - pub map: FxHashMap>, + pub map: FxHashMap>, maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>, // Caches to avoid allocation of `BitSet` on every query pub bitset: (BitSet, BitSet), diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs index 4157b3f49306..47b93aad20c8 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs @@ -1,7 +1,7 @@ use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::HybridBitSet; +use rustc_index::bit_set::BitSet; use rustc_lint::LateContext; use rustc_middle::mir; @@ -22,7 +22,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> { } } - pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap> { + pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap> { let mut map = FxHashMap::default(); for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { if is_copy(cx, self.body.local_decls[row].ty) { diff --git a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs index 7fe2960739fa..74d1f60af71c 100644 --- a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs +++ b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::HybridBitSet; +use rustc_index::bit_set::BitSet; use rustc_middle::mir; #[derive(Default)] @@ -12,8 +12,8 @@ impl TransitiveRelation { self.relations.entry(a).or_default().push(b); } - pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet { - let mut seen = HybridBitSet::new_empty(domain_size); + pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> BitSet { + let mut seen = BitSet::new_empty(domain_size); let mut stack = vec![a]; while let Some(u) = stack.pop() { if let Some(edges) = self.relations.get(&u) { From b7ff2aedd962e297a30feb1d5a871d0ae00a4916 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 13:12:01 +1100 Subject: [PATCH 195/330] Stop using `HybridBitSet` in `SparseBitMatrix`. Use `ChunkedBitSet` instead. --- compiler/rustc_index/src/bit_set.rs | 31 +++++++++++++++++------------ 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 0930e3d830ce..5446894374f6 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -453,6 +453,11 @@ impl ChunkedBitSet { ChunkedBitSet::new(domain_size, /* is_empty */ false) } + pub fn clear(&mut self) { + let domain_size = self.domain_size(); + *self = ChunkedBitSet::new_empty(domain_size); + } + #[cfg(test)] fn chunks(&self) -> &[Chunk] { &self.chunks @@ -1883,7 +1888,7 @@ impl fmt::Debug for BitMatrix { /// sparse representation. /// /// Initially, every row has no explicit representation. If any bit within a -/// row is set, the entire row is instantiated as `Some()`. +/// row is set, the entire row is instantiated as `Some()`. /// Furthermore, any previously uninstantiated rows prior to it will be /// instantiated as `None`. Those prior rows may themselves become fully /// instantiated later on if any of their bits are set. @@ -1897,7 +1902,7 @@ where C: Idx, { num_columns: usize, - rows: IndexVec>>, + rows: IndexVec>>, } impl SparseBitMatrix { @@ -1906,10 +1911,10 @@ impl SparseBitMatrix { Self { num_columns, rows: IndexVec::new() } } - fn ensure_row(&mut self, row: R) -> &mut HybridBitSet { - // Instantiate any missing rows up to and including row `row` with an empty HybridBitSet. - // Then replace row `row` with a full HybridBitSet if necessary. - self.rows.get_or_insert_with(row, || HybridBitSet::new_empty(self.num_columns)) + fn ensure_row(&mut self, row: R) -> &mut ChunkedBitSet { + // Instantiate any missing rows up to and including row `row` with an empty ChunkedBitSet. + // Then replace row `row` with a full ChunkedBitSet if necessary. + self.rows.get_or_insert_with(row, || ChunkedBitSet::new_empty(self.num_columns)) } /// Sets the cell at `(row, column)` to true. Put another way, insert @@ -1983,17 +1988,17 @@ impl SparseBitMatrix { self.row(row).into_iter().flat_map(|r| r.iter()) } - pub fn row(&self, row: R) -> Option<&HybridBitSet> { + pub fn row(&self, row: R) -> Option<&ChunkedBitSet> { self.rows.get(row)?.as_ref() } /// Intersects `row` with `set`. `set` can be either `BitSet` or - /// `HybridBitSet`. Has no effect if `row` does not exist. + /// `ChunkedBitSet`. Has no effect if `row` does not exist. /// /// Returns true if the row was changed. pub fn intersect_row(&mut self, row: R, set: &Set) -> bool where - HybridBitSet: BitRelations, + ChunkedBitSet: BitRelations, { match self.rows.get_mut(row) { Some(Some(row)) => row.intersect(set), @@ -2002,12 +2007,12 @@ impl SparseBitMatrix { } /// Subtracts `set` from `row`. `set` can be either `BitSet` or - /// `HybridBitSet`. Has no effect if `row` does not exist. + /// `ChunkedBitSet`. Has no effect if `row` does not exist. /// /// Returns true if the row was changed. pub fn subtract_row(&mut self, row: R, set: &Set) -> bool where - HybridBitSet: BitRelations, + ChunkedBitSet: BitRelations, { match self.rows.get_mut(row) { Some(Some(row)) => row.subtract(set), @@ -2016,12 +2021,12 @@ impl SparseBitMatrix { } /// Unions `row` with `set`. `set` can be either `BitSet` or - /// `HybridBitSet`. + /// `ChunkedBitSet`. /// /// Returns true if the row was changed. pub fn union_row(&mut self, row: R, set: &Set) -> bool where - HybridBitSet: BitRelations, + ChunkedBitSet: BitRelations, { self.ensure_row(row).union(set) } From 4846c1922d13d143eb346e8747e282eb46ad45b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 13:17:12 +1100 Subject: [PATCH 196/330] Remove `HybridBitSet`. It's no longer used. --- Cargo.lock | 1 - compiler/rustc_index/Cargo.toml | 1 - compiler/rustc_index/src/bit_set.rs | 514 ---------------------- compiler/rustc_index/src/bit_set/tests.rs | 180 +------- 4 files changed, 3 insertions(+), 693 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29176a3ae8e2..8745f78ce98c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3820,7 +3820,6 @@ dependencies = [ name = "rustc_index" version = "0.0.0" dependencies = [ - "arrayvec", "rustc_index_macros", "rustc_macros", "rustc_serialize", diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index f7d18f84e345..33e8e2824c7a 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -arrayvec = { version = "0.7", default-features = false } rustc_index_macros = { path = "../rustc_index_macros", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 5446894374f6..de6fa132ca07 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -4,7 +4,6 @@ use std::rc::Rc; use std::{fmt, iter, mem, slice}; use Chunk::*; -use arrayvec::ArrayVec; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_Generic, Encodable_Generic}; use smallvec::{SmallVec, smallvec}; @@ -240,45 +239,6 @@ impl BitSet { BitIter::new(&self.words) } - /// Set `self = self | other`. In contrast to `union` returns `true` if the set contains at - /// least one bit that is not in `other` (i.e. `other` is not a superset of `self`). - /// - /// This is an optimization for union of a hybrid bitset. - fn reverse_union_sparse(&mut self, sparse: &SparseBitSet) -> bool { - assert!(sparse.domain_size == self.domain_size); - self.clear_excess_bits(); - - let mut not_already = false; - // Index of the current word not yet merged. - let mut current_index = 0; - // Mask of bits that came from the sparse set in the current word. - let mut new_bit_mask = 0; - for (word_index, mask) in sparse.iter().map(|x| word_index_and_mask(*x)) { - // Next bit is in a word not inspected yet. - if word_index > current_index { - self.words[current_index] |= new_bit_mask; - // Were there any bits in the old word that did not occur in the sparse set? - not_already |= (self.words[current_index] ^ new_bit_mask) != 0; - // Check all words we skipped for any set bit. - not_already |= self.words[current_index + 1..word_index].iter().any(|&x| x != 0); - // Update next word. - current_index = word_index; - // Reset bit mask, no bits have been merged yet. - new_bit_mask = 0; - } - // Add bit and mark it as coming from the sparse set. - // self.words[word_index] |= mask; - new_bit_mask |= mask; - } - self.words[current_index] |= new_bit_mask; - // Any bits in the last inspected word that were not in the sparse set? - not_already |= (self.words[current_index] ^ new_bit_mask) != 0; - // Any bits in the tail? Note `clear_excess_bits` before. - not_already |= self.words[current_index + 1..].iter().any(|&x| x != 0); - - not_already - } - pub fn last_set_in(&self, range: impl RangeBounds) -> Option { let (start, end) = inclusive_start_end(range, self.domain_size)?; let (start_word_index, _) = word_index_and_mask(start); @@ -829,30 +789,6 @@ impl BitRelations> for ChunkedBitSet { } } -impl BitRelations> for ChunkedBitSet { - fn union(&mut self, other: &HybridBitSet) -> bool { - // FIXME: This is slow if `other` is dense, but it hasn't been a problem - // in practice so far. - // If a faster implementation of this operation is required, consider - // reopening https://github.com/rust-lang/rust/pull/94625 - assert_eq!(self.domain_size, other.domain_size()); - sequential_update(|elem| self.insert(elem), other.iter()) - } - - fn subtract(&mut self, other: &HybridBitSet) -> bool { - // FIXME: This is slow if `other` is dense, but it hasn't been a problem - // in practice so far. - // If a faster implementation of this operation is required, consider - // reopening https://github.com/rust-lang/rust/pull/94625 - assert_eq!(self.domain_size, other.domain_size()); - sequential_update(|elem| self.remove(elem), other.iter()) - } - - fn intersect(&mut self, _other: &HybridBitSet) -> bool { - unimplemented!("implement if/when necessary"); - } -} - impl BitRelations> for BitSet { fn union(&mut self, other: &ChunkedBitSet) -> bool { sequential_update(|elem| self.insert(elem), other.iter()) @@ -1022,176 +958,6 @@ fn sequential_update( it.fold(false, |changed, elem| self_update(elem) | changed) } -// Optimization of intersection for SparseBitSet that's generic -// over the RHS -fn sparse_intersect( - set: &mut SparseBitSet, - other_contains: impl Fn(&T) -> bool, -) -> bool { - let size = set.elems.len(); - set.elems.retain(|elem| other_contains(elem)); - set.elems.len() != size -} - -// Optimization of dense/sparse intersection. The resulting set is -// guaranteed to be at most the size of the sparse set, and hence can be -// represented as a sparse set. Therefore the sparse set is copied and filtered, -// then returned as the new set. -fn dense_sparse_intersect( - dense: &BitSet, - sparse: &SparseBitSet, -) -> (SparseBitSet, bool) { - let mut sparse_copy = sparse.clone(); - sparse_intersect(&mut sparse_copy, |el| dense.contains(*el)); - let n = sparse_copy.len(); - (sparse_copy, n != dense.count()) -} - -// hybrid REL dense -impl BitRelations> for HybridBitSet { - fn union(&mut self, other: &BitSet) -> bool { - assert_eq!(self.domain_size(), other.domain_size); - match self { - HybridBitSet::Sparse(sparse) => { - // `self` is sparse and `other` is dense. To - // merge them, we have two available strategies: - // * Densify `self` then merge other - // * Clone other then integrate bits from `self` - // The second strategy requires dedicated method - // since the usual `union` returns the wrong - // result. In the dedicated case the computation - // is slightly faster if the bits of the sparse - // bitset map to only few words of the dense - // representation, i.e. indices are near each - // other. - // - // Benchmarking seems to suggest that the second - // option is worth it. - let mut new_dense = other.clone(); - let changed = new_dense.reverse_union_sparse(sparse); - *self = HybridBitSet::Dense(new_dense); - changed - } - - HybridBitSet::Dense(dense) => dense.union(other), - } - } - - fn subtract(&mut self, other: &BitSet) -> bool { - assert_eq!(self.domain_size(), other.domain_size); - match self { - HybridBitSet::Sparse(sparse) => { - sequential_update(|elem| sparse.remove(elem), other.iter()) - } - HybridBitSet::Dense(dense) => dense.subtract(other), - } - } - - fn intersect(&mut self, other: &BitSet) -> bool { - assert_eq!(self.domain_size(), other.domain_size); - match self { - HybridBitSet::Sparse(sparse) => sparse_intersect(sparse, |elem| other.contains(*elem)), - HybridBitSet::Dense(dense) => dense.intersect(other), - } - } -} - -// dense REL hybrid -impl BitRelations> for BitSet { - fn union(&mut self, other: &HybridBitSet) -> bool { - assert_eq!(self.domain_size, other.domain_size()); - match other { - HybridBitSet::Sparse(sparse) => { - sequential_update(|elem| self.insert(elem), sparse.iter().cloned()) - } - HybridBitSet::Dense(dense) => self.union(dense), - } - } - - fn subtract(&mut self, other: &HybridBitSet) -> bool { - assert_eq!(self.domain_size, other.domain_size()); - match other { - HybridBitSet::Sparse(sparse) => { - sequential_update(|elem| self.remove(elem), sparse.iter().cloned()) - } - HybridBitSet::Dense(dense) => self.subtract(dense), - } - } - - fn intersect(&mut self, other: &HybridBitSet) -> bool { - assert_eq!(self.domain_size, other.domain_size()); - match other { - HybridBitSet::Sparse(sparse) => { - let (updated, changed) = dense_sparse_intersect(self, sparse); - - // We can't directly assign the SparseBitSet to the BitSet, and - // doing `*self = updated.to_dense()` would cause a drop / reallocation. Instead, - // the BitSet is cleared and `updated` is copied into `self`. - self.clear(); - for elem in updated.iter() { - self.insert(*elem); - } - changed - } - HybridBitSet::Dense(dense) => self.intersect(dense), - } - } -} - -// hybrid REL hybrid -impl BitRelations> for HybridBitSet { - fn union(&mut self, other: &HybridBitSet) -> bool { - assert_eq!(self.domain_size(), other.domain_size()); - match self { - HybridBitSet::Sparse(_) => { - match other { - HybridBitSet::Sparse(other_sparse) => { - // Both sets are sparse. Add the elements in - // `other_sparse` to `self` one at a time. This - // may or may not cause `self` to be densified. - let mut changed = false; - for elem in other_sparse.iter() { - changed |= self.insert(*elem); - } - changed - } - - HybridBitSet::Dense(other_dense) => self.union(other_dense), - } - } - - HybridBitSet::Dense(self_dense) => self_dense.union(other), - } - } - - fn subtract(&mut self, other: &HybridBitSet) -> bool { - assert_eq!(self.domain_size(), other.domain_size()); - match self { - HybridBitSet::Sparse(self_sparse) => { - sequential_update(|elem| self_sparse.remove(elem), other.iter()) - } - HybridBitSet::Dense(self_dense) => self_dense.subtract(other), - } - } - - fn intersect(&mut self, other: &HybridBitSet) -> bool { - assert_eq!(self.domain_size(), other.domain_size()); - match self { - HybridBitSet::Sparse(self_sparse) => { - sparse_intersect(self_sparse, |elem| other.contains(*elem)) - } - HybridBitSet::Dense(self_dense) => match other { - HybridBitSet::Sparse(other_sparse) => { - let (updated, changed) = dense_sparse_intersect(self_dense, other_sparse); - *self = HybridBitSet::Sparse(updated); - changed - } - HybridBitSet::Dense(other_dense) => self_dense.intersect(other_dense), - }, - } - } -} - impl Clone for BitSet { fn clone(&self) -> Self { BitSet { domain_size: self.domain_size, words: self.words.clone(), marker: PhantomData } @@ -1340,286 +1106,6 @@ where false } -const SPARSE_MAX: usize = 8; - -/// A fixed-size bitset type with a sparse representation and a maximum of -/// `SPARSE_MAX` elements. The elements are stored as a sorted `ArrayVec` with -/// no duplicates. -/// -/// This type is used by `HybridBitSet`; do not use directly. -#[derive(Clone, Debug)] -pub struct SparseBitSet { - domain_size: usize, - elems: ArrayVec, -} - -impl SparseBitSet { - fn new_empty(domain_size: usize) -> Self { - SparseBitSet { domain_size, elems: ArrayVec::new() } - } - - fn len(&self) -> usize { - self.elems.len() - } - - fn is_empty(&self) -> bool { - self.elems.len() == 0 - } - - fn contains(&self, elem: T) -> bool { - assert!(elem.index() < self.domain_size); - self.elems.contains(&elem) - } - - fn insert(&mut self, elem: T) -> bool { - assert!(elem.index() < self.domain_size); - let changed = if let Some(i) = self.elems.iter().position(|&e| e.index() >= elem.index()) { - if self.elems[i] == elem { - // `elem` is already in the set. - false - } else { - // `elem` is smaller than one or more existing elements. - self.elems.insert(i, elem); - true - } - } else { - // `elem` is larger than all existing elements. - self.elems.push(elem); - true - }; - assert!(self.len() <= SPARSE_MAX); - changed - } - - fn remove(&mut self, elem: T) -> bool { - assert!(elem.index() < self.domain_size); - if let Some(i) = self.elems.iter().position(|&e| e == elem) { - self.elems.remove(i); - true - } else { - false - } - } - - fn to_dense(&self) -> BitSet { - let mut dense = BitSet::new_empty(self.domain_size); - for elem in self.elems.iter() { - dense.insert(*elem); - } - dense - } - - fn iter(&self) -> slice::Iter<'_, T> { - self.elems.iter() - } - - bit_relations_inherent_impls! {} -} - -impl SparseBitSet { - pub fn last_set_in(&self, range: impl RangeBounds) -> Option { - let mut last_leq = None; - for e in self.iter() { - if range.contains(e) { - last_leq = Some(*e); - } - } - last_leq - } -} - -/// A fixed-size bitset type with a hybrid representation: sparse when there -/// are up to a `SPARSE_MAX` elements in the set, but dense when there are more -/// than `SPARSE_MAX`. -/// -/// This type is especially efficient for sets that typically have a small -/// number of elements, but a large `domain_size`, and are cleared frequently. -/// -/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also -/// just be `usize`. -/// -/// All operations that involve an element will panic if the element is equal -/// to or greater than the domain size. All operations that involve two bitsets -/// will panic if the bitsets have differing domain sizes. -#[derive(Clone)] -pub enum HybridBitSet { - Sparse(SparseBitSet), - Dense(BitSet), -} - -impl fmt::Debug for HybridBitSet { - fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Sparse(b) => b.fmt(w), - Self::Dense(b) => b.fmt(w), - } - } -} - -impl HybridBitSet { - pub fn new_empty(domain_size: usize) -> Self { - HybridBitSet::Sparse(SparseBitSet::new_empty(domain_size)) - } - - pub fn domain_size(&self) -> usize { - match self { - HybridBitSet::Sparse(sparse) => sparse.domain_size, - HybridBitSet::Dense(dense) => dense.domain_size, - } - } - - pub fn clear(&mut self) { - let domain_size = self.domain_size(); - *self = HybridBitSet::new_empty(domain_size); - } - - pub fn contains(&self, elem: T) -> bool { - match self { - HybridBitSet::Sparse(sparse) => sparse.contains(elem), - HybridBitSet::Dense(dense) => dense.contains(elem), - } - } - - pub fn superset(&self, other: &HybridBitSet) -> bool { - match (self, other) { - (HybridBitSet::Dense(self_dense), HybridBitSet::Dense(other_dense)) => { - self_dense.superset(other_dense) - } - _ => { - assert!(self.domain_size() == other.domain_size()); - other.iter().all(|elem| self.contains(elem)) - } - } - } - - pub fn is_empty(&self) -> bool { - match self { - HybridBitSet::Sparse(sparse) => sparse.is_empty(), - HybridBitSet::Dense(dense) => dense.is_empty(), - } - } - - /// Returns the previous element present in the bitset from `elem`, - /// inclusively of elem. That is, will return `Some(elem)` if elem is in the - /// bitset. - pub fn last_set_in(&self, range: impl RangeBounds) -> Option - where - T: Ord, - { - match self { - HybridBitSet::Sparse(sparse) => sparse.last_set_in(range), - HybridBitSet::Dense(dense) => dense.last_set_in(range), - } - } - - pub fn insert(&mut self, elem: T) -> bool { - // No need to check `elem` against `self.domain_size` here because all - // the match cases check it, one way or another. - match self { - HybridBitSet::Sparse(sparse) if sparse.len() < SPARSE_MAX => { - // The set is sparse and has space for `elem`. - sparse.insert(elem) - } - HybridBitSet::Sparse(sparse) if sparse.contains(elem) => { - // The set is sparse and does not have space for `elem`, but - // that doesn't matter because `elem` is already present. - false - } - HybridBitSet::Sparse(sparse) => { - // The set is sparse and full. Convert to a dense set. - let mut dense = sparse.to_dense(); - let changed = dense.insert(elem); - assert!(changed); - *self = HybridBitSet::Dense(dense); - changed - } - HybridBitSet::Dense(dense) => dense.insert(elem), - } - } - - pub fn insert_range(&mut self, elems: impl RangeBounds) { - // No need to check `elem` against `self.domain_size` here because all - // the match cases check it, one way or another. - let start = match elems.start_bound().cloned() { - Bound::Included(start) => start.index(), - Bound::Excluded(start) => start.index() + 1, - Bound::Unbounded => 0, - }; - let end = match elems.end_bound().cloned() { - Bound::Included(end) => end.index() + 1, - Bound::Excluded(end) => end.index(), - Bound::Unbounded => self.domain_size() - 1, - }; - let Some(len) = end.checked_sub(start) else { return }; - match self { - HybridBitSet::Sparse(sparse) if sparse.len() + len < SPARSE_MAX => { - // The set is sparse and has space for `elems`. - for elem in start..end { - sparse.insert(T::new(elem)); - } - } - HybridBitSet::Sparse(sparse) => { - // The set is sparse and full. Convert to a dense set. - let mut dense = sparse.to_dense(); - dense.insert_range(elems); - *self = HybridBitSet::Dense(dense); - } - HybridBitSet::Dense(dense) => dense.insert_range(elems), - } - } - - pub fn insert_all(&mut self) { - let domain_size = self.domain_size(); - match self { - HybridBitSet::Sparse(_) => { - *self = HybridBitSet::Dense(BitSet::new_filled(domain_size)); - } - HybridBitSet::Dense(dense) => dense.insert_all(), - } - } - - pub fn remove(&mut self, elem: T) -> bool { - // Note: we currently don't bother going from Dense back to Sparse. - match self { - HybridBitSet::Sparse(sparse) => sparse.remove(elem), - HybridBitSet::Dense(dense) => dense.remove(elem), - } - } - - /// Converts to a dense set, consuming itself in the process. - pub fn to_dense(self) -> BitSet { - match self { - HybridBitSet::Sparse(sparse) => sparse.to_dense(), - HybridBitSet::Dense(dense) => dense, - } - } - - pub fn iter(&self) -> HybridIter<'_, T> { - match self { - HybridBitSet::Sparse(sparse) => HybridIter::Sparse(sparse.iter()), - HybridBitSet::Dense(dense) => HybridIter::Dense(dense.iter()), - } - } - - bit_relations_inherent_impls! {} -} - -pub enum HybridIter<'a, T: Idx> { - Sparse(slice::Iter<'a, T>), - Dense(BitIter<'a, T>), -} - -impl<'a, T: Idx> Iterator for HybridIter<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - match self { - HybridIter::Sparse(sparse) => sparse.next().copied(), - HybridIter::Dense(dense) => dense.next(), - } - } -} - /// A resizable bitset type with a dense representation. /// /// `T` is an index type, typically a newtyped `usize` wrapper, but it can also diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs index 21e681d63f69..3f9198ce37f1 100644 --- a/compiler/rustc_index/src/bit_set/tests.rs +++ b/compiler/rustc_index/src/bit_set/tests.rs @@ -75,96 +75,6 @@ fn union_two_sets() { assert!(set1.contains(64)); } -#[test] -fn hybrid_bitset() { - let mut sparse038: HybridBitSet = HybridBitSet::new_empty(256); - assert!(sparse038.is_empty()); - assert!(sparse038.insert(0)); - assert!(sparse038.insert(1)); - assert!(sparse038.insert(8)); - assert!(sparse038.insert(3)); - assert!(!sparse038.insert(3)); - assert!(sparse038.remove(1)); - assert!(!sparse038.is_empty()); - assert_eq!(sparse038.iter().collect::>(), [0, 3, 8]); - - for i in 0..256 { - if i == 0 || i == 3 || i == 8 { - assert!(sparse038.contains(i)); - } else { - assert!(!sparse038.contains(i)); - } - } - - let mut sparse01358 = sparse038.clone(); - assert!(sparse01358.insert(1)); - assert!(sparse01358.insert(5)); - assert_eq!(sparse01358.iter().collect::>(), [0, 1, 3, 5, 8]); - - let mut dense10 = HybridBitSet::new_empty(256); - for i in 0..10 { - assert!(dense10.insert(i)); - } - assert!(!dense10.is_empty()); - assert_eq!(dense10.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - - let mut dense256 = HybridBitSet::new_empty(256); - assert!(dense256.is_empty()); - dense256.insert_all(); - assert!(!dense256.is_empty()); - for i in 0..256 { - assert!(dense256.contains(i)); - } - - assert!(sparse038.superset(&sparse038)); // sparse + sparse (self) - assert!(sparse01358.superset(&sparse038)); // sparse + sparse - assert!(dense10.superset(&sparse038)); // dense + sparse - assert!(dense10.superset(&dense10)); // dense + dense (self) - assert!(dense256.superset(&dense10)); // dense + dense - - let mut hybrid = sparse038.clone(); - assert!(!sparse01358.union(&hybrid)); // no change - assert!(hybrid.union(&sparse01358)); - assert!(hybrid.superset(&sparse01358) && sparse01358.superset(&hybrid)); - assert!(!dense256.union(&dense10)); - - // dense / sparse where dense superset sparse - assert!(!dense10.clone().union(&sparse01358)); - assert!(sparse01358.clone().union(&dense10)); - assert!(dense10.clone().intersect(&sparse01358)); - assert!(!sparse01358.clone().intersect(&dense10)); - assert!(dense10.clone().subtract(&sparse01358)); - assert!(sparse01358.clone().subtract(&dense10)); - - // dense / sparse where sparse superset dense - let dense038 = sparse038.to_dense(); - assert!(!sparse01358.clone().union(&dense038)); - assert!(dense038.clone().union(&sparse01358)); - assert!(sparse01358.clone().intersect(&dense038)); - assert!(!dense038.clone().intersect(&sparse01358)); - assert!(sparse01358.clone().subtract(&dense038)); - assert!(dense038.clone().subtract(&sparse01358)); - - let mut dense = dense10.clone(); - assert!(dense.union(&dense256)); - assert!(dense.superset(&dense256) && dense256.superset(&dense)); - assert!(hybrid.union(&dense256)); - assert!(hybrid.superset(&dense256) && dense256.superset(&hybrid)); - - assert!(!dense10.clone().intersect(&dense256)); - assert!(dense256.clone().intersect(&dense10)); - assert!(dense10.clone().subtract(&dense256)); - assert!(dense256.clone().subtract(&dense10)); - - assert_eq!(dense256.iter().count(), 256); - let mut dense0 = dense256; - for i in 0..256 { - assert!(dense0.remove(i)); - } - assert!(!dense0.remove(0)); - assert!(dense0.is_empty()); -} - #[test] fn chunked_bitset() { let mut b0 = ChunkedBitSet::::new_empty(0); @@ -593,15 +503,15 @@ fn sparse_matrix_operations() { matrix.insert(2, 99); matrix.insert(4, 0); - let mut disjoint: HybridBitSet = HybridBitSet::new_empty(100); + let mut disjoint: ChunkedBitSet = ChunkedBitSet::new_empty(100); disjoint.insert(33); - let mut superset = HybridBitSet::new_empty(100); + let mut superset = ChunkedBitSet::new_empty(100); superset.insert(22); superset.insert(75); superset.insert(33); - let mut subset = HybridBitSet::new_empty(100); + let mut subset = ChunkedBitSet::new_empty(100); subset.insert(22); // SparseBitMatrix::remove @@ -746,90 +656,6 @@ fn dense_last_set_before() { } } -/// Merge dense hybrid set into empty sparse hybrid set. -#[bench] -fn union_hybrid_sparse_empty_to_dense(b: &mut Bencher) { - let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(256); - for i in 0..10 { - assert!(pre_dense.insert(i)); - } - let pre_sparse: HybridBitSet = HybridBitSet::new_empty(256); - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into full hybrid set with same indices. -#[bench] -fn union_hybrid_sparse_full_to_dense(b: &mut Bencher) { - let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(256); - for i in 0..10 { - assert!(pre_dense.insert(i)); - } - let mut pre_sparse: HybridBitSet = HybridBitSet::new_empty(256); - for i in 0..SPARSE_MAX { - assert!(pre_sparse.insert(i)); - } - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into full hybrid set with indices over the whole domain. -#[bench] -fn union_hybrid_sparse_domain_to_dense(b: &mut Bencher) { - let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX * 64); - for i in 0..10 { - assert!(pre_dense.insert(i)); - } - let mut pre_sparse: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX * 64); - for i in 0..SPARSE_MAX { - assert!(pre_sparse.insert(i * 64)); - } - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into empty hybrid set where the domain is very small. -#[bench] -fn union_hybrid_sparse_empty_small_domain(b: &mut Bencher) { - let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); - for i in 0..SPARSE_MAX { - assert!(pre_dense.insert(i)); - } - let pre_sparse: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - -/// Merge dense hybrid set into full hybrid set where the domain is very small. -#[bench] -fn union_hybrid_sparse_full_small_domain(b: &mut Bencher) { - let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); - for i in 0..SPARSE_MAX { - assert!(pre_dense.insert(i)); - } - let mut pre_sparse: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); - for i in 0..SPARSE_MAX { - assert!(pre_sparse.insert(i)); - } - b.iter(|| { - let dense = pre_dense.clone(); - let mut sparse = pre_sparse.clone(); - sparse.union(&dense); - }) -} - #[bench] fn bench_insert(b: &mut Bencher) { let mut bs = BitSet::new_filled(99999usize); From d626f6a2f4b8f44f661ba76d1b5b67c4d7826df9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 13:15:28 +1100 Subject: [PATCH 197/330] Remove last vestiges of `HybridBitSet`. This is in a test where the arrangement of backticks matters, but the exact words do not. --- tests/rustdoc-ui/unescaped_backticks.rs | 2 +- tests/rustdoc-ui/unescaped_backticks.stderr | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs index e813fba47179..8d6239296bf7 100644 --- a/tests/rustdoc-ui/unescaped_backticks.rs +++ b/tests/rustdoc-ui/unescaped_backticks.rs @@ -218,7 +218,7 @@ pub mod rustc { pub fn with_options() {} /// Subtracts `set from `row`. `set` can be either `BitSet` or - /// `HybridBitSet`. Has no effect if `row` does not exist. + /// `ChunkedBitSet`. Has no effect if `row` does not exist. //~^ ERROR unescaped backtick /// /// Returns true if the row was changed. diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index 67b87f353a15..1e2b3528d4af 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -124,10 +124,10 @@ LL | /// also avoids the need to import `OpenOptions\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:221:46 + --> $DIR/unescaped_backticks.rs:221:47 | -LL | /// `HybridBitSet`. Has no effect if `row` does not exist. - | ^ +LL | /// `ChunkedBitSet`. Has no effect if `row` does not exist. + | ^ | help: a previous inline code might be longer than expected | @@ -135,8 +135,8 @@ LL | /// Subtracts `set` from `row`. `set` can be either `BitSet` or | + help: if you meant to use a literal backtick, escape it | -LL | /// `HybridBitSet`. Has no effect if `row\` does not exist. - | + +LL | /// `ChunkedBitSet`. Has no effect if `row\` does not exist. + | + error: unescaped backtick --> $DIR/unescaped_backticks.rs:247:12 From 27c4c3a9785b9fd0278e1bb23a3ddc07e3e9de0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 29 Nov 2024 11:46:34 +0100 Subject: [PATCH 198/330] update link to "C++ Exceptions under the hood" blog The link was introduced in 0ec321f7b541fcbfbf20286beb497e6d9d3352b2. For the old link see https://web.archive.org/web/20170409223244/https://monoinfinito.wordpress.com/series/exception-handling-in-c/. The blog has migrated from WordPress to Blogger in 2021 and to GitHub pages in 2024. --- library/panic_unwind/src/gcc.rs | 2 +- library/std/src/sys/personality/gcc.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 925af6c08322..b2389078afd0 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -5,7 +5,7 @@ //! documents linked from it. //! These are also good reads: //! * -//! * +//! * //! * //! //! ## A brief summary diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index ad596ecff65d..88a25caeff0d 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -5,7 +5,7 @@ //! documents linked from it. //! These are also good reads: //! * -//! * +//! * //! * //! //! ## A brief summary From c76f1f0b9be9f5c5236effda44525a498e0cd905 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 21 Oct 2023 08:33:37 +0000 Subject: [PATCH 199/330] Doc comment custom MIR debuginfo. and add a test for the constant case --- library/core/src/intrinsics/mir.rs | 24 +++++++++++++++ .../custom/debuginfo.constant.built.after.mir | 10 +++++++ .../custom/debuginfo.numbered.built.after.mir | 2 +- tests/mir-opt/building/custom/debuginfo.rs | 29 +++++++++++++++++-- 4 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 tests/mir-opt/building/custom/debuginfo.constant.built.after.mir diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 6539964bc095..d9701225cceb 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -249,6 +249,30 @@ //! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`. //! - [`TailCall`] does not have a return destination or next block, so its syntax is just //! `TailCall(function(arg1, arg2, ...))`. +//! +//! #### Debuginfo +//! +//! - A debuginfo name can be given to a local using `debug my_name => contents;`. +//! For `contents`, we use the same syntax as operands, to support both places and constants. +//! +//! ```rust +//! #![allow(internal_features)] +//! #![feature(core_intrinsics, custom_mir)] +//! +//! use core::intrinsics::mir::*; +//! +//! #[custom_mir(dialect = "built")] +//! fn debuginfo(option: Option<&i32>) { +//! mir!( +//! debug option => option; +//! debug projection => *Field::<&i32>(Variant(option, 1), 0); +//! debug constant => 5_usize; +//! { +//! Return() +//! } +//! ) +//! } +//! ``` #![unstable( feature = "custom_mir", diff --git a/tests/mir-opt/building/custom/debuginfo.constant.built.after.mir b/tests/mir-opt/building/custom/debuginfo.constant.built.after.mir new file mode 100644 index 000000000000..00702b5b99c4 --- /dev/null +++ b/tests/mir-opt/building/custom/debuginfo.constant.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `constant` after built + +fn constant() -> () { + debug scalar => const 5_usize; + let mut _0: (); + + bb0: { + return; + } +} diff --git a/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir b/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir index d86392537181..fba611818ef6 100644 --- a/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir +++ b/tests/mir-opt/building/custom/debuginfo.numbered.built.after.mir @@ -2,7 +2,7 @@ fn numbered(_1: (u32, i32)) -> () { debug first => (_1.0: u32); - debug second => (_1.0: u32); + debug second => (_1.1: i32); let mut _0: (); bb0: { diff --git a/tests/mir-opt/building/custom/debuginfo.rs b/tests/mir-opt/building/custom/debuginfo.rs index 5ab83fd4214b..c4ea2162e0b0 100644 --- a/tests/mir-opt/building/custom/debuginfo.rs +++ b/tests/mir-opt/building/custom/debuginfo.rs @@ -1,4 +1,3 @@ -// skip-filecheck #![feature(custom_mir, core_intrinsics)] extern crate core; @@ -7,6 +6,8 @@ use core::intrinsics::mir::*; // EMIT_MIR debuginfo.pointee.built.after.mir #[custom_mir(dialect = "built")] fn pointee(opt: &mut Option) { + // CHECK-LABEL: fn pointee( + // CHECK: debug foo => (((*_1) as variant#1).0: i32); mir! { debug foo => Field::(Variant(*opt, 1), 0); { @@ -18,9 +19,12 @@ fn pointee(opt: &mut Option) { // EMIT_MIR debuginfo.numbered.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn numbered(i: (u32, i32)) { + // CHECK-LABEL: fn numbered( + // CHECK: debug first => (_1.0: u32); + // CHECK: debug second => (_1.1: i32); mir! { debug first => i.0; - debug second => i.0; + debug second => i.1; { Return() } @@ -34,6 +38,8 @@ struct S { // EMIT_MIR debuginfo.structured.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn structured(i: S) { + // CHECK-LABEL: fn structured( + // CHECK: debug x => (_1.0: f32); mir! { debug x => i.x; { @@ -45,6 +51,8 @@ fn structured(i: S) { // EMIT_MIR debuginfo.variant.built.after.mir #[custom_mir(dialect = "built")] fn variant(opt: Option) { + // CHECK-LABEL: fn variant( + // CHECK: debug inner => ((_1 as variant#1).0: i32); mir! { debug inner => Field::(Variant(opt, 1), 0); { @@ -56,6 +64,9 @@ fn variant(opt: Option) { // EMIT_MIR debuginfo.variant_deref.built.after.mir #[custom_mir(dialect = "built")] fn variant_deref(opt: Option<&i32>) { + // CHECK-LABEL: fn variant_deref( + // CHECK: debug pointer => ((_1 as variant#1).0: &i32); + // CHECK: debug deref => (*((_1 as variant#1).0: &i32)); mir! { debug pointer => Field::<&i32>(Variant(opt, 1), 0); debug deref => *Field::<&i32>(Variant(opt, 1), 0); @@ -65,10 +76,24 @@ fn variant_deref(opt: Option<&i32>) { } } +// EMIT_MIR debuginfo.constant.built.after.mir +#[custom_mir(dialect = "built")] +fn constant() { + // CHECK-LABEL: fn constant( + // CHECK: debug scalar => const 5_usize; + mir!( + debug scalar => 5_usize; + { + Return() + } + ) +} + fn main() { numbered((5, 6)); structured(S { x: 5. }); variant(Some(5)); variant_deref(Some(&5)); pointee(&mut Some(5)); + constant(); } From de94536553606a3b0c1e461751b0c431c3d642a4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 29 Nov 2024 12:44:01 +0100 Subject: [PATCH 200/330] check local cache even if global is usable we store overflow errors locally, even if we can otherwise use the global cache for this goal. --- .../src/traits/select/mod.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3b64a47181a6..f93791302f6e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1537,14 +1537,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Some(res) = tcx.selection_cache.get(&(infcx.typing_env(param_env), pred), tcx) { - Some(res) - } else { - debug_assert_eq!(infcx.selection_cache.get(&(param_env, pred), tcx), None); - None + return Some(res); + } else if cfg!(debug_assertions) { + match infcx.selection_cache.get(&(param_env, pred), tcx) { + None | Some(Err(Overflow(OverflowError::Canonical))) => {} + res => bug!("unexpected local cache result: {res:?}"), + } } - } else { - infcx.selection_cache.get(&(param_env, pred), tcx) } + + // Subtle: we need to check the local cache even if we're able to use the + // global cache as we don't cache overflow in the global cache but need to + // cache it as otherwise rustdoc hangs when compiling diesel. + infcx.selection_cache.get(&(param_env, pred), tcx) } /// Determines whether can we safely cache the result From 6e449e18addc5cd0c1fd7ad234a6f101c96d6865 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 29 Nov 2024 12:41:51 +0100 Subject: [PATCH 201/330] refine mir debuginfo docs --- library/core/src/intrinsics/mir.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index d9701225cceb..55dcf7cd47e9 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -252,8 +252,13 @@ //! //! #### Debuginfo //! -//! - A debuginfo name can be given to a local using `debug my_name => contents;`. -//! For `contents`, we use the same syntax as operands, to support both places and constants. +//! Debuginfo associates source code variable names (of variables that may not exist any more) with +//! MIR expressions that indicate where the value of that variable is stored. The syntax to do so +//! is: +//! ```text +//! debug source_var_name => expression; +//! ``` +//! Both places and constants are supported in the `expression`. //! //! ```rust //! #![allow(internal_features)] @@ -262,10 +267,14 @@ //! use core::intrinsics::mir::*; //! //! #[custom_mir(dialect = "built")] -//! fn debuginfo(option: Option<&i32>) { +//! fn debuginfo(arg: Option<&i32>) { //! mir!( -//! debug option => option; -//! debug projection => *Field::<&i32>(Variant(option, 1), 0); +//! // Debuginfo for a source variable `plain_local` that just duplicates `arg`. +//! debug plain_local => arg; +//! // Debuginfo for a source variable `projection` that can be computed by dereferencing +//! // a field of `arg`. +//! debug projection => *Field::<&i32>(Variant(arg, 1), 0); +//! // Debuginfo for a source variable `constant` that always holds the value `5`. //! debug constant => 5_usize; //! { //! Return() From 3f65114ffcbd880e20b07608945342c54bf7721b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 23 Nov 2024 13:24:57 +1100 Subject: [PATCH 202/330] coverage: Rename `CrateCoverageContext` to `CguCoverageContext` This context is stored in `CodegenCx`, which makes it per-CGU rather than per-crate. A single crate can have multiple CGUs. --- compiler/rustc_codegen_llvm/src/context.rs | 8 ++++---- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 841c110b3c8e..8218126ea29c 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -82,8 +82,8 @@ pub(crate) struct CodegenCx<'ll, 'tcx> { pub isize_ty: &'ll Type, - /// Extra codegen state needed when coverage instrumentation is enabled. - pub coverage_cx: Option>, + /// Extra per-CGU codegen state needed when coverage instrumentation is enabled. + pub coverage_cx: Option>, pub dbg_cx: Option>, eh_personality: Cell>, @@ -525,7 +525,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); let coverage_cx = - tcx.sess.instrument_coverage().then(coverageinfo::CrateCoverageContext::new); + tcx.sess.instrument_coverage().then(coverageinfo::CguCoverageContext::new); let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { let dctx = debuginfo::CodegenUnitDebugContext::new(llmod); @@ -576,7 +576,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// Extra state that is only available when coverage instrumentation is enabled. #[inline] #[track_caller] - pub(crate) fn coverage_cx(&self) -> &coverageinfo::CrateCoverageContext<'ll, 'tcx> { + pub(crate) fn coverage_cx(&self) -> &coverageinfo::CguCoverageContext<'ll, 'tcx> { self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled") } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index bf773cd2667a..d1af9bbe241d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -21,8 +21,8 @@ mod llvm_cov; pub(crate) mod map_data; mod mapgen; -/// A context object for maintaining all state needed by the coverageinfo module. -pub(crate) struct CrateCoverageContext<'ll, 'tcx> { +/// Extra per-CGU context/state needed for coverage instrumentation. +pub(crate) struct CguCoverageContext<'ll, 'tcx> { /// Coverage data for each instrumented function identified by DefId. pub(crate) function_coverage_map: RefCell, FunctionCoverageCollector<'tcx>>>, @@ -32,7 +32,7 @@ pub(crate) struct CrateCoverageContext<'ll, 'tcx> { covfun_section_name: OnceCell, } -impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { +impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> { pub(crate) fn new() -> Self { Self { function_coverage_map: Default::default(), From 58e122fef8f430888a3d91b67b7eede4bbd67dd0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 23 Nov 2024 14:21:33 +1100 Subject: [PATCH 203/330] coverage: Hoist and explain the check for `coverage_cx` --- .../src/coverageinfo/mod.rs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index d1af9bbe241d..12cd1876b67f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -143,6 +143,13 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let bx = self; + // Due to LocalCopy instantiation or MIR inlining, coverage statements + // can end up in a crate that isn't doing coverage instrumentation. + // When that happens, we currently just discard those statements, so + // the corresponding code will be undercounted. + // FIXME(Zalathar): Find a better solution for mixed-coverage builds. + let Some(coverage_cx) = &bx.cx.coverage_cx else { return }; + let Some(function_coverage_info) = bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref() else { @@ -150,12 +157,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { return; }; - // FIXME(#132395): Unwrapping `coverage_cx` here has led to ICEs in the - // wild, so keep this early-return until we understand why. - let mut coverage_map = match bx.coverage_cx { - Some(ref cx) => cx.function_coverage_map.borrow_mut(), - None => return, - }; + let mut coverage_map = coverage_cx.function_coverage_map.borrow_mut(); let func_coverage = coverage_map .entry(instance) .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info)); @@ -197,8 +199,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } CoverageKind::CondBitmapUpdate { index, decision_depth } => { drop(coverage_map); - let cond_bitmap = bx - .coverage_cx() + let cond_bitmap = coverage_cx .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for updating"); let cond_index = bx.const_i32(index as i32); @@ -206,9 +207,11 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { drop(coverage_map); - let cond_bitmap = bx.coverage_cx() - .try_get_mcdc_condition_bitmap(&instance, decision_depth) - .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); + let cond_bitmap = + coverage_cx.try_get_mcdc_condition_bitmap(&instance, decision_depth).expect( + "mcdc cond bitmap should have been allocated for merging \ + into the global bitmap", + ); assert!( bitmap_idx as usize <= function_coverage_info.mcdc_bitmap_bits, "bitmap index of the decision out of range" From 05d95a98414949bebda824d29b240230d8661082 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 25 Nov 2024 22:20:23 +1100 Subject: [PATCH 204/330] coverage: Allow niches in counter/expression IDs There is unlikely to be any practical difference between a counter limit of 2^32 and a counter limit of (2^32 - 256). --- compiler/rustc_middle/src/mir/coverage.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 11a4e7f89a7c..b7410ca5f189 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -28,7 +28,6 @@ rustc_index::newtype_index! { #[derive(HashStable)] #[encodable] #[orderable] - #[max = 0xFFFF_FFFF] #[debug_format = "CounterId({})"] pub struct CounterId {} } @@ -46,7 +45,6 @@ rustc_index::newtype_index! { #[derive(HashStable)] #[encodable] #[orderable] - #[max = 0xFFFF_FFFF] #[debug_format = "ExpressionId({})"] pub struct ExpressionId {} } From 121a17ccc34f3812142c6e1683b4e5a1ce256c1a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 25 Nov 2024 21:17:50 +1100 Subject: [PATCH 205/330] coverage: All counter terms in an unused function are zero This is currently handled automatically by the fact that codegen doesn't visit coverage statements in unused functions, but that will no longer be the case when unused IDs are identified by a separate query instead. --- compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs | 4 ++-- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index e3c0df278836..cdcd9fa970a7 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -117,7 +117,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { // (By construction, expressions can only refer to other expressions // that have lower IDs, so one pass is sufficient.) for (id, expression) in self.function_coverage_info.expressions.iter_enumerated() { - if !self.expressions_seen.contains(id) { + if !self.is_used || !self.expressions_seen.contains(id) { // If an expression was not seen, it must have been optimized away, // so any operand that refers to it can be replaced with zero. zero_expressions.insert(id); @@ -238,7 +238,7 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn is_zero_term(&self, term: CovTerm) -> bool { - is_zero_term(&self.counters_seen, &self.zero_expressions, term) + !self.is_used || is_zero_term(&self.counters_seen, &self.zero_expressions, term) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index b582dd967a70..059eace86912 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -535,8 +535,7 @@ fn add_unused_function_coverage<'tcx>( }), ); - // An unused function's mappings will automatically be rewritten to map to - // zero, because none of its counters/expressions are marked as seen. + // An unused function's mappings will all be rewritten to map to zero. let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info); cx.coverage_cx().function_coverage_map.borrow_mut().insert(instance, function_coverage); From 6fc0fe76e8495e638a8b69461b8001437b4f319a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 24 Nov 2024 18:26:05 +1100 Subject: [PATCH 206/330] coverage: Use a query to identify which counter/expression IDs are used --- .../src/coverageinfo/map_data.rs | 72 ++++--------------- .../src/coverageinfo/mapgen.rs | 6 +- .../src/coverageinfo/mod.rs | 28 ++++---- compiler/rustc_middle/src/mir/query.rs | 16 ++++- .../rustc_mir_transform/src/coverage/query.rs | 47 +++++++++--- tests/coverage/inline-dead.cov-map | 10 +-- tests/coverage/let_else_loop.cov-map | 6 +- 7 files changed, 93 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index cdcd9fa970a7..0752c718c706 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,12 +1,13 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::BitSet; +use rustc_middle::mir::CoverageIdsInfo; use rustc_middle::mir::coverage::{ CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op, SourceRegion, }; use rustc_middle::ty::Instance; -use tracing::{debug, instrument}; +use tracing::debug; use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; @@ -16,17 +17,8 @@ use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; pub(crate) struct FunctionCoverageCollector<'tcx> { /// Coverage info that was attached to this function by the instrumentor. function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, is_used: bool, - - /// Tracks which counters have been seen, so that we can identify mappings - /// to counters that were optimized out, and set them to zero. - counters_seen: BitSet, - /// Contains all expression IDs that have been seen in an `ExpressionUsed` - /// coverage statement, plus all expression IDs that aren't directly used - /// by any mappings (and therefore do not have expression-used statements). - /// After MIR traversal is finished, we can conclude that any IDs missing - /// from this set must have had their statements deleted by MIR opts. - expressions_seen: BitSet, } impl<'tcx> FunctionCoverageCollector<'tcx> { @@ -34,21 +26,24 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { pub(crate) fn new( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, ) -> Self { - Self::create(instance, function_coverage_info, true) + Self::create(instance, function_coverage_info, ids_info, true) } /// Creates a new set of coverage data for an unused (never called) function. pub(crate) fn unused( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, ) -> Self { - Self::create(instance, function_coverage_info, false) + Self::create(instance, function_coverage_info, ids_info, false) } fn create( instance: Instance<'tcx>, function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, is_used: bool, ) -> Self { let num_counters = function_coverage_info.num_counters; @@ -58,44 +53,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { num_counters={num_counters}, num_expressions={num_expressions}, is_used={is_used}" ); - // Create a filled set of expression IDs, so that expressions not - // directly used by mappings will be treated as "seen". - // (If they end up being unused, LLVM will delete them for us.) - let mut expressions_seen = BitSet::new_filled(num_expressions); - // For each expression ID that is directly used by one or more mappings, - // mark it as not-yet-seen. This indicates that we expect to see a - // corresponding `ExpressionUsed` statement during MIR traversal. - for mapping in function_coverage_info.mappings.iter() { - // Currently we only worry about ordinary code mappings. - // For branch and MC/DC mappings, expressions might not correspond - // to any particular point in the control-flow graph. - // (Keep this in sync with the injection of `ExpressionUsed` - // statements in the `InstrumentCoverage` MIR pass.) - if let MappingKind::Code(term) = mapping.kind - && let CovTerm::Expression(id) = term - { - expressions_seen.remove(id); - } - } - - Self { - function_coverage_info, - is_used, - counters_seen: BitSet::new_empty(num_counters), - expressions_seen, - } - } - - /// Marks a counter ID as having been seen in a counter-increment statement. - #[instrument(level = "debug", skip(self))] - pub(crate) fn mark_counter_id_seen(&mut self, id: CounterId) { - self.counters_seen.insert(id); - } - - /// Marks an expression ID as having been seen in an expression-used statement. - #[instrument(level = "debug", skip(self))] - pub(crate) fn mark_expression_id_seen(&mut self, id: ExpressionId) { - self.expressions_seen.insert(id); + Self { function_coverage_info, ids_info, is_used } } /// Identify expressions that will always have a value of zero, and note @@ -117,7 +75,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { // (By construction, expressions can only refer to other expressions // that have lower IDs, so one pass is sufficient.) for (id, expression) in self.function_coverage_info.expressions.iter_enumerated() { - if !self.is_used || !self.expressions_seen.contains(id) { + if !self.is_used || !self.ids_info.expressions_seen.contains(id) { // If an expression was not seen, it must have been optimized away, // so any operand that refers to it can be replaced with zero. zero_expressions.insert(id); @@ -146,7 +104,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { assert_operand_expression_is_lower(id); } - if is_zero_term(&self.counters_seen, &zero_expressions, *operand) { + if is_zero_term(&self.ids_info.counters_seen, &zero_expressions, *operand) { *operand = CovTerm::Zero; } }; @@ -172,17 +130,17 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { pub(crate) fn into_finished(self) -> FunctionCoverage<'tcx> { let zero_expressions = self.identify_zero_expressions(); - let FunctionCoverageCollector { function_coverage_info, is_used, counters_seen, .. } = self; + let FunctionCoverageCollector { function_coverage_info, ids_info, is_used, .. } = self; - FunctionCoverage { function_coverage_info, is_used, counters_seen, zero_expressions } + FunctionCoverage { function_coverage_info, ids_info, is_used, zero_expressions } } } pub(crate) struct FunctionCoverage<'tcx> { pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo, + ids_info: &'tcx CoverageIdsInfo, is_used: bool, - counters_seen: BitSet, zero_expressions: ZeroExpressions, } @@ -238,7 +196,7 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn is_zero_term(&self, term: CovTerm) -> bool { - !self.is_used || is_zero_term(&self.counters_seen, &self.zero_expressions, term) + !self.is_used || is_zero_term(&self.ids_info.counters_seen, &self.zero_expressions, term) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 059eace86912..8c24579fa7cc 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -536,7 +536,11 @@ fn add_unused_function_coverage<'tcx>( ); // An unused function's mappings will all be rewritten to map to zero. - let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info); + let function_coverage = FunctionCoverageCollector::unused( + instance, + function_coverage_info, + tcx.coverage_ids_info(instance.def), + ); cx.coverage_cx().function_coverage_map.borrow_mut().insert(instance, function_coverage); } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 12cd1876b67f..c2fcb33f98bc 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -157,27 +157,28 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { return; }; - let mut coverage_map = coverage_cx.function_coverage_map.borrow_mut(); - let func_coverage = coverage_map - .entry(instance) - .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info)); + // Mark the instance as used in this CGU, for coverage purposes. + // This includes functions that were not partitioned into this CGU, + // but were MIR-inlined into one of this CGU's functions. + coverage_cx.function_coverage_map.borrow_mut().entry(instance).or_insert_with(|| { + FunctionCoverageCollector::new( + instance, + function_coverage_info, + bx.tcx.coverage_ids_info(instance.def), + ) + }); match *kind { CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!( "marker statement {kind:?} should have been removed by CleanupPostBorrowck" ), CoverageKind::CounterIncrement { id } => { - func_coverage.mark_counter_id_seen(id); - // We need to explicitly drop the `RefMut` before calling into - // `instrprof_increment`, as that needs an exclusive borrow. - drop(coverage_map); - // The number of counters passed to `llvm.instrprof.increment` might // be smaller than the number originally inserted by the instrumentor, // if some high-numbered counters were removed by MIR optimizations. // If so, LLVM's profiler runtime will use fewer physical counters. let num_counters = - bx.tcx().coverage_ids_info(instance.def).max_counter_id.as_u32() + 1; + bx.tcx().coverage_ids_info(instance.def).num_counters_after_mir_opts(); assert!( num_counters as usize <= function_coverage_info.num_counters, "num_counters disagreement: query says {num_counters} but function info only has {}", @@ -194,11 +195,11 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { ); bx.instrprof_increment(fn_name, hash, num_counters, index); } - CoverageKind::ExpressionUsed { id } => { - func_coverage.mark_expression_id_seen(id); + CoverageKind::ExpressionUsed { id: _ } => { + // Expression-used statements are markers that are handled by + // `coverage_ids_info`, so there's nothing to codegen here. } CoverageKind::CondBitmapUpdate { index, decision_depth } => { - drop(coverage_map); let cond_bitmap = coverage_cx .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for updating"); @@ -206,7 +207,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { bx.mcdc_condbitmap_update(cond_index, cond_bitmap); } CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { - drop(coverage_map); let cond_bitmap = coverage_cx.try_get_mcdc_condition_bitmap(&instance, decision_depth).expect( "mcdc cond bitmap should have been allocated for merging \ diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 86abeb503823..ac48af88b209 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -8,7 +8,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; -use rustc_index::bit_set::BitMatrix; +use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; @@ -358,12 +358,22 @@ pub struct DestructuredConstant<'tcx> { /// Used by the `coverage_ids_info` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] pub struct CoverageIdsInfo { - /// Coverage codegen needs to know the highest counter ID that is ever + pub counters_seen: BitSet, + pub expressions_seen: BitSet, +} + +impl CoverageIdsInfo { + /// Coverage codegen needs to know how many coverage counters are ever /// incremented within a function, so that it can set the `num-counters` /// argument of the `llvm.instrprof.increment` intrinsic. /// /// This may be less than the highest counter ID emitted by the /// InstrumentCoverage MIR pass, if the highest-numbered counter increments /// were removed by MIR optimizations. - pub max_counter_id: mir::coverage::CounterId, + pub fn num_counters_after_mir_opts(&self) -> u32 { + // FIXME(Zalathar): Currently this treats an unused counter as "used" + // if its ID is less than that of the highest counter that really is + // used. Fixing this would require adding a renumbering step somewhere. + self.counters_seen.last_set_in(..).map_or(0, |max| max.as_u32() + 1) + } } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index df151f8cca35..0090f6f30404 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,6 +1,7 @@ use rustc_data_structures::captures::Captures; +use rustc_index::bit_set::BitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::coverage::{CounterId, CoverageKind}; +use rustc_middle::mir::coverage::{CovTerm, CoverageKind, MappingKind}; use rustc_middle::mir::{Body, CoverageIdsInfo, Statement, StatementKind}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::{self, TyCtxt}; @@ -86,15 +87,43 @@ fn coverage_ids_info<'tcx>( ) -> CoverageIdsInfo { let mir_body = tcx.instance_mir(instance_def); - let max_counter_id = all_coverage_in_mir_body(mir_body) - .filter_map(|kind| match *kind { - CoverageKind::CounterIncrement { id } => Some(id), - _ => None, - }) - .max() - .unwrap_or(CounterId::ZERO); + let Some(fn_cov_info) = mir_body.function_coverage_info.as_ref() else { + return CoverageIdsInfo { + counters_seen: BitSet::new_empty(0), + expressions_seen: BitSet::new_empty(0), + }; + }; - CoverageIdsInfo { max_counter_id } + let mut counters_seen = BitSet::new_empty(fn_cov_info.num_counters); + let mut expressions_seen = BitSet::new_filled(fn_cov_info.expressions.len()); + + // For each expression ID that is directly used by one or more mappings, + // mark it as not-yet-seen. This indicates that we expect to see a + // corresponding `ExpressionUsed` statement during MIR traversal. + for mapping in fn_cov_info.mappings.iter() { + // Currently we only worry about ordinary code mappings. + // For branch and MC/DC mappings, expressions might not correspond + // to any particular point in the control-flow graph. + // (Keep this in sync with the injection of `ExpressionUsed` + // statements in the `InstrumentCoverage` MIR pass.) + if let MappingKind::Code(CovTerm::Expression(id)) = mapping.kind { + expressions_seen.remove(id); + } + } + + for kind in all_coverage_in_mir_body(mir_body) { + match *kind { + CoverageKind::CounterIncrement { id } => { + counters_seen.insert(id); + } + CoverageKind::ExpressionUsed { id } => { + expressions_seen.insert(id); + } + _ => {} + } + } + + CoverageIdsInfo { counters_seen, expressions_seen } } fn all_coverage_in_mir_body<'a, 'tcx>( diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 411f16725bb0..5a20de3d4d44 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -8,18 +8,18 @@ Number of file 0 mappings: 1 Highest counter ID seen: (none) Function name: inline_dead::live:: -Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 0e, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 01, 01, 09, 05, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Zero +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 - Code(Counter(0)) at (prev + 14, 1) to (start + 1, 9) -- Code(Zero) at (prev + 2, 9) to (start + 0, 15) +- Code(Counter(1)) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) - = (c0 - Zero) + = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) -Highest counter ID seen: c0 +Highest counter ID seen: c1 Function name: inline_dead::main Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index 04451596eae4..7789114c2395 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -21,13 +21,13 @@ Number of file 0 mappings: 3 Highest counter ID seen: (none) Function name: let_else_loop::loopy -Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 00, 01, 1c, 00, 23, 05, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 09, 01, 1c, 00, 23, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 9, 1) to (start + 1, 20) -- Code(Zero) at (prev + 1, 28) to (start + 0, 35) +- Code(Counter(2)) at (prev + 1, 28) to (start + 0, 35) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) -Highest counter ID seen: c1 +Highest counter ID seen: c2 From 5b9a77a09dffec853d37fe7f722166b3996823d6 Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Fri, 29 Nov 2024 16:04:12 +0100 Subject: [PATCH 207/330] CI: split x86_64-mingw job --- src/bootstrap/mk/Makefile.in | 8 +++++--- src/ci/github-actions/jobs.yml | 16 +++++++++++++--- src/ci/shared.sh | 3 ++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 92c8f5dc452f..a1f38b9ac147 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -108,11 +108,13 @@ ci-msvc: ci-msvc-py ci-msvc-ps1 ## MingW native builders -# test both x and bootstrap entrypoints +# Set of tests that should represent half of the time of the test suite. +# Used to split tests across multiple CI runners. +# Test both x and bootstrap entrypoints. ci-mingw-x: - $(Q)$(CFG_SRC_DIR)/x test --stage 2 tidy + $(Q)$(CFG_SRC_DIR)/x test --stage 2 --skip=compiler --skip=src ci-mingw-bootstrap: - $(Q)$(BOOTSTRAP) test --stage 2 --skip tidy + $(Q)$(BOOTSTRAP) test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest ci-mingw: ci-mingw-x ci-mingw-bootstrap .PHONY: dist diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 2f59892acf6a..454c855c75d2 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -439,14 +439,24 @@ auto: NO_DOWNLOAD_CI_LLVM: 1 <<: *job-windows-8c - - image: x86_64-mingw + # x86_64-mingw is split into two jobs to run tests in parallel. + - image: x86_64-mingw-1 env: - SCRIPT: make ci-mingw + SCRIPT: make ci-mingw-x RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu # We are intentionally allowing an old toolchain on this builder (and that's # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 - <<: *job-windows-8c + <<: *job-windows + + - image: x86_64-mingw-2 + env: + SCRIPT: make ci-mingw-bootstrap + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + # We are intentionally allowing an old toolchain on this builder (and that's + # incompatible with LLVM downloads today). + NO_DOWNLOAD_CI_LLVM: 1 + <<: *job-windows - image: dist-x86_64-msvc env: diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 1e6a008a5de8..9fce68947f42 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -53,7 +53,8 @@ function isLinux { } function isKnownToBeMingwBuild { - isGitHubActions && [[ "${CI_JOB_NAME}" == *mingw ]] + # CI_JOB_NAME must end with "mingw" and optionally `-N` to be considered a MinGW build. + isGitHubActions && [[ "${CI_JOB_NAME}" =~ mingw(-[0-9]+)?$ ]] } function isCiBranch { From 3465ce57863c1e725a7e84537e4e3630c933e675 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 29 Nov 2024 17:23:21 +0100 Subject: [PATCH 208/330] fast reject: limit recursion depth --- compiler/rustc_type_ir/src/fast_reject.rs | 70 +++++++++++++++++------ 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 2c8e47bcbca2..81c8a7d4bfa4 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -214,27 +214,47 @@ impl DeepRejectCtxt { impl DeepRejectCtxt { + // Quite arbitrary. Large enough to only affect a very tiny amount of impls/crates + // and small enough to prevent hangs. + const STARTING_DEPTH: usize = 8; + pub fn args_may_unify( self, obligation_args: I::GenericArgs, impl_args: I::GenericArgs, ) -> bool { + self.args_may_unify_inner(obligation_args, impl_args, Self::STARTING_DEPTH) + } + + pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { + self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH) + } + + fn args_may_unify_inner( + self, + obligation_args: I::GenericArgs, + impl_args: I::GenericArgs, + depth: usize, + ) -> bool { + // No need to decrement the depth here as this function is only + // recursively reachable via `types_may_unify_inner` which already + // increments the depth for us. iter::zip(obligation_args.iter(), impl_args.iter()).all(|(obl, imp)| { match (obl.kind(), imp.kind()) { // We don't fast reject based on regions. (ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_)) => true, (ty::GenericArgKind::Type(obl), ty::GenericArgKind::Type(imp)) => { - self.types_may_unify(obl, imp) + self.types_may_unify_inner(obl, imp, depth) } (ty::GenericArgKind::Const(obl), ty::GenericArgKind::Const(imp)) => { - self.consts_may_unify(obl, imp) + self.consts_may_unify_inner(obl, imp) } _ => panic!("kind mismatch: {obl:?} {imp:?}"), } }) } - pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { + fn types_may_unify_inner(self, lhs: I::Ty, rhs: I::Ty, depth: usize) -> bool { match rhs.kind() { // Start by checking whether the `rhs` type may unify with // pretty much everything. Just return `true` in that case. @@ -273,18 +293,31 @@ impl {} }; + // The type system needs to support exponentially large types + // as long as they are self-similar. While most other folders + // use caching to handle them, this folder exists purely as a + // perf optimization and is incredibly hot. In pretty much all + // uses checking the cache is slower than simply recursing, so + // we instead just add an arbitrary depth cutoff. + // + // We only decrement the depth here as the match on `rhs` + // does not recurse. + let Some(depth) = depth.checked_sub(1) else { + return true; + }; + // For purely rigid types, use structural equivalence. match lhs.kind() { ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() { ty::Ref(_, rhs_ty, rhs_mutbl) => { - lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth) } _ => false, }, ty::Adt(lhs_def, lhs_args) => match rhs.kind() { ty::Adt(rhs_def, rhs_args) => { - lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) + lhs_def == rhs_def && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, @@ -326,27 +359,28 @@ impl { lhs.len() == rhs.len() && iter::zip(lhs.iter(), rhs.iter()) - .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) + .all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth)) } _ => false, }, ty::Array(lhs_ty, lhs_len) => match rhs.kind() { ty::Array(rhs_ty, rhs_len) => { - self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) + self.types_may_unify_inner(lhs_ty, rhs_ty, depth) + && self.consts_may_unify_inner(lhs_len, rhs_len) } _ => false, }, ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() { ty::RawPtr(rhs_ty, rhs_mutbl) => { - lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) + lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth) } _ => false, }, ty::Slice(lhs_ty) => { - matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify(lhs_ty, rhs_ty)) + matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth)) } ty::Dynamic(lhs_preds, ..) => { @@ -366,7 +400,7 @@ impl false, }, @@ -375,49 +409,51 @@ impl match rhs.kind() { ty::FnDef(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() { ty::Closure(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() { ty::CoroutineClosure(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() { ty::Coroutine(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() { ty::CoroutineWitness(rhs_def_id, rhs_args) => { - lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth) } _ => false, }, ty::Pat(lhs_ty, _) => { // FIXME(pattern_types): take pattern into account - matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify(lhs_ty, rhs_ty)) + matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth)) } ty::Error(..) => true, } } - pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool { + // Unlike `types_may_unify_inner`, this does not take a depth as + // we never recurse from this function. + fn consts_may_unify_inner(self, lhs: I::Const, rhs: I::Const) -> bool { match rhs.kind() { ty::ConstKind::Param(_) => { if INSTANTIATE_RHS_WITH_INFER { From fc9f727c7ce2e7ce3bedc0fe0ad390d20b72eb32 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 28 Nov 2024 10:12:01 +0100 Subject: [PATCH 209/330] Fix tests that rely on LLVM IR verification Pass -Z verify-llvm-ir to tests that rely on it, to make sure they pass regardless of the value of verify-llvm-ir in config.toml. Also remove the 109681.rs test, because it is a duplicat of common-linkage-non-zero-init.rs. --- tests/crashes/109681.rs | 9 --------- tests/crashes/34127.rs | 2 +- tests/ui/linkage-attr/common-linkage-non-zero-init.rs | 1 + 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 tests/crashes/109681.rs diff --git a/tests/crashes/109681.rs b/tests/crashes/109681.rs deleted file mode 100644 index 73ff10070943..000000000000 --- a/tests/crashes/109681.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #109681 - -#![crate_type="lib"] -#![feature(linkage)] - -#[linkage = "common"] -pub static TEST3: bool = true; - -fn main() {} diff --git a/tests/crashes/34127.rs b/tests/crashes/34127.rs index 88a2cf30ec5d..ea36b48ecba0 100644 --- a/tests/crashes/34127.rs +++ b/tests/crashes/34127.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -g -Copt-level=0 +//@ compile-flags: -g -Copt-level=0 -Z verify-llvm-ir //@ known-bug: #34127 //@ only-x86_64 diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs index a1fdd5a014c0..e5de08a7a28b 100644 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs +++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs @@ -2,6 +2,7 @@ //@ failure-status: 101 //@ known-bug: #109681 //@ ignore-wasm32 this appears to SIGABRT on wasm, not fail cleanly +//@ compile-flags: -Z verify-llvm-ir // This test verifies that we continue to hit the LLVM error for common linkage with non-zero // initializers, since it generates invalid LLVM IR. From e97e15dea55d61d68732bc030be1a44d8a51a1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 Nov 2024 18:31:37 +0000 Subject: [PATCH 210/330] Use rmake `diff` output in test --- .../foo.stderr | 34 +++++++++++++++++++ .../rmake.rs | 25 +++++++------- 2 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr new file mode 100644 index 000000000000..36379429530b --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo.stderr @@ -0,0 +1,34 @@ +error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied + --> foo-current.rs:13:19 + | +13 | check_trait::(); + | ^^^^^^^^^^^ the trait `Trait` is not implemented for `foo::Struct` + | +note: there are multiple different versions of crate `foo` in the dependency graph + --> foo-current.rs:7:1 + | +4 | extern crate foo; + | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate +5 | +6 | pub struct Struct; + | ----------------- this type implements the required trait +7 | pub trait Trait {} + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: foo-prev.rs:X:Y + | +4 | pub struct Struct; + | ----------------- this type doesn't implement the required trait +5 | pub trait Trait {} + | --------------- this is the found trait + = note: two types coming from two different versions of the same crate are different types even if they look the same + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `check_trait` + --> foo-current.rs:10:19 + | +10 | fn check_trait() {} + | ^^^^^ required by this bound in `check_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs index f52f3d791a71..57e0cab92f1e 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -7,26 +7,25 @@ // and traits of the different versions are mixed, we produce diagnostic output and not an ICE. // #133563 -use run_make_support::{rust_lib_name, rustc}; +use run_make_support::{diff, rust_lib_name, rustc}; fn main() { rustc().input("foo-prev.rs").run(); - rustc() + let out = rustc() .extra_filename("current") .metadata("current") .input("foo-current.rs") .extern_("foo", rust_lib_name("foo")) .run_fail() - .assert_stderr_contains(r#" -note: there are multiple different versions of crate `foo` in the dependency graph - --> foo-current.rs:7:1 - | -4 | extern crate foo; - | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate -5 | -6 | pub struct Struct; - | ----------------- this type implements the required trait -7 | pub trait Trait {} - | ^^^^^^^^^^^^^^^ this is the required trait"#); + .stderr_utf8(); + + // We don't remap the path of the `foo-prev` crate, so we remap it here. + let mut lines: Vec<_> = out.lines().collect(); + for line in &mut lines { + if line.starts_with(" ::: ") { + *line = " ::: foo-prev.rs:X:Y"; + } + } + diff().expected_file("foo.stderr").actual_text("(rustc)", &lines.join("\n")).run(); } From 998ff2f0cd2902e86178d35b01ba78fe4633f80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 29 Nov 2024 18:43:48 +0000 Subject: [PATCH 211/330] Move the `crate-loading` test to use `diff` output --- .../src/external_deps/rustc.rs | 6 + .../multiple-dep-versions.stderr | 127 ++++++++++++++++++ tests/run-make/crate-loading/rmake.rs | 95 +++---------- 3 files changed, 152 insertions(+), 76 deletions(-) create mode 100644 tests/run-make/crate-loading/multiple-dep-versions.stderr diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 494daeca9636..ffe10092cc28 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -227,6 +227,12 @@ impl Rustc { self } + /// Normalize the line number in the stderr output + pub fn ui_testing(&mut self) -> &mut Self { + self.cmd.arg(format!("-Zui-testing")); + self + } + /// Specify the target triple, or a path to a custom target json spec file. pub fn target>(&mut self, target: S) -> &mut Self { let target = target.as_ref(); diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr new file mode 100644 index 000000000000..5888aad8f37b --- /dev/null +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -0,0 +1,127 @@ +error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied + --> replaced + | +LL | do_something(Type); + | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` + | | + | required by a bound introduced by this call + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub struct Type(pub i32); + | --------------- this type implements the required trait +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | + ::: replaced + | +LL | pub struct Type; + | --------------- this type doesn't implement the required trait +LL | pub trait Trait { + | --------------- this is the found trait + = note: two types coming from two different versions of the same crate are different types even if they look the same + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `do_something` + --> replaced + | +LL | pub fn do_something(_: X) {} + | ^^^^^ required by this bound in `do_something` + +error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope + --> replaced + | +LL | Type.foo(); + | ^^^ method not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +LL | fn foo(&self); + | -------------- the method is available for `dep_2_reexport::Type` here + | + ::: replaced + | +LL | use dependency::{Trait, do_something}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the trait that was imported + +error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope + --> replaced + | +LL | Type::bar(); + | ^^^ function or associated item not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +LL | fn foo(&self); +LL | fn bar(); + | --------- the associated function is available for `dep_2_reexport::Type` here + | + ::: replaced + | +LL | use dependency::{Trait, do_something}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the trait that was imported + +error[E0277]: the trait bound `OtherType: Trait` is not satisfied + --> replaced + | +LL | do_something(OtherType); + | ------------ ^^^^^^^^^ the trait `Trait` is not implemented for `OtherType` + | | + | required by a bound introduced by this call + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | + ::: replaced + | +LL | pub struct OtherType; + | -------------------- this type doesn't implement the required trait + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the found trait + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `do_something` + --> replaced + | +LL | pub fn do_something(_: X) {} + | ^^^^^ required by this bound in `do_something` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 544bf9ab957a..6ad456e3e3e5 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -3,7 +3,7 @@ //@ ignore-wasm64 // ignore-tidy-linelength -use run_make_support::{rust_lib_name, rustc}; +use run_make_support::{diff, rust_lib_name, rustc}; fn main() { rustc().input("multiple-dep-versions-1.rs").run(); @@ -13,83 +13,26 @@ fn main() { .extern_("dependency", rust_lib_name("dependency2")) .run(); - rustc() + let out = rustc() .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) + .ui_testing() .run_fail() - .assert_stderr_contains(r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied - --> multiple-dep-versions.rs:7:18 - | -7 | do_something(Type); - | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` - | | - | required by a bound introduced by this call - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -3 | pub struct Type(pub i32); - | --------------- this type implements the required trait -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the required trait -"#) - .assert_stderr_contains(r#" -1 | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` -2 | extern crate dependency; - | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate"#) - .assert_stderr_contains(r#" -3 | pub struct Type; - | --------------- this type doesn't implement the required trait -4 | pub trait Trait { - | --------------- this is the found trait - = note: two types coming from two different versions of the same crate are different types even if they look the same - = help: you can use `cargo tree` to explore your dependency tree"#) - .assert_stderr_contains(r#"note: required by a bound in `do_something`"#) - .assert_stderr_contains(r#" -12 | pub fn do_something(_: X) {} - | ^^^^^ required by this bound in `do_something`"#) - .assert_stderr_contains(r#"error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope - --> multiple-dep-versions.rs:8:10 - | -8 | Type.foo(); - | ^^^ method not found in `Type` - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -5 | fn foo(&self); - | -------------- the method is available for `dep_2_reexport::Type` here - | - ::: multiple-dep-versions.rs:4:18 - | -4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | --------------- this is the trait that was imported"#) - .assert_stderr_contains(r#" -error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope - --> multiple-dep-versions.rs:9:11 - | -9 | Type::bar(); - | ^^^ function or associated item not found in `Type` - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -5 | fn foo(&self); -6 | fn bar(); - | --------- the associated function is available for `dep_2_reexport::Type` here - | - ::: multiple-dep-versions.rs:4:18 - | -4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) - .assert_stderr_contains( - r#" -6 | pub struct OtherType; - | -------------------- this type doesn't implement the required trait"#); + .stderr_utf8(); + + // We don't remap all the paths, so we remap it here. + let mut lines: Vec<_> = out.lines().collect(); + for line in &mut lines { + if line.starts_with(" --> ") { + *line = " --> replaced"; + } + if line.starts_with(" ::: ") { + *line = " ::: replaced"; + } + } + diff() + .expected_file("multiple-dep-versions.stderr") + .actual_text("(rustc)", &lines.join("\n")) + .run(); } From ce98bf3d798bf183d33d2e3fc2d07a94e86e006e Mon Sep 17 00:00:00 2001 From: Orion Gonzalez Date: Fri, 29 Nov 2024 11:15:15 +0100 Subject: [PATCH 212/330] simplify how the `hir_typeck_pass_to_variadic_function` diagnostic is created --- compiler/rustc_hir_typeck/messages.ftl | 1 - compiler/rustc_hir_typeck/src/errors.rs | 7 +--- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 11 +---- tests/ui/c-variadic/variadic-ffi-1.stderr | 42 ++++++++++++++++--- tests/ui/error-codes/E0617.stderr | 35 +++++++++++++--- 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 6001816ffbec..b27f7215ae4a 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -146,7 +146,6 @@ hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value in hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function .suggestion = cast the value to `{$cast_ty}` - .help = cast the value to `{$cast_ty}` .teach_help = certain types, like `{$ty}`, must be casted before passing them to a variadic function, because of arcane ABI rules dictated by the C standard hir_typeck_ptr_cast_add_auto_to_object = adding {$traits_len -> diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index fa27abd270ff..a2e008593077 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -789,11 +789,8 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> { pub span: Span, pub ty: Ty<'tcx>, pub cast_ty: &'a str, - #[suggestion(code = "{replace}", applicability = "machine-applicable")] - pub sugg_span: Option, - pub replace: String, - #[help] - pub help: bool, + #[suggestion(code = " as {cast_ty}", applicability = "machine-applicable", style = "verbose")] + pub sugg_span: Span, #[note(hir_typeck_teach_help)] pub(crate) teach: bool, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 63777f82f1ae..30c838b74af6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -440,20 +440,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, cast_ty: &str, ) { - let (sugg_span, replace, help) = - if let Ok(snippet) = sess.source_map().span_to_snippet(span) { - (Some(span), format!("{snippet} as {cast_ty}"), false) - } else { - (None, "".to_string(), true) - }; - sess.dcx().emit_err(errors::PassToVariadicFunction { span, ty, cast_ty, - help, - replace, - sugg_span, + sugg_span: span.shrink_to_hi(), teach: sess.teach(E0617), }); } diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr index 72d60a1439af..194710dfd218 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.stderr +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -62,37 +62,67 @@ error[E0617]: can't pass `f32` to variadic function --> $DIR/variadic-ffi-1.rs:28:19 | LL | foo(1, 2, 3f32); - | ^^^^ help: cast the value to `c_double`: `3f32 as c_double` + | ^^^^ + | +help: cast the value to `c_double` + | +LL | foo(1, 2, 3f32 as c_double); + | +++++++++++ error[E0617]: can't pass `bool` to variadic function --> $DIR/variadic-ffi-1.rs:29:19 | LL | foo(1, 2, true); - | ^^^^ help: cast the value to `c_int`: `true as c_int` + | ^^^^ + | +help: cast the value to `c_int` + | +LL | foo(1, 2, true as c_int); + | ++++++++ error[E0617]: can't pass `i8` to variadic function --> $DIR/variadic-ffi-1.rs:30:19 | LL | foo(1, 2, 1i8); - | ^^^ help: cast the value to `c_int`: `1i8 as c_int` + | ^^^ + | +help: cast the value to `c_int` + | +LL | foo(1, 2, 1i8 as c_int); + | ++++++++ error[E0617]: can't pass `u8` to variadic function --> $DIR/variadic-ffi-1.rs:31:19 | LL | foo(1, 2, 1u8); - | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint` + | ^^^ + | +help: cast the value to `c_uint` + | +LL | foo(1, 2, 1u8 as c_uint); + | +++++++++ error[E0617]: can't pass `i16` to variadic function --> $DIR/variadic-ffi-1.rs:32:19 | LL | foo(1, 2, 1i16); - | ^^^^ help: cast the value to `c_int`: `1i16 as c_int` + | ^^^^ + | +help: cast the value to `c_int` + | +LL | foo(1, 2, 1i16 as c_int); + | ++++++++ error[E0617]: can't pass `u16` to variadic function --> $DIR/variadic-ffi-1.rs:33:19 | LL | foo(1, 2, 1u16); - | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint` + | ^^^^ + | +help: cast the value to `c_uint` + | +LL | foo(1, 2, 1u16 as c_uint); + | +++++++++ error: aborting due to 11 previous errors diff --git a/tests/ui/error-codes/E0617.stderr b/tests/ui/error-codes/E0617.stderr index 7193463e0283..b2eee1299601 100644 --- a/tests/ui/error-codes/E0617.stderr +++ b/tests/ui/error-codes/E0617.stderr @@ -2,31 +2,56 @@ error[E0617]: can't pass `f32` to variadic function --> $DIR/E0617.rs:7:36 | LL | printf(::std::ptr::null(), 0f32); - | ^^^^ help: cast the value to `c_double`: `0f32 as c_double` + | ^^^^ + | +help: cast the value to `c_double` + | +LL | printf(::std::ptr::null(), 0f32 as c_double); + | +++++++++++ error[E0617]: can't pass `i8` to variadic function --> $DIR/E0617.rs:10:36 | LL | printf(::std::ptr::null(), 0i8); - | ^^^ help: cast the value to `c_int`: `0i8 as c_int` + | ^^^ + | +help: cast the value to `c_int` + | +LL | printf(::std::ptr::null(), 0i8 as c_int); + | ++++++++ error[E0617]: can't pass `i16` to variadic function --> $DIR/E0617.rs:13:36 | LL | printf(::std::ptr::null(), 0i16); - | ^^^^ help: cast the value to `c_int`: `0i16 as c_int` + | ^^^^ + | +help: cast the value to `c_int` + | +LL | printf(::std::ptr::null(), 0i16 as c_int); + | ++++++++ error[E0617]: can't pass `u8` to variadic function --> $DIR/E0617.rs:16:36 | LL | printf(::std::ptr::null(), 0u8); - | ^^^ help: cast the value to `c_uint`: `0u8 as c_uint` + | ^^^ + | +help: cast the value to `c_uint` + | +LL | printf(::std::ptr::null(), 0u8 as c_uint); + | +++++++++ error[E0617]: can't pass `u16` to variadic function --> $DIR/E0617.rs:19:36 | LL | printf(::std::ptr::null(), 0u16); - | ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint` + | ^^^^ + | +help: cast the value to `c_uint` + | +LL | printf(::std::ptr::null(), 0u16 as c_uint); + | +++++++++ error[E0617]: can't pass a function item to a variadic function --> $DIR/E0617.rs:22:36 From 5fa483cb1028fed1ab1b8a674238a7cac5a1a42a Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 29 Nov 2024 21:29:02 +0000 Subject: [PATCH 213/330] Cargo patch --- src/bootstrap/src/core/build_steps/test.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index dd967bca867d..9c4527066083 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -263,12 +263,16 @@ pub struct Cargo { host: TargetSelection, } +impl Cargo { + const CRATE_PATH: &str = "src/tools/cargo"; +} + impl Step for Cargo { type Output = (); const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/cargo") + run.path(Self::CRATE_PATH) } fn make_run(run: RunConfig<'_>) { @@ -286,7 +290,7 @@ impl Step for Cargo { Mode::ToolRustc, self.host, Kind::Test, - "src/tools/cargo", + Self::CRATE_PATH, SourceType::Submodule, &[], ); @@ -301,6 +305,9 @@ impl Step for Cargo { // those features won't be able to land. cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1"); cargo.env("PATH", path_for_cargo(builder, compiler)); + // Cargo's test suite requires configurations from its own `.cargo/config.toml`. + // Change to the directory so Cargo can read from it. + cargo.current_dir(builder.src.join(Self::CRATE_PATH)); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( From a9cb2d67092a088944eb46d88fc925071f6c65de Mon Sep 17 00:00:00 2001 From: David Tenty Date: Fri, 29 Nov 2024 16:40:13 -0500 Subject: [PATCH 214/330] Add a comment --- compiler/rustc_metadata/src/native_libs.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index fa1e274fda9e..1d85aef9dff2 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -54,6 +54,9 @@ pub fn walk_native_lib_search_dirs( // The targets here should be in sync with `copy_third_party_objects` in bootstrap. // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind // and sanitizers to self-contained directory, and stop adding this search path. + // FIXME: On AIX this also has the side-effect of making the list of library search paths + // non-empty, which is needed or the linker may decide to record the LIBPATH env, if + // defined, as the search path instead of appending the default search paths. if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" From 2ba7d68011bfcbfb8f5c75d60bd357c0ba0386aa Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 29 Nov 2024 18:41:03 -0500 Subject: [PATCH 215/330] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 4c39aaff6686..3908f64086a3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 4c39aaff66862cc0da52fe529aa1990bb8bb9a22 +Subproject commit 3908f64086a3d7b9af8d87b4da2bd100776c3e61 From c5abbb3f9f56958c1a5154b8dc75482aa3da7888 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 13:36:42 -0800 Subject: [PATCH 216/330] Eliminate rustc_ast_pretty's print_expr_maybe_paren --- .../rustc_ast_pretty/src/pprust/state/expr.rs | 118 +++++++++++++----- 1 file changed, 87 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 04ec135c4289..e9c49e9f682f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -58,10 +58,6 @@ impl<'a> State<'a> { self.pclose() } - fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8, fixup: FixupContext) { - self.print_expr_cond_paren(expr, expr.precedence() < prec, fixup); - } - /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in /// `if cond { ... }`. fn print_expr_as_cond(&mut self, expr: &ast::Expr) { @@ -237,7 +233,7 @@ impl<'a> State<'a> { // because the latter is valid syntax but with the incorrect meaning. // It's a match-expression followed by tuple-expression, not a function // call. - self.print_expr_maybe_paren(func, prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren(func, func.precedence() < prec, fixup.leftmost_subexpression()); self.print_call_post(args) } @@ -258,7 +254,11 @@ impl<'a> State<'a> { // boundaries, `$receiver.method()` can be parsed back as a statement // containing an expression if and only if `$receiver` can be parsed as // a statement containing an expression. - self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + receiver, + receiver.precedence() < parser::PREC_UNAMBIGUOUS, + fixup, + ); self.word("."); self.print_ident(segment.ident); @@ -306,17 +306,29 @@ impl<'a> State<'a> { _ => left_prec, }; - self.print_expr_maybe_paren(lhs, left_prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + lhs, + lhs.precedence() < left_prec, + fixup.leftmost_subexpression(), + ); self.space(); self.word_space(op.node.as_str()); - self.print_expr_maybe_paren(rhs, right_prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + rhs, + rhs.precedence() < right_prec, + fixup.subsequent_subexpression(), + ); } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) { self.word(op.as_str()); - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + expr, + expr.precedence() < parser::PREC_PREFIX, + fixup.subsequent_subexpression(), + ); } fn print_expr_addr_of( @@ -334,7 +346,11 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + expr, + expr.precedence() < parser::PREC_PREFIX, + fixup.subsequent_subexpression(), + ); } pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) { @@ -417,7 +433,11 @@ impl<'a> State<'a> { } ast::ExprKind::Cast(expr, ty) => { let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(expr, prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + expr, + expr.precedence() < prec, + fixup.leftmost_subexpression(), + ); self.space(); self.word_space("as"); self.print_type(ty); @@ -490,7 +510,11 @@ impl<'a> State<'a> { self.space(); } MatchKind::Postfix => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + expr, + expr.precedence() < parser::PREC_UNAMBIGUOUS, + fixup, + ); self.word_nbsp(".match"); } } @@ -550,33 +574,57 @@ impl<'a> State<'a> { self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Await(expr, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + expr, + expr.precedence() < parser::PREC_UNAMBIGUOUS, + fixup, + ); self.word(".await"); } ast::ExprKind::Assign(lhs, rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + lhs, + lhs.precedence() <= prec, + fixup.leftmost_subexpression(), + ); self.space(); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + rhs, + rhs.precedence() < prec, + fixup.subsequent_subexpression(), + ); } ast::ExprKind::AssignOp(op, lhs, rhs) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + lhs, + lhs.precedence() <= prec, + fixup.leftmost_subexpression(), + ); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + rhs, + rhs.precedence() < prec, + fixup.subsequent_subexpression(), + ); } ast::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren( + expr, + expr.precedence() < parser::PREC_UNAMBIGUOUS, + fixup, + ); self.word("."); self.print_ident(*ident); } ast::ExprKind::Index(expr, index, _) => { - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_UNAMBIGUOUS, + expr.precedence() < parser::PREC_UNAMBIGUOUS, fixup.leftmost_subexpression(), ); self.word("["); @@ -590,14 +638,22 @@ impl<'a> State<'a> { // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.) let fake_prec = AssocOp::LOr.precedence() as i8; if let Some(e) = start { - self.print_expr_maybe_paren(e, fake_prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren( + e, + e.precedence() < fake_prec, + fixup.leftmost_subexpression(), + ); } match limits { ast::RangeLimits::HalfOpen => self.word(".."), ast::RangeLimits::Closed => self.word("..="), } if let Some(e) = end { - self.print_expr_maybe_paren(e, fake_prec, fixup.subsequent_subexpression()); + self.print_expr_cond_paren( + e, + e.precedence() < fake_prec, + fixup.subsequent_subexpression(), + ); } } ast::ExprKind::Underscore => self.word("_"), @@ -632,9 +688,9 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + expr.precedence() < parser::PREC_JUMP, fixup.subsequent_subexpression(), ); } @@ -645,9 +701,9 @@ impl<'a> State<'a> { self.word("yeet"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + expr.precedence() < parser::PREC_JUMP, fixup.subsequent_subexpression(), ); } @@ -655,9 +711,9 @@ impl<'a> State<'a> { ast::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( result, - parser::PREC_JUMP, + result.precedence() < parser::PREC_JUMP, fixup.subsequent_subexpression(), ); } @@ -709,15 +765,15 @@ impl<'a> State<'a> { if let Some(expr) = e { self.space(); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + expr.precedence() < parser::PREC_JUMP, fixup.subsequent_subexpression(), ); } } ast::ExprKind::Try(e) => { - self.print_expr_maybe_paren(e, parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren(e, e.precedence() < parser::PREC_UNAMBIGUOUS, fixup); self.word("?") } ast::ExprKind::TryBlock(blk) => { From 94538031a3385336f72696ea0e1f2fecfe3aa114 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 13:39:32 -0800 Subject: [PATCH 217/330] Eliminate rustc_hir_pretty's print_expr_maybe_paren --- compiler/rustc_hir_pretty/src/lib.rs | 38 +++++++++++++--------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 64c6969d4b9c..5a5b39c694f8 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1010,10 +1010,6 @@ impl<'a> State<'a> { self.pclose() } - fn print_expr_maybe_paren(&mut self, expr: &hir::Expr<'_>, prec: i8) { - self.print_expr_cond_paren(expr, expr.precedence() < prec) - } - /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in /// `if cond { ... }`. fn print_expr_as_cond(&mut self, expr: &hir::Expr<'_>) { @@ -1141,7 +1137,7 @@ impl<'a> State<'a> { _ => parser::PREC_UNAMBIGUOUS, }; - self.print_expr_maybe_paren(func, prec); + self.print_expr_cond_paren(func, func.precedence() < prec); self.print_call_post(args) } @@ -1152,7 +1148,7 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(receiver, receiver.precedence() < parser::PREC_UNAMBIGUOUS); self.word("."); self.print_ident(segment.ident); @@ -1188,15 +1184,15 @@ impl<'a> State<'a> { _ => left_prec, }; - self.print_expr_maybe_paren(lhs, left_prec); + self.print_expr_cond_paren(lhs, lhs.precedence() < left_prec); self.space(); self.word_space(op.node.as_str()); - self.print_expr_maybe_paren(rhs, right_prec) + self.print_expr_cond_paren(rhs, rhs.precedence() < right_prec) } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { self.word(op.as_str()); - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX) } fn print_expr_addr_of( @@ -1213,7 +1209,7 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX) } fn print_literal(&mut self, lit: &hir::Lit) { @@ -1352,7 +1348,7 @@ impl<'a> State<'a> { } hir::ExprKind::Cast(expr, ty) => { let prec = AssocOp::As.precedence() as i8; - self.print_expr_maybe_paren(expr, prec); + self.print_expr_cond_paren(expr, expr.precedence() < prec); self.space(); self.word_space("as"); self.print_type(ty); @@ -1454,26 +1450,26 @@ impl<'a> State<'a> { } hir::ExprKind::Assign(lhs, rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1); + self.print_expr_cond_paren(lhs, lhs.precedence() <= prec); self.space(); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < prec); } hir::ExprKind::AssignOp(op, lhs, rhs) => { let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_maybe_paren(lhs, prec + 1); + self.print_expr_cond_paren(lhs, lhs.precedence() <= prec); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_maybe_paren(rhs, prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < prec); } hir::ExprKind::Field(expr, ident) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS); self.word("."); self.print_ident(ident); } hir::ExprKind::Index(expr, index, _) => { - self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS); self.word("["); self.print_expr(index); self.word("]"); @@ -1487,7 +1483,7 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); } } hir::ExprKind::Continue(destination) => { @@ -1501,13 +1497,13 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); } } hir::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_maybe_paren(result, parser::PREC_JUMP); + self.print_expr_cond_paren(result, result.precedence() < parser::PREC_JUMP); } hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); @@ -1532,7 +1528,7 @@ impl<'a> State<'a> { } hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_maybe_paren(expr, parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); } hir::ExprKind::Err(_) => { self.popen(); From 92a1a1de17212065963ca3f8edd0697e3f6519d4 Mon Sep 17 00:00:00 2001 From: Xiaoguang Wang Date: Sat, 30 Nov 2024 16:29:49 +0800 Subject: [PATCH 218/330] Remove unused code --- tests/run-make/thumb-none-qemu/rmake.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/run-make/thumb-none-qemu/rmake.rs b/tests/run-make/thumb-none-qemu/rmake.rs index a505bb013f9b..9d4b426f4a19 100644 --- a/tests/run-make/thumb-none-qemu/rmake.rs +++ b/tests/run-make/thumb-none-qemu/rmake.rs @@ -27,7 +27,6 @@ fn main() { std::env::set_current_dir(CRATE).unwrap(); let target_dir = path("target"); - let manifest_path = path("Cargo.toml"); // Debug cargo() From 23d9741be3bd6471689327ee4e58cd5d1967b760 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 09:52:20 +0100 Subject: [PATCH 219/330] move slice::swap_unchecked constness to slice_swap_unchecked feature gate --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index a24417dba8cc..ec04852d44b4 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -959,7 +959,7 @@ impl [T] { /// [`swap`]: slice::swap /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[unstable(feature = "slice_swap_unchecked", issue = "88539")] - #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + #[rustc_const_unstable(feature = "slice_swap_unchecked", issue = "88539")] pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { assert_unsafe_precondition!( check_library_ub, From 67a29ac73dfb8eec670d47c01123beb79b303af7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 10:06:58 +0100 Subject: [PATCH 220/330] bump hashbrown version --- library/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 197e0a8fedb8..36f779d8acbb 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "compiler_builtins", From 330ef743de814af56874c35fa7e4662ccc9f315a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Oct 2024 08:00:18 +0100 Subject: [PATCH 221/330] bootstrap: show diagnostics relative to rustc src dir --- src/bootstrap/bootstrap.py | 3 ++- src/bootstrap/src/core/builder/cargo.rs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d7ae0299dd69..762f4e653e91 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1029,7 +1029,8 @@ class RustBuild(object): raise Exception("no cargo executable found at `{}`".format( self.cargo())) args = [self.cargo(), "build", "--manifest-path", - os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] + os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"), + "-Zroot-dir="+self.rust_root] args.extend("--verbose" for _ in range(self.verbose)) if self.use_locked_deps: args.append("--locked") diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 0688a1d68928..dd138508bea6 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -703,6 +703,9 @@ impl Builder<'_> { cargo.arg("-j").arg(self.jobs().to_string()); + // Make cargo emit diagnostics relative to the rustc src dir. + cargo.arg(format!("-Zroot-dir={}", self.src.display())); + // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 // Force cargo to output binaries with disambiguating hashes in the name let mut metadata = if compiler.stage == 0 { From ede5f0111d21b52f3f821455512d5c5b13fe9e29 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 09:57:19 +0100 Subject: [PATCH 222/330] move swap_nonoverlapping constness to separate feature gate --- library/core/src/ptr/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6147e9f5e619..b6fc0caebd02 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1009,6 +1009,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[rustc_diagnostic_item = "ptr_swap"] +#[rustc_const_stable_indirect] pub const unsafe fn swap(x: *mut T, y: *mut T) { // Give ourselves some scratch space to work with. // We do not have to worry about drops: `MaybeUninit` does nothing when dropped. @@ -1069,7 +1070,7 @@ pub const unsafe fn swap(x: *mut T, y: *mut T) { /// ``` #[inline] #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] -#[rustc_const_unstable(feature = "const_swap", issue = "83163")] +#[rustc_const_unstable(feature = "const_swap_nonoverlapping", issue = "133668")] #[rustc_diagnostic_item = "ptr_swap_nonoverlapping"] pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { #[allow(unused)] @@ -1129,7 +1130,6 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { /// LLVM can vectorize this (at least it can for the power-of-two-sized types /// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. #[inline] -#[rustc_const_unstable(feature = "const_swap", issue = "83163")] const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, count: usize) { let x = x.cast::>(); let y = y.cast::>(); From 0dc94404ee1c529dcf0071f0ef84f64934e7f747 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 10:23:39 +0100 Subject: [PATCH 223/330] remove a whole bunch of unnecessary const feature gates --- library/alloc/src/lib.rs | 8 -------- library/alloc/tests/lib.rs | 2 -- library/core/src/lib.rs | 19 ------------------- library/core/tests/lib.rs | 1 - library/std/src/lib.rs | 2 -- 5 files changed, 32 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 108224b27fa8..84f4202c02a9 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -91,8 +91,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] -#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))] #![cfg_attr(test, feature(str_as_str))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -107,13 +105,8 @@ #![feature(box_uninit_write)] #![feature(clone_to_uninit)] #![feature(coerce_unsized)] -#![feature(const_align_of_val)] -#![feature(const_box)] #![feature(const_eval_select)] #![feature(const_heap)] -#![feature(const_maybe_uninit_write)] -#![feature(const_size_of_val)] -#![feature(const_vec_string_slice)] #![feature(core_intrinsics)] #![feature(deprecated_suggestion)] #![feature(deref_pure_trait)] @@ -170,7 +163,6 @@ #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] #![feature(const_precise_live_drops)] -#![feature(const_try)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(fundamental)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 02bbb40ef81d..bcab17e7b2dd 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -4,8 +4,6 @@ #![feature(assert_matches)] #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] -#![feature(const_heap)] -#![feature(const_try)] #![feature(core_intrinsics)] #![feature(extract_if)] #![feature(exact_size_is_empty)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1b9a9ea3ecff..ab9c33ee7547 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -109,23 +109,7 @@ // tidy-alphabetical-start #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(const_align_of_val)] -#![feature(const_align_of_val_raw)] -#![feature(const_alloc_layout)] -#![feature(const_black_box)] -#![feature(const_eq_ignore_ascii_case)] #![feature(const_eval_select)] -#![feature(const_heap)] -#![feature(const_nonnull_new)] -#![feature(const_ptr_sub_ptr)] -#![feature(const_raw_ptr_comparison)] -#![feature(const_size_of_val)] -#![feature(const_size_of_val_raw)] -#![feature(const_sockaddr_setters)] -#![feature(const_swap)] -#![feature(const_try)] -#![feature(const_type_id)] -#![feature(const_type_name)] #![feature(const_typed_swap)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] @@ -165,10 +149,7 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(cfg_ub_checks)] -#![feature(const_for)] -#![feature(const_is_char_boundary)] #![feature(const_precise_live_drops)] -#![feature(const_str_split_at)] #![feature(const_trait_impl)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 40129619ce50..20200cd2ba7a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -16,7 +16,6 @@ #![feature(const_align_of_val_raw)] #![feature(const_black_box)] #![feature(const_eval_select)] -#![feature(const_heap)] #![feature(const_nonnull_new)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 42f99c3b9711..ec1d58f181e5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -410,9 +410,7 @@ // // Only for const-ness: // tidy-alphabetical-start -#![feature(const_collections_with_hasher)] #![feature(io_const_error)] -#![feature(thread_local_internals)] // tidy-alphabetical-end // #![default_lib_allocator] From f5691baba63ac568239b480c1de4a168fb3b6675 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 30 Nov 2024 10:34:38 +0100 Subject: [PATCH 224/330] Revert "Auto merge of #133654 - weihanglo:update-cargo, r=weihanglo" This reverts commit 76f3ff605962d7046bc1537597ceed5e12325f54, reversing changes made to 1fc691e6ddc24506b5234d586a5c084eb767f1ad. The new pgo_works test fails when rust is built without profiling support, including in CI on x86_64-gnu-aux. --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 3908f64086a3..4c39aaff6686 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3908f64086a3d7b9af8d87b4da2bd100776c3e61 +Subproject commit 4c39aaff66862cc0da52fe529aa1990bb8bb9a22 From fd9019852e2e54f5b35b40c7c6b8af237dd405b2 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 30 Nov 2024 12:40:43 +0300 Subject: [PATCH 225/330] replace hard coded error id with `ErrorKind::DirectoryNotEmpty` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/clean.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index d857de96cce7..61cc9eeed555 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -203,10 +203,8 @@ fn rm_rf(path: &Path) { do_op(path, "remove dir", |p| match fs::remove_dir(p) { // Check for dir not empty on Windows - // FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized, - // match on `e.kind()` instead. #[cfg(windows)] - Err(e) if e.raw_os_error() == Some(145) => Ok(()), + Err(e) if e.kind() == ErrorKind::DirectoryNotEmpty => Ok(()), r => r, }); } From 2a05e5be4f09503e0d33123bbf2b4343872d1162 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 10:04:41 +0100 Subject: [PATCH 226/330] add test for bytewise ptr::swap of a pointer --- library/core/tests/lib.rs | 1 + library/core/tests/ptr.rs | 19 +++++++++++++++++++ tests/ui/consts/missing_span_in_backtrace.rs | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 40129619ce50..29de66852a42 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -18,6 +18,7 @@ #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_nonnull_new)] +#![feature(const_swap)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 91f8c977d088..7e9773f2fb95 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -897,6 +897,25 @@ fn test_const_copy() { }; } +#[test] +fn test_const_swap() { + const { + let mut ptr1 = &1; + let mut ptr2 = &666; + + // Swap ptr1 and ptr2, bytewise. `swap` does not take a count + // so the best we can do is use an array. + type T = [u8; mem::size_of::<&i32>()]; + unsafe { + ptr::swap(ptr::from_mut(&mut ptr1).cast::(), ptr::from_mut(&mut ptr2).cast::()); + } + + // Make sure they still work. + assert!(*ptr1 == 666); + assert!(*ptr2 == 1); + }; +} + #[test] fn test_null_array_as_slice() { let arr: *mut [u8; 4] = null_mut(); diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index ea457c96f153..703cc7fbf89b 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Z ui-testing=no -#![feature(const_swap)] +#![feature(const_swap_nonoverlapping)] use std::{ mem::{self, MaybeUninit}, ptr, From 9836196e3cca6661e752c3acd8bc207f181736ed Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 30 Nov 2024 01:59:17 -0800 Subject: [PATCH 227/330] Fix chaining `carrying_add`s Something about the MIR lowering for `||` ended up breaking this, but it's fixed by changing the code to use `|` instead. I also added an assembly test to ensure it *keeps* being `adc`. --- library/core/src/num/uint_macros.rs | 2 +- tests/assembly/x86_64-bigint-add.rs | 33 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/assembly/x86_64-bigint-add.rs diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 90b986f4998d..0ebd765b5490 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2354,7 +2354,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_add(rhs); let (c, d) = a.overflowing_add(carry as $SelfT); - (c, b || d) + (c, b | d) } /// Calculates `self` + `rhs` with a signed `rhs`. diff --git a/tests/assembly/x86_64-bigint-add.rs b/tests/assembly/x86_64-bigint-add.rs new file mode 100644 index 000000000000..4bcb9732c640 --- /dev/null +++ b/tests/assembly/x86_64-bigint-add.rs @@ -0,0 +1,33 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O -C target-cpu=x86-64-v4 +//@ compile-flags: -C llvm-args=-x86-asm-syntax=intel + +#![no_std] +#![feature(bigint_helper_methods)] + +// This checks that the `carrying_add` implementation successfully chains, to catch +// issues like + +// This forces the ABI to avoid the windows-vs-linux ABI differences. + +// CHECK-LABEL: bigint_chain_carrying_add: +#[no_mangle] +pub unsafe extern "sysv64" fn bigint_chain_carrying_add( + dest: *mut u64, + src1: *const u64, + src2: *const u64, + n: usize, + mut carry: bool, +) -> bool { + // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] + // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] + // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] + // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + for i in 0..n { + (*dest.add(i), carry) = u64::carrying_add(*src1.add(i), *src2.add(i), carry); + } + carry +} From c4cab8a15c9d5cd739ffa4db31c25ab02942a353 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 11:22:52 +0100 Subject: [PATCH 228/330] bless tests for changed library path --- tests/ui/extern/extern-types-field-offset.run.stderr | 2 +- tests/ui/extern/extern-types-size_of_val.align.run.stderr | 2 +- tests/ui/extern/extern-types-size_of_val.size.run.stderr | 2 +- tests/ui/panics/panic-in-cleanup.run.stderr | 2 +- tests/ui/panics/panic-in-ffi.run.stderr | 2 +- tests/ui/process/println-with-broken-pipe.run.stderr | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ui/extern/extern-types-field-offset.run.stderr b/tests/ui/extern/extern-types-field-offset.run.stderr index f14073989800..1b04b860db5a 100644 --- a/tests/ui/extern/extern-types-field-offset.run.stderr +++ b/tests/ui/extern/extern-types-field-offset.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `Opaque` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/extern/extern-types-size_of_val.align.run.stderr b/tests/ui/extern/extern-types-size_of_val.align.run.stderr index faad1aa13faf..20c4d8785e84 100644 --- a/tests/ui/extern/extern-types-size_of_val.align.run.stderr +++ b/tests/ui/extern/extern-types-size_of_val.align.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `A` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/extern/extern-types-size_of_val.size.run.stderr b/tests/ui/extern/extern-types-size_of_val.size.run.stderr index faad1aa13faf..20c4d8785e84 100644 --- a/tests/ui/extern/extern-types-size_of_val.size.run.stderr +++ b/tests/ui/extern/extern-types-size_of_val.size.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `A` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr index 3417d4bf1a30..e7def11b0e94 100644 --- a/tests/ui/panics/panic-in-cleanup.run.stderr +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -4,6 +4,6 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at $DIR/panic-in-cleanup.rs:16:9: BOOM stack backtrace: -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: panic in a destructor during cleanup thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr index 58f5187f0daf..fe8c2b04b91a 100644 --- a/tests/ui/panics/panic-in-ffi.run.stderr +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -2,7 +2,7 @@ thread 'main' panicked at $DIR/panic-in-ffi.rs:21:5: Test note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace Noisy Drop -thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. diff --git a/tests/ui/process/println-with-broken-pipe.run.stderr b/tests/ui/process/println-with-broken-pipe.run.stderr index f9d138a04241..a334c0ad2047 100644 --- a/tests/ui/process/println-with-broken-pipe.run.stderr +++ b/tests/ui/process/println-with-broken-pipe.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at std/src/io/stdio.rs:LL:CC: +thread 'main' panicked at library/std/src/io/stdio.rs:LL:CC: failed printing to stdout: Broken pipe (os error 32) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From 4ce2116aef0677c6f59890d9bd3acea890fa5cbb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 10:33:09 +0100 Subject: [PATCH 229/330] get rid of a bunch of unnecessary rustc_const_unstable --- library/alloc/src/collections/binary_heap/mod.rs | 1 - library/core/src/cell.rs | 1 - library/core/src/num/nonzero.rs | 1 - library/core/src/num/uint_macros.rs | 1 - library/core/src/ptr/const_ptr.rs | 3 --- library/core/src/ptr/mut_ptr.rs | 5 ----- library/core/src/ptr/unique.rs | 1 + library/core/src/slice/mod.rs | 2 -- 8 files changed, 1 insertion(+), 14 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 0bc65cdbc55a..5d3997e14e3e 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -486,7 +486,6 @@ impl BinaryHeap { /// heap.push(4); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_binary_heap_new_in", issue = "125961")] #[must_use] pub const fn new_in(alloc: A) -> BinaryHeap { BinaryHeap { data: Vec::new_in(alloc) } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index c55397903277..cfa4c1fb5647 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -713,7 +713,6 @@ impl Cell<[T; N]> { /// let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); /// ``` #[unstable(feature = "as_array_of_cells", issue = "88248")] - #[rustc_const_unstable(feature = "as_array_of_cells", issue = "88248")] pub const fn as_array_of_cells(&self) -> &[Cell; N] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T; N]> as *const [Cell; N]) } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index dba64d5dc8e3..03f8d462d4d7 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -614,7 +614,6 @@ macro_rules! nonzero_integer { /// ``` /// #[unstable(feature = "non_zero_count_ones", issue = "120287")] - #[rustc_const_unstable(feature = "non_zero_count_ones", issue = "120287")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 90b986f4998d..61083b6783b2 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3162,7 +3162,6 @@ macro_rules! uint_impl { #[inline] #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behavior")] - #[rustc_const_unstable(feature = "wrapping_next_power_of_two", issue = "32463")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn wrapping_next_power_of_two(self) -> Self { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 6f6815f49cd2..f100adecbbb7 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -346,7 +346,6 @@ impl *const T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, @@ -1528,7 +1527,6 @@ impl *const [T] { /// /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. #[unstable(feature = "slice_as_array", issue = "133508")] - #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] #[inline] #[must_use] pub const fn as_array(self) -> Option<*const [T; N]> { @@ -1608,7 +1606,6 @@ impl *const [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 678c6029158b..6d0361b8c63f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -342,7 +342,6 @@ impl *mut T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, @@ -676,7 +675,6 @@ impl *mut T { /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> where T: Sized, @@ -1762,7 +1760,6 @@ impl *mut [T] { /// /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. #[unstable(feature = "slice_as_array", issue = "133508")] - #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] #[inline] #[must_use] pub const fn as_mut_array(self) -> Option<*mut [T; N]> { @@ -1963,7 +1960,6 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None @@ -2015,7 +2011,6 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { if self.is_null() { None diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index a796820a7e46..ebdc918a729c 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -92,6 +92,7 @@ impl Unique { /// Creates a new `Unique` if `ptr` is non-null. #[inline] + // rustc_const_unstable attribute can be removed when `const_nonnull_new` is stable #[rustc_const_unstable(feature = "ptr_internals", issue = "none")] pub const fn new(ptr: *mut T) -> Option { if let Some(pointer) = NonNull::new(ptr) { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index a24417dba8cc..c6aa2e580f6e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -859,7 +859,6 @@ impl [T] { /// /// If `N` is not exactly equal to slice's the length of `self`, then this method returns `None`. #[unstable(feature = "slice_as_array", issue = "133508")] - #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] #[inline] #[must_use] pub const fn as_array(&self) -> Option<&[T; N]> { @@ -878,7 +877,6 @@ impl [T] { /// /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. #[unstable(feature = "slice_as_array", issue = "133508")] - #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] #[inline] #[must_use] pub const fn as_mut_array(&mut self) -> Option<&mut [T; N]> { From 9182aa0bf7296fa3d024fbf1ac5257ef09dae262 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 10:35:09 +0100 Subject: [PATCH 230/330] rustc_allow_const_fn_unstable is not used in proc_macro --- library/proc_macro/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 15770248b310..4aa47ce4e4f5 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -22,7 +22,6 @@ // This library is copied into rust-analyzer to allow loading rustc compiled proc macros. // Please avoid unstable features where possible to minimize the amount of changes necessary // to make it compile with rust-analyzer on stable. -#![feature(rustc_allow_const_fn_unstable)] #![feature(staged_api)] #![feature(allow_internal_unstable)] #![feature(decl_macro)] From 43ae473520078e2f006a563b8dbba70c79539f6f Mon Sep 17 00:00:00 2001 From: Steve Lau Date: Sat, 30 Nov 2024 19:04:58 +0800 Subject: [PATCH 231/330] fix: hurd build, stat64.st_fsid was renamed to st_dev --- library/Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- library/std/src/os/hurd/fs.rs | 2 +- library/std/src/sys/pal/unix/os.rs | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 55851daaf2a8..a470dfaed0f5 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index c1ab70b714a4..94eb0c6eea76 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -34,7 +34,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.162", default-features = false, features = [ +libc = { version = "0.2.167", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } diff --git a/library/std/src/os/hurd/fs.rs b/library/std/src/os/hurd/fs.rs index 00ff1560f31d..e3087fa8af1c 100644 --- a/library/std/src/os/hurd/fs.rs +++ b/library/std/src/os/hurd/fs.rs @@ -298,7 +298,7 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for Metadata { fn st_dev(&self) -> u64 { - self.as_inner().as_inner().st_fsid as u64 + self.as_inner().as_inner().st_dev as u64 } fn st_ino(&self) -> u64 { self.as_inner().as_inner().st_ino as u64 diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f207131ddf33..794d484528da 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -428,11 +428,13 @@ pub fn current_exe() -> io::Result { pub fn current_exe() -> io::Result { unsafe { let mut sz: u32 = 0; + #[expect(deprecated)] libc::_NSGetExecutablePath(ptr::null_mut(), &mut sz); if sz == 0 { return Err(io::Error::last_os_error()); } let mut v: Vec = Vec::with_capacity(sz as usize); + #[expect(deprecated)] let err = libc::_NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz); if err != 0 { return Err(io::Error::last_os_error()); From 97b84e40cb4f002b77ba16cb2cd55a9ddb7928a8 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 30 Nov 2024 15:07:06 +0100 Subject: [PATCH 232/330] add tests for niches in pointers --- tests/ui/enum-discriminant/ptr_niche.rs | 38 +++++++++++++++++++++++++ tests/ui/structs-enums/type-sizes.rs | 7 +++++ 2 files changed, 45 insertions(+) create mode 100644 tests/ui/enum-discriminant/ptr_niche.rs diff --git a/tests/ui/enum-discriminant/ptr_niche.rs b/tests/ui/enum-discriminant/ptr_niche.rs new file mode 100644 index 000000000000..32df08bce634 --- /dev/null +++ b/tests/ui/enum-discriminant/ptr_niche.rs @@ -0,0 +1,38 @@ +//@ run-pass +//! Check that we can codegen setting and getting discriminants, including non-null niches, +//! for enums with a pointer-like ABI. This used to crash llvm. + +#![feature(rustc_attrs)] +use std::{ptr, mem}; + + +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_layout_scalar_valid_range_end(100)] +#[derive(Copy, Clone)] +struct PointerWithRange(#[allow(dead_code)] *const u8); + + +fn main() { + let val = unsafe { PointerWithRange(ptr::without_provenance(90)) }; + + let ptr = Some(val); + assert!(ptr.is_some()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert_eq!(raw, 90); + + let ptr = Some(Some(val)); + assert!(ptr.is_some()); + assert!(ptr.unwrap().is_some()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert_eq!(raw, 90); + + let ptr: Option = None; + assert!(ptr.is_none()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert!(!(1..=100).contains(&raw)); + + let ptr: Option> = None; + assert!(ptr.is_none()); + let raw = unsafe { mem::transmute::<_, usize>(ptr) }; + assert!(!(1..=100).contains(&raw)); +} diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs index 1961f10bd0aa..a8fadcc1d1ec 100644 --- a/tests/ui/structs-enums/type-sizes.rs +++ b/tests/ui/structs-enums/type-sizes.rs @@ -5,6 +5,7 @@ #![allow(dead_code)] #![feature(never_type)] #![feature(pointer_is_aligned_to)] +#![feature(rustc_attrs)] use std::mem::size_of; use std::num::NonZero; @@ -237,6 +238,10 @@ struct VecDummy { len: usize, } +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_layout_scalar_valid_range_end(100)] +struct PointerWithRange(#[allow(dead_code)] *const u8); + pub fn main() { assert_eq!(size_of::(), 1 as usize); assert_eq!(size_of::(), 4 as usize); @@ -354,4 +359,6 @@ pub fn main() { assert!(ptr::from_ref(&v.a).addr() > ptr::from_ref(&v.b).addr()); + assert_eq!(size_of::>(), size_of::()); + assert_eq!(size_of::>>(), size_of::()); } From 69c03262295ab8542aec037ca284cc053ec24047 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 30 Nov 2024 16:15:47 +0100 Subject: [PATCH 233/330] Stabilize `ptr::fn_addr_eq` --- library/core/src/ptr/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 805edddfe631..671fca027ced 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2111,7 +2111,6 @@ pub fn addr_eq(p: *const T, q: *const U) -> bool { /// when compiled with optimization: /// /// ``` -/// # #![feature(ptr_fn_addr_eq)] /// let f: fn(i32) -> i32 = |x| x; /// let g: fn(i32) -> i32 = |x| x + 0; // different closure, different body /// let h: fn(u32) -> u32 = |x| x + 0; // different signature too @@ -2136,7 +2135,6 @@ pub fn addr_eq(p: *const T, q: *const U) -> bool { /// # Examples /// /// ``` -/// #![feature(ptr_fn_addr_eq)] /// use std::ptr; /// /// fn a() { println!("a"); } @@ -2145,7 +2143,7 @@ pub fn addr_eq(p: *const T, q: *const U) -> bool { /// ``` /// /// [subtype]: https://doc.rust-lang.org/reference/subtyping.html -#[unstable(feature = "ptr_fn_addr_eq", issue = "129322")] +#[stable(feature = "ptr_fn_addr_eq", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[must_use = "function pointer comparison produces a value"] pub fn fn_addr_eq(f: T, g: U) -> bool { From 8b2ff49ff9dd20ee417907c2e96daa9f0cd8e7c4 Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 30 Nov 2024 16:22:56 +0100 Subject: [PATCH 234/330] std: clarify comments about initialization --- library/std/src/sys/pal/unix/sync/condvar.rs | 12 ++++++------ library/std/src/sys/pal/unix/sync/mutex.rs | 8 +++++--- library/std/src/sys/sync/condvar/pthread.rs | 2 +- library/std/src/sys/sync/mutex/pthread.rs | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs index 13eeba9c8807..73631053e9f4 100644 --- a/library/std/src/sys/pal/unix/sync/condvar.rs +++ b/library/std/src/sys/pal/unix/sync/condvar.rs @@ -23,7 +23,7 @@ impl Condvar { } /// # Safety - /// `init` must have been called. + /// `init` must have been called on this instance. #[inline] pub unsafe fn notify_one(self: Pin<&Self>) { let r = unsafe { libc::pthread_cond_signal(self.raw()) }; @@ -31,7 +31,7 @@ impl Condvar { } /// # Safety - /// `init` must have been called. + /// `init` must have been called on this instance. #[inline] pub unsafe fn notify_all(self: Pin<&Self>) { let r = unsafe { libc::pthread_cond_broadcast(self.raw()) }; @@ -39,7 +39,7 @@ impl Condvar { } /// # Safety - /// * `init` must have been called. + /// * `init` must have been called on this instance. /// * `mutex` must be locked by the current thread. /// * This condition variable may only be used with the same mutex. #[inline] @@ -49,7 +49,7 @@ impl Condvar { } /// # Safety - /// * `init` must have been called. + /// * `init` must have been called on this instance. /// * `mutex` must be locked by the current thread. /// * This condition variable may only be used with the same mutex. pub unsafe fn wait_timeout(&self, mutex: Pin<&Mutex>, dur: Duration) -> bool { @@ -95,7 +95,7 @@ impl Condvar { const CLOCK: libc::clockid_t = libc::CLOCK_MONOTONIC; /// # Safety - /// May only be called once. + /// May only be called once per instance of `Self`. pub unsafe fn init(self: Pin<&mut Self>) { use crate::mem::MaybeUninit; @@ -137,7 +137,7 @@ impl Condvar { const CLOCK: libc::clockid_t = libc::CLOCK_REALTIME; /// # Safety - /// May only be called once. + /// May only be called once per instance of `Self`. pub unsafe fn init(self: Pin<&mut Self>) { if cfg!(any(target_os = "espidf", target_os = "horizon", target_os = "teeos")) { // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet diff --git a/library/std/src/sys/pal/unix/sync/mutex.rs b/library/std/src/sys/pal/unix/sync/mutex.rs index 8ffd375bf91b..8ff6c3d3d15d 100644 --- a/library/std/src/sys/pal/unix/sync/mutex.rs +++ b/library/std/src/sys/pal/unix/sync/mutex.rs @@ -18,7 +18,7 @@ impl Mutex { } /// # Safety - /// Must only be called once. + /// May only be called once per instance of `Self`. pub unsafe fn init(self: Pin<&mut Self>) { // Issue #33770 // @@ -58,7 +58,8 @@ impl Mutex { } /// # Safety - /// * If `init` was not called, reentrant locking causes undefined behaviour. + /// * If `init` was not called on this instance, reentrant locking causes + /// undefined behaviour. /// * Destroying a locked mutex causes undefined behaviour. pub unsafe fn lock(self: Pin<&Self>) { #[cold] @@ -82,7 +83,8 @@ impl Mutex { } /// # Safety - /// * If `init` was not called, reentrant locking causes undefined behaviour. + /// * If `init` was not called on this instance, reentrant locking causes + /// undefined behaviour. /// * Destroying a locked mutex causes undefined behaviour. pub unsafe fn try_lock(self: Pin<&Self>) -> bool { unsafe { libc::pthread_mutex_trylock(self.raw()) == 0 } diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs index 4d2f9c0aaba4..5bb7431eecf0 100644 --- a/library/std/src/sys/sync/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -22,7 +22,7 @@ impl Condvar { fn get(&self) -> Pin<&pal::Condvar> { self.cvar.get_or_init(|| { let mut cvar = Box::pin(pal::Condvar::new()); - // SAFETY: we only call `init` once, namely here. + // SAFETY: we only call `init` once per `pal::Condvar`, namely here. unsafe { cvar.as_mut().init() }; cvar }) diff --git a/library/std/src/sys/sync/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs index 5719bb10f7f9..75b4b9c6dad9 100644 --- a/library/std/src/sys/sync/mutex/pthread.rs +++ b/library/std/src/sys/sync/mutex/pthread.rs @@ -21,7 +21,7 @@ impl Mutex { // This is sound however, as it cannot have been locked. self.pal.get_or_init(|| { let mut pal = Box::pin(pal::Mutex::new()); - // SAFETY: we only call `init` once, namely here. + // SAFETY: we only call `init` once per `pal::Mutex`, namely here. unsafe { pal.as_mut().init() }; pal }) From a3623f20ae18996f31cc4a5a431d8afaa382247e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 04:48:01 +0000 Subject: [PATCH 235/330] Make compare_impl_item into a query --- .../rustc_hir_analysis/src/check/check.rs | 18 +---- .../src/check/compare_impl_item.rs | 72 +++++++++++-------- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 11 +-- compiler/rustc_ty_utils/src/instance.rs | 12 ++-- tests/crashes/119701.rs | 21 ------ tests/crashes/121127.rs | 23 ------ tests/crashes/121411.rs | 13 ---- tests/crashes/129075.rs | 16 ----- tests/crashes/129127.rs | 21 ------ tests/crashes/129214.rs | 30 -------- tests/crashes/131294-2.rs | 25 ------- tests/crashes/131294.rs | 16 ----- .../const-generics/issues/issue-83765.stderr | 8 +-- .../const-traits/eval-bad-signature.rs} | 3 +- .../const-traits/eval-bad-signature.stderr | 21 ++++++ 16 files changed, 84 insertions(+), 228 deletions(-) delete mode 100644 tests/crashes/119701.rs delete mode 100644 tests/crashes/121127.rs delete mode 100644 tests/crashes/121411.rs delete mode 100644 tests/crashes/129075.rs delete mode 100644 tests/crashes/129127.rs delete mode 100644 tests/crashes/129214.rs delete mode 100644 tests/crashes/131294-2.rs delete mode 100644 tests/crashes/131294.rs rename tests/{crashes/112623.rs => ui/traits/const-traits/eval-bad-signature.rs} (69%) create mode 100644 tests/ui/traits/const-traits/eval-bad-signature.stderr diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 192dc1b4d229..34ff9c1ec434 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -33,7 +33,7 @@ use tracing::{debug, instrument}; use ty::TypingMode; use {rustc_attr as attr, rustc_hir as hir}; -use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty}; +use super::compare_impl_item::check_type_bounds; use super::*; use crate::check::intrinsicck::InlineAsmCtxt; @@ -1044,20 +1044,8 @@ fn check_impl_items_against_trait<'tcx>( tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait"); continue; }; - match ty_impl_item.kind { - ty::AssocKind::Const => { - tcx.ensure().compare_impl_const(( - impl_item.expect_local(), - ty_impl_item.trait_item_def_id.unwrap(), - )); - } - ty::AssocKind::Fn => { - compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref); - } - ty::AssocKind::Type => { - compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref); - } - } + + let _ = tcx.ensure().compare_impl_item(impl_item.expect_local()); check_specialization_validity( tcx, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 06dee6bda540..16f156a925ed 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -35,6 +35,24 @@ use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; mod refine; +/// Call the query `tcx.compare_impl_item()` directly instead. +pub(super) fn compare_impl_item( + tcx: TyCtxt<'_>, + impl_item_def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + let impl_item = tcx.associated_item(impl_item_def_id); + let trait_item = tcx.associated_item(impl_item.trait_item_def_id.unwrap()); + let impl_trait_ref = + tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity(); + debug!(?impl_trait_ref); + + match impl_item.kind { + ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref), + } +} + /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. /// @@ -44,22 +62,21 @@ mod refine; /// - `trait_m`: the method in the trait /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation #[instrument(level = "debug", skip(tcx))] -pub(super) fn compare_impl_method<'tcx>( +fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: ty::AssocItem, trait_m: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, -) { - let _: Result<_, ErrorGuaranteed> = try { - check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; - compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; - refine::check_refining_return_position_impl_trait_in_trait( - tcx, - impl_m, - trait_m, - impl_trait_ref, - ); - }; +) -> Result<(), ErrorGuaranteed> { + check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; + compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; + refine::check_refining_return_position_impl_trait_in_trait( + tcx, + impl_m, + trait_m, + impl_trait_ref, + ); + Ok(()) } /// Checks a bunch of different properties of the impl/trait methods for @@ -1721,17 +1738,12 @@ fn compare_generic_param_kinds<'tcx>( Ok(()) } -/// Use `tcx.compare_impl_const` instead -pub(super) fn compare_impl_const_raw( - tcx: TyCtxt<'_>, - (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId), +fn compare_impl_const<'tcx>( + tcx: TyCtxt<'tcx>, + impl_const_item: ty::AssocItem, + trait_const_item: ty::AssocItem, + impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let impl_const_item = tcx.associated_item(impl_const_item_def); - let trait_const_item = tcx.associated_item(trait_const_item_def); - let impl_trait_ref = - tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity(); - debug!(?impl_trait_ref); - compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?; compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?; check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?; @@ -1862,19 +1874,17 @@ fn compare_const_predicate_entailment<'tcx>( } #[instrument(level = "debug", skip(tcx))] -pub(super) fn compare_impl_ty<'tcx>( +fn compare_impl_ty<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: ty::AssocItem, trait_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, -) { - let _: Result<(), ErrorGuaranteed> = try { - compare_number_of_generics(tcx, impl_ty, trait_ty, false)?; - compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?; - check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?; - compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?; - check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?; - }; +) -> Result<(), ErrorGuaranteed> { + compare_number_of_generics(tcx, impl_ty, trait_ty, false)?; + compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?; + check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?; + compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?; + check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref) } /// The equivalent of [compare_method_predicate_entailment], but for associated types diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 375cbfd1c4fb..61e203a1ff66 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -108,7 +108,7 @@ pub fn provide(providers: &mut Providers) { adt_async_destructor, region_scope_tree, collect_return_position_impl_trait_in_trait_tys, - compare_impl_const: compare_impl_item::compare_impl_const_raw, + compare_impl_item: compare_impl_item::compare_impl_item, check_coroutine_obligations: check::check_coroutine_obligations, ..*providers }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0f2a6d598a0f..a17aa9ecc044 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2311,10 +2311,13 @@ rustc_queries! { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } - query compare_impl_const( - key: (LocalDefId, DefId) - ) -> Result<(), ErrorGuaranteed> { - desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0) } + /// This takes the def-id of an associated item from a impl of a trait, + /// and checks its validity against the trait item it corresponds to. + /// + /// Any other def id will ICE. + query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } + ensure_forwards_result_if_red } query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 1a98c85bee9f..ede671b0f0f8 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -216,15 +216,13 @@ fn resolve_associated_item<'tcx>( let args = tcx.erase_regions(args); - // Check if we just resolved an associated `const` declaration from - // a `trait` to an associated `const` definition in an `impl`, where - // the definition in the `impl` has the wrong type (for which an - // error has already been/will be emitted elsewhere). - if leaf_def.item.kind == ty::AssocKind::Const - && trait_item_id != leaf_def.item.def_id + // We check that the impl item is compatible with the trait item + // because otherwise we may ICE in const eval due to type mismatches, + // signature incompatibilities, etc. + if trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - tcx.compare_impl_const((leaf_def_item, trait_item_id))?; + tcx.ensure().compare_impl_item(leaf_def_item)?; } Some(ty::Instance::new(leaf_def.item.def_id, args)) diff --git a/tests/crashes/119701.rs b/tests/crashes/119701.rs deleted file mode 100644 index bdb326ea76b1..000000000000 --- a/tests/crashes/119701.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: #119701 -#![feature(const_trait_impl, generic_const_exprs)] - -fn main() { - let _ = process::<()>([()]); -} - -fn process() -> [(); T::make(2)] { - input -} - -#[const_trait] -trait Trait { - fn make(input: u8) -> usize; -} - -impl const Trait for () { - fn make(input: usize) -> usize { - input / 2 - } -} diff --git a/tests/crashes/121127.rs b/tests/crashes/121127.rs deleted file mode 100644 index e50dc7763fc6..000000000000 --- a/tests/crashes/121127.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #121127 -//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes -C debuginfo=2 -// Note that as of PR#123949 this only crashes with debuginfo enabled - -#![feature(specialization)] - -pub trait Foo { - fn abc() -> u32; -} - -pub trait Marker {} - -impl Foo for T { - default fn abc(f: fn(&T), t: &T) -> u32 { - 16 - } -} - -impl Foo for T { - fn def() -> u32 { - Self::abc() - } -} diff --git a/tests/crashes/121411.rs b/tests/crashes/121411.rs deleted file mode 100644 index 2456910e6fa6..000000000000 --- a/tests/crashes/121411.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #121411 -#![feature(const_trait_impl)] - -#[const_trait] -trait Foo { - fn into_iter(&self) {} -} - -impl const Foo for () { - fn into_iter(a: u32, b: u32) {} -} - -const _: () = Foo::into_iter(&()); diff --git a/tests/crashes/129075.rs b/tests/crashes/129075.rs deleted file mode 100644 index 4a0e920914cc..000000000000 --- a/tests/crashes/129075.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#129075 -//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes - -struct Foo([T; 2]); - -impl Default for Foo { - fn default(&mut self) -> Self { - Foo([Default::default(); 2]) - } -} - -fn field_array() { - let a: i32; - let b; - Foo([a, b]) = Default::default(); -} diff --git a/tests/crashes/129127.rs b/tests/crashes/129127.rs deleted file mode 100644 index 8ec848dbd057..000000000000 --- a/tests/crashes/129127.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: rust-lang/rust#129127 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always - - - - -pub struct Rows<'a>(); - -impl<'a> Iterator for Rows<'a> { - type Item = (); - - fn next() -> Option { - let mut rows = Rows(); - rows.map(|row| row).next() - } -} - -fn main() { - let mut rows = Rows(); - rows.next(); -} diff --git a/tests/crashes/129214.rs b/tests/crashes/129214.rs deleted file mode 100644 index e14b9f379d62..000000000000 --- a/tests/crashes/129214.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ known-bug: rust-lang/rust#129214 -//@ compile-flags: -Zvalidate-mir -Copt-level=3 --crate-type=lib - -trait to_str {} - -trait map { - fn map(&self, f: F) -> Vec - where - F: FnMut(&Box) -> U; -} -impl map for Vec { - fn map(&self, mut f: F) -> Vec - where - F: FnMut(&T) -> U, - { - let mut r = Vec::new(); - for i in self { - r.push(f(i)); - } - r - } -} - -fn foo>(x: T) -> Vec { - x.map(|_e| "hi".to_string()) -} - -pub fn main() { - assert_eq!(foo(vec![1]), ["hi".to_string()]); -} diff --git a/tests/crashes/131294-2.rs b/tests/crashes/131294-2.rs deleted file mode 100644 index 130a8b10fb78..000000000000 --- a/tests/crashes/131294-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #131294 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always - -// https://github.com/rust-lang/rust/issues/131294#issuecomment-2395088049 second comment -struct Rows; - -impl Iterator for Rows { - type Item = String; - - fn next() -> Option { - let args = format_args!("Hello world"); - - { - match args.as_str() { - Some(t) => t.to_owned(), - None => String::new(), - } - } - .into() - } -} - -fn main() { - Rows.next(); -} diff --git a/tests/crashes/131294.rs b/tests/crashes/131294.rs deleted file mode 100644 index ec6c95674677..000000000000 --- a/tests/crashes/131294.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #131294 -//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always - -struct Rows; - -impl Iterator for Rows { - type Item = String; - - fn next() -> Option { - std::fmt::format(format_args!("Hello world")).into() - } -} - -fn main() { - Rows.next(); -} diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr index c3292314f23b..cce627499125 100644 --- a/tests/ui/const-generics/issues/issue-83765.stderr +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -29,11 +29,11 @@ note: ...which requires computing candidate for `::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when checking that `` is well-formed - --> $DIR/issue-83765.rs:56:1 +note: cycle used when checking assoc item `::bget` is compatible with trait definition + --> $DIR/issue-83765.rs:58:5 | -LL | impl<'a, T: Broadcastable, const DIM: usize> Broadcastable for LazyUpdim<'a, T, { T::DIM }, DIM> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn bget(&self, index: [usize; DIM]) -> Option { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0308]: method not compatible with trait diff --git a/tests/crashes/112623.rs b/tests/ui/traits/const-traits/eval-bad-signature.rs similarity index 69% rename from tests/crashes/112623.rs rename to tests/ui/traits/const-traits/eval-bad-signature.rs index 592ad742e5ff..97c573ea6528 100644 --- a/tests/crashes/112623.rs +++ b/tests/ui/traits/const-traits/eval-bad-signature.rs @@ -1,4 +1,4 @@ -//@ known-bug: #112623 +// Make sure we don't ICE when evaluating a trait whose impl has a bad signature. #![feature(const_trait_impl)] @@ -15,6 +15,7 @@ struct FortyTwo; impl const Value for FortyTwo { fn value() -> i64 { + //~^ ERROR method `value` has an incompatible type for trait 42 } } diff --git a/tests/ui/traits/const-traits/eval-bad-signature.stderr b/tests/ui/traits/const-traits/eval-bad-signature.stderr new file mode 100644 index 000000000000..a64cf631743d --- /dev/null +++ b/tests/ui/traits/const-traits/eval-bad-signature.stderr @@ -0,0 +1,21 @@ +error[E0053]: method `value` has an incompatible type for trait + --> $DIR/eval-bad-signature.rs:17:19 + | +LL | fn value() -> i64 { + | ^^^ expected `u32`, found `i64` + | +note: type in trait + --> $DIR/eval-bad-signature.rs:7:19 + | +LL | fn value() -> u32; + | ^^^ + = note: expected signature `fn() -> u32` + found signature `fn() -> i64` +help: change the output type to match the trait + | +LL | fn value() -> u32 { + | ~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0053`. From 1e655ef21385eee0a3c224523eac316c7c20e8ed Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Nov 2024 16:44:58 +0000 Subject: [PATCH 236/330] Move refinement check out of compare_impl_item --- .../rustc_hir_analysis/src/check/check.rs | 19 +++++++++++++- .../src/check/compare_impl_item.rs | 8 +----- .../src/check/compare_impl_item/refine.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 2 ++ tests/ui/impl-trait/in-trait/refine-cycle.rs | 26 +++++++++++++++++++ 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/refine-cycle.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 34ff9c1ec434..e1f4ccca97e9 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1045,7 +1045,24 @@ fn check_impl_items_against_trait<'tcx>( continue; }; - let _ = tcx.ensure().compare_impl_item(impl_item.expect_local()); + let res = tcx.ensure().compare_impl_item(impl_item.expect_local()); + + if res.is_ok() { + match ty_impl_item.kind { + ty::AssocKind::Fn => { + compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait( + tcx, + ty_impl_item, + ty_trait_item, + tcx.impl_trait_ref(ty_impl_item.container_id(tcx)) + .unwrap() + .instantiate_identity(), + ); + } + ty::AssocKind::Const => {} + ty::AssocKind::Type => {} + } + } check_specialization_validity( tcx, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 16f156a925ed..e176fc589995 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -33,7 +33,7 @@ use tracing::{debug, instrument}; use super::potentially_plural_count; use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; -mod refine; +pub(super) mod refine; /// Call the query `tcx.compare_impl_item()` directly instead. pub(super) fn compare_impl_item( @@ -70,12 +70,6 @@ fn compare_impl_method<'tcx>( ) -> Result<(), ErrorGuaranteed> { check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; - refine::check_refining_return_position_impl_trait_in_trait( - tcx, - impl_m, - trait_m, - impl_trait_ref, - ); Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 67cbcc1566ab..6eac4ac3baf8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -17,7 +17,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt; use rustc_trait_selection::traits::{ObligationCtxt, elaborate, normalize_param_env_or_error}; /// Check that an implementation does not refine an RPITIT from a trait method signature. -pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( +pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( tcx: TyCtxt<'tcx>, impl_m: ty::AssocItem, trait_m: ty::AssocItem, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index ede671b0f0f8..eb30169a7d91 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -219,6 +219,8 @@ fn resolve_associated_item<'tcx>( // We check that the impl item is compatible with the trait item // because otherwise we may ICE in const eval due to type mismatches, // signature incompatibilities, etc. + // NOTE: We could also only enforce this in `PostAnalysis`, which + // is what CTFE and MIR inlining would care about anyways. if trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { diff --git a/tests/ui/impl-trait/in-trait/refine-cycle.rs b/tests/ui/impl-trait/in-trait/refine-cycle.rs new file mode 100644 index 000000000000..78d672a7ed60 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-cycle.rs @@ -0,0 +1,26 @@ +//@ check-pass + +// Make sure that refinement checking doesn't cause a cycle in `Instance::resolve` +// which calls `compare_impl_item`. + +trait Foo { + fn test() -> impl IntoIterator + Send; +} + +struct A; +impl Foo for A { + fn test() -> impl IntoIterator + Send { + B::test() + } +} + +struct B; +impl Foo for B { + fn test() -> impl IntoIterator + Send { + for () in A::test() {} + + [] + } +} + +fn main() {} From fa7449d130c70bf96d1302ebd69c054227028ec3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Nov 2024 02:47:40 +0000 Subject: [PATCH 237/330] Do not create trait object type if missing associated types --- .../src/hir_ty_lowering/dyn_compatibility.rs | 6 ++- .../src/hir_ty_lowering/errors.rs | 25 ++++++---- tests/crashes/131668.rs | 12 ----- .../overlaping-bound-suggestion.rs | 1 - .../overlaping-bound-suggestion.stderr | 16 +----- tests/ui/async-await/async-fn/dyn-pos.rs | 5 +- tests/ui/async-await/async-fn/dyn-pos.stderr | 48 +----------------- .../dyn-compatibility/missing-assoc-type.rs | 3 -- .../missing-assoc-type.stderr | 49 +------------------ tests/ui/issues/issue-21950.rs | 3 +- tests/ui/issues/issue-21950.stderr | 20 +------- tests/ui/issues/issue-28344.rs | 2 - tests/ui/issues/issue-28344.stderr | 27 ++-------- tests/ui/suggestions/trait-hidden-method.rs | 2 - .../ui/suggestions/trait-hidden-method.stderr | 21 ++------ 15 files changed, 35 insertions(+), 205 deletions(-) delete mode 100644 tests/crashes/131668.rs diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index cab04ee09874..321a8aba7f72 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -219,11 +219,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id)); } - self.complain_about_missing_assoc_tys( + if let Err(guar) = self.check_for_required_assoc_tys( associated_types, potential_assoc_types, hir_trait_bounds, - ); + ) { + return Ty::new_error(tcx, guar); + } // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as // `dyn Trait + Send`. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 0b58b807090d..ff449a858d67 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -714,14 +714,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// reasonable suggestion on how to write it. For the case of multiple associated types in the /// same trait bound have the same name (as they come from different supertraits), we instead /// emit a generic note suggesting using a `where` clause to constraint instead. - pub(crate) fn complain_about_missing_assoc_tys( + pub(crate) fn check_for_required_assoc_tys( &self, associated_types: FxIndexMap>, potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], - ) { + ) -> Result<(), ErrorGuaranteed> { if associated_types.values().all(|v| v.is_empty()) { - return; + return Ok(()); } let tcx = self.tcx(); @@ -739,7 +739,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and // `issue-22560.rs`. let mut trait_bound_spans: Vec = vec![]; - let mut dyn_compatibility_violations = false; + let mut dyn_compatibility_violations = Ok(()); for (span, items) in &associated_types { if !items.is_empty() { trait_bound_spans.push(*span); @@ -752,13 +752,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let violations = dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); if !violations.is_empty() { - report_dyn_incompatibility(tcx, *span, None, trait_def_id, &violations).emit(); - dyn_compatibility_violations = true; + dyn_compatibility_violations = Err(report_dyn_incompatibility( + tcx, + *span, + None, + trait_def_id, + &violations, + ) + .emit()); } } } - if dyn_compatibility_violations { - return; + + if let Err(guar) = dyn_compatibility_violations { + return Err(guar); } // related to issue #91997, turbofishes added only when in an expr or pat @@ -965,7 +972,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - err.emit(); + Err(err.emit()) } /// On ambiguous associated type, look for an associated function whose name matches the diff --git a/tests/crashes/131668.rs b/tests/crashes/131668.rs deleted file mode 100644 index 90aa44944256..000000000000 --- a/tests/crashes/131668.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #131668 - -#![feature(generic_associated_types_extended)] -trait B { - type Y; -} - -struct Erase(T); - -fn make_static() { - Erase:: B<&'c ()>>(()); -} diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs index c0012564843f..ee75cb96afd3 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs @@ -5,7 +5,6 @@ trait Item { pub struct Flatten { inner: >::IntoIterator as Item>::Core, //~^ ERROR E0191 - //~| ERROR E0223 } fn main() {} diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index 39a2b98e2e2d..c80b32dc3d8f 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -4,18 +4,6 @@ error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIt LL | inner: >::IntoIterator as Item>::Core, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator, Item = Type, IntoIter = Type>` -error[E0223]: ambiguous associated type - --> $DIR/overlaping-bound-suggestion.rs:6:13 - | -LL | inner: >::IntoIterator as Item>::Core, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `IntoIterator` implemented for `(dyn IntoIterator + 'static)`, you could use the fully-qualified path - | -LL | inner: <<(dyn IntoIterator + 'static) as Example>::IntoIterator as Item>::Core, - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0191, E0223. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs index 772c7d15cfd4..a16b7c26f0d5 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.rs +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -3,9 +3,6 @@ #![feature(async_closure)] fn foo(x: &dyn async Fn()) {} -//~^ ERROR the trait `AsyncFn` cannot be made into an object -//~| ERROR the trait `AsyncFnMut` cannot be made into an object -//~| ERROR the trait `AsyncFnMut` cannot be made into an object -//~| ERROR the trait `AsyncFnMut` cannot be made into an object +//~^ ERROR the trait `AsyncFnMut` cannot be made into an object fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr index 78e915d49e78..a9abfc5e5c46 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.stderr +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -13,52 +13,6 @@ note: for a trait to be "dyn-compatible" it needs to allow building a vtable to &mut F std::boxed::Box -error[E0038]: the trait `AsyncFnMut` cannot be made into an object - --> $DIR/dyn-pos.rs:5:16 - | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL - | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead: - &F - &mut F - std::boxed::Box - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `AsyncFnMut` cannot be made into an object - --> $DIR/dyn-pos.rs:5:16 - | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL - | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead: - &F - &mut F - std::boxed::Box - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `AsyncFn` cannot be made into an object - --> $DIR/dyn-pos.rs:5:12 - | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^^^^^ `AsyncFn` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL - | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFn` for this new enum and using it instead: - &F - std::boxed::Box - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.rs b/tests/ui/dyn-compatibility/missing-assoc-type.rs index c83be544c0a1..21f7fd92e80d 100644 --- a/tests/ui/dyn-compatibility/missing-assoc-type.rs +++ b/tests/ui/dyn-compatibility/missing-assoc-type.rs @@ -3,8 +3,5 @@ trait Foo { } fn bar(x: &dyn Foo) {} //~ ERROR the trait `Foo` cannot be made into an object -//~^ ERROR the trait `Foo` cannot be made into an object -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR the trait `Foo` cannot be made into an object fn main() {} diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr index f8450ba212d0..184201dd1cee 100644 --- a/tests/ui/dyn-compatibility/missing-assoc-type.stderr +++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr @@ -13,53 +13,6 @@ LL | type Bar; | ^^^ ...because it contains the generic associated type `Bar` = help: consider moving `Bar` to another trait -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/missing-assoc-type.rs:5:16 - | -LL | fn bar(x: &dyn Foo) {} - | ^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/missing-assoc-type.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Bar; - | ^^^ ...because it contains the generic associated type `Bar` - = help: consider moving `Bar` to another trait - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/missing-assoc-type.rs:5:16 - | -LL | fn bar(x: &dyn Foo) {} - | ^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/missing-assoc-type.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Bar; - | ^^^ ...because it contains the generic associated type `Bar` - = help: consider moving `Bar` to another trait - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/missing-assoc-type.rs:5:12 - | -LL | fn bar(x: &dyn Foo) {} - | ^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/missing-assoc-type.rs:2:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type Bar; - | ^^^ ...because it contains the generic associated type `Bar` - = help: consider moving `Bar` to another trait - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-21950.rs b/tests/ui/issues/issue-21950.rs index 72a98bd8ddd8..7a85ac91bca0 100644 --- a/tests/ui/issues/issue-21950.rs +++ b/tests/ui/issues/issue-21950.rs @@ -8,6 +8,5 @@ impl Add for i32 { fn main() { let x = &10 as &dyn Add; - //~^ ERROR E0393 - //~| ERROR E0191 + //~^ ERROR E0191 } diff --git a/tests/ui/issues/issue-21950.stderr b/tests/ui/issues/issue-21950.stderr index 584370c71782..24230cfe17f3 100644 --- a/tests/ui/issues/issue-21950.stderr +++ b/tests/ui/issues/issue-21950.stderr @@ -7,22 +7,6 @@ LL | type Output; LL | let x = &10 as &dyn Add; | ^^^ help: specify the associated type: `Add` -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/issue-21950.rs:10:25 - | -LL | trait Add { - | ------------------- type parameter `Rhs` must be specified for this -... -LL | let x = &10 as &dyn Add; - | ^^^ - | - = note: because of the default `Self` reference, type parameters must be specified on object types -help: set the type parameter to the desired type - | -LL | let x = &10 as &dyn Add; - | +++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0191, E0393. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-28344.rs b/tests/ui/issues/issue-28344.rs index 1a6a7f46b274..951ea5d69e93 100644 --- a/tests/ui/issues/issue-28344.rs +++ b/tests/ui/issues/issue-28344.rs @@ -3,13 +3,11 @@ use std::ops::BitXor; fn main() { let x: u8 = BitXor::bitor(0 as u8, 0 as u8); //~^ ERROR must be specified - //~| no function or associated item named //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition let g = BitXor::bitor; //~^ ERROR must be specified - //~| no function or associated item named //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition } diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index 261f8b67b52c..d8febe716524 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -18,17 +18,8 @@ error[E0191]: the value of the associated type `Output` in `BitXor` must be spec LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^^ help: specify the associated type: `BitXor::` -error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:4:25 - | -LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); - | ^^^^^ function or associated item not found in `dyn BitXor<_>` - | -help: there is a method `bitxor` with a similar name, but with different arguments - --> $SRC_DIR/core/src/ops/bit.rs:LL:COL - warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-28344.rs:10:13 + --> $DIR/issue-28344.rs:9:13 | LL | let g = BitXor::bitor; | ^^^^^^ @@ -41,21 +32,11 @@ LL | let g = ::bitor; | ++++ + error[E0191]: the value of the associated type `Output` in `BitXor` must be specified - --> $DIR/issue-28344.rs:10:13 + --> $DIR/issue-28344.rs:9:13 | LL | let g = BitXor::bitor; | ^^^^^^ help: specify the associated type: `BitXor::` -error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope - --> $DIR/issue-28344.rs:10:21 - | -LL | let g = BitXor::bitor; - | ^^^^^ function or associated item not found in `dyn BitXor<_>` - | -help: there is a method `bitxor` with a similar name - --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +error: aborting due to 2 previous errors; 2 warnings emitted -error: aborting due to 4 previous errors; 2 warnings emitted - -Some errors have detailed explanations: E0191, E0599. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/suggestions/trait-hidden-method.rs b/tests/ui/suggestions/trait-hidden-method.rs index ae7ef47e1d4d..1efc1cc6faeb 100644 --- a/tests/ui/suggestions/trait-hidden-method.rs +++ b/tests/ui/suggestions/trait-hidden-method.rs @@ -1,8 +1,6 @@ // #107983 - testing that `__iterator_get_unchecked` isn't suggested // HELP included so that compiletest errors on the bad suggestion pub fn i_can_has_iterator() -> impl Iterator { - //~^ ERROR expected `Box` - //~| HELP consider constraining the associated type Box::new(1..=10) as Box //~^ ERROR the value of the associated type `Item` //~| HELP specify the associated type diff --git a/tests/ui/suggestions/trait-hidden-method.stderr b/tests/ui/suggestions/trait-hidden-method.stderr index 729523cde55e..87753e578462 100644 --- a/tests/ui/suggestions/trait-hidden-method.stderr +++ b/tests/ui/suggestions/trait-hidden-method.stderr @@ -1,24 +1,9 @@ error[E0191]: the value of the associated type `Item` in `Iterator` must be specified - --> $DIR/trait-hidden-method.rs:6:33 + --> $DIR/trait-hidden-method.rs:4:33 | LL | Box::new(1..=10) as Box | ^^^^^^^^ help: specify the associated type: `Iterator` -error[E0271]: expected `Box` to be an iterator that yields `u32`, but it yields `::Item` - --> $DIR/trait-hidden-method.rs:3:32 - | -LL | pub fn i_can_has_iterator() -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type -... -LL | Box::new(1..=10) as Box - | ------------------------------------- return type was inferred to be `Box` here - | - = note: expected type `u32` - found associated type `::Item` - = help: consider constraining the associated type `::Item` to `u32` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0191, E0271. -For more information about an error, try `rustc --explain E0191`. +For more information about this error, try `rustc --explain E0191`. From ce95a44db65f7f595812a52df6b2f0bc479bd290 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 18:05:48 +0100 Subject: [PATCH 238/330] improve TagEncoding::Niche docs and sanity check --- compiler/rustc_abi/src/lib.rs | 24 +++++++++++++---- .../rustc_ty_utils/src/layout/invariant.rs | 16 ++++++++--- .../enum-untagged-variant-invalid-encoding.rs | 27 +++++++++++++++++++ ...m-untagged-variant-invalid-encoding.stderr | 15 +++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs create mode 100644 src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 2e51753ede69..7ae8b027e3e5 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1215,6 +1215,15 @@ impl Scalar { Scalar::Union { .. } => true, } } + + /// Returns `true` if this is a signed integer scalar + #[inline] + pub fn is_signed(&self) -> bool { + match self.primitive() { + Primitive::Int(_, signed) => signed, + _ => false, + } + } } // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. @@ -1401,10 +1410,7 @@ impl BackendRepr { #[inline] pub fn is_signed(&self) -> bool { match self { - BackendRepr::Scalar(scal) => match scal.primitive() { - Primitive::Int(_, signed) => signed, - _ => false, - }, + BackendRepr::Scalar(scal) => scal.is_signed(), _ => panic!("`is_signed` on non-scalar ABI {self:?}"), } } @@ -1528,14 +1534,22 @@ pub enum TagEncoding { /// The variant `untagged_variant` contains a niche at an arbitrary /// offset (field `tag_field` of the enum), which for a variant with /// discriminant `d` is set to - /// `(d - niche_variants.start).wrapping_add(niche_start)`. + /// `(d - niche_variants.start).wrapping_add(niche_start)` + /// (this is wrapping arithmetic using the type of the niche field). /// /// For example, `Option<(usize, &T)>` is represented such that /// `None` has a null pointer for the second tuple field, and /// `Some` is the identity function (with a non-null reference). + /// + /// Other variants that are not `untagged_variant` and that are outside the `niche_variants` + /// range cannot be represented; they must be uninhabited. Niche { untagged_variant: VariantIdx, + /// This range *may* contain `untagged_variant`; that is then just a "dead value" and + /// not used to encode anything. niche_variants: RangeInclusive, + /// This is inbounds of the type of the niche field + /// (not sign-extended, i.e., all bits beyond the niche field size are 0). niche_start: u128, }, } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 26ea81daf784..f39b87622f44 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -1,11 +1,11 @@ use std::assert_matches::assert_matches; -use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, Variants}; +use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, TagEncoding, Variants}; use rustc_middle::bug; use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; /// Enforce some basic invariants on layouts. -pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { +pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { let tcx = cx.tcx(); // Type-level uninhabitedness should always imply ABI uninhabitedness. @@ -241,7 +241,17 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa check_layout_abi(cx, layout); - if let Variants::Multiple { variants, .. } = &layout.variants { + if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants { + if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding { + let niche_size = tag.size(cx); + assert!(*niche_start <= niche_size.unsigned_int_max()); + for (idx, variant) in variants.iter_enumerated() { + // Ensure all inhabited variants are accounted for. + if !variant.is_uninhabited() { + assert!(idx == *untagged_variant || niche_variants.contains(&idx)); + } + } + } for variant in variants.iter() { // No nested "multiple". assert_matches!(variant.variants, Variants::Single { .. }); diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs new file mode 100644 index 000000000000..bd02e7f5fb44 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs @@ -0,0 +1,27 @@ +// Validity makes this fail at the wrong place. +//@compile-flags: -Zmiri-disable-validation +use std::mem; + +// This enum has untagged variant idx 1, with niche_variants being 0..=2 +// and niche_start being 2. +// That means the untagged variants is in the niche variant range! +// However, using the corresponding value (2+1 = 3) is not a valid encoding of this variant. +#[derive(Copy, Clone, PartialEq)] +enum Foo { + Var1, + Var2(bool), + Var3, +} + +fn main() { + unsafe { + assert!(Foo::Var2(false) == mem::transmute(0u8)); + assert!(Foo::Var2(true) == mem::transmute(1u8)); + assert!(Foo::Var1 == mem::transmute(2u8)); + assert!(Foo::Var3 == mem::transmute(4u8)); + + let invalid: Foo = mem::transmute(3u8); + assert!(matches!(invalid, Foo::Var2(_))); + //~^ ERROR: invalid tag + } +} diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr new file mode 100644 index 000000000000..759dbc363802 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: enum value has invalid tag: 0x03 + --> tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC + | +LL | assert!(matches!(invalid, Foo::Var2(_))); + | ^^^^^^^ enum value has invalid tag: 0x03 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From a36652c274e25802230e5188bceab8a92a3e7346 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 18:06:33 +0100 Subject: [PATCH 239/330] report UB when the niche value refers to the untagged variant --- .../rustc_const_eval/src/const_eval/mod.rs | 4 +- .../src/interpret/discriminant.rs | 43 +++++++++++-------- compiler/rustc_const_eval/src/lib.rs | 1 + compiler/rustc_ty_utils/src/layout.rs | 2 +- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 8cbdcd68e135..34f795bda759 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -2,6 +2,7 @@ use rustc_abi::VariantIdx; use rustc_middle::query::{Key, TyCtxtAt}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use tracing::instrument; @@ -85,5 +86,6 @@ pub fn tag_for_variant_provider<'tcx>( crate::const_eval::DummyMachine, ); - ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag) + let layout = ecx.layout_of(ty).unwrap(); + ecx.tag_for_variant(layout, variant_index).unwrap().map(|(tag, _tag_field)| tag) } diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index f94d0cbb42be..c7c8a2902e29 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -1,7 +1,7 @@ //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines). use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants}; -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty}; use rustc_middle::{mir, span_bug}; use tracing::{instrument, trace}; @@ -21,17 +21,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { variant_index: VariantIdx, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - // Layout computation excludes uninhabited variants from consideration - // therefore there's no way to represent those variants in the given layout. - // Essentially, uninhabited variants do not have a tag that corresponds to their - // discriminant, so we cannot do anything here. - // When evaluating we will always error before even getting here, but ConstProp 'executes' - // dead code, so we cannot ICE here. - if dest.layout().for_variant(self, variant_index).is_uninhabited() { - throw_ub!(UninhabitedEnumVariantWritten(variant_index)) - } - - match self.tag_for_variant(dest.layout().ty, variant_index)? { + match self.tag_for_variant(dest.layout(), variant_index)? { Some((tag, tag_field)) => { // No need to validate that the discriminant here because the // `TyAndLayout::for_variant()` call earlier already checks the @@ -188,6 +178,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let variants = ty.ty_adt_def().expect("tagged layout for non adt").variants(); assert!(variant_index < variants.next_index()); + if variant_index == untagged_variant { + // The untagged variant can be in the niche range, but even then it + // is not a valid encoding. + throw_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))) + } variant_index } else { untagged_variant @@ -236,10 +231,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// given field index. pub(crate) fn tag_for_variant( &self, - ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, variant_index: VariantIdx, ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> { - match self.layout_of(ty)?.variants { + // Layout computation excludes uninhabited variants from consideration. + // Therefore, there's no way to represent those variants in the given layout. + // Essentially, uninhabited variants do not have a tag that corresponds to their + // discriminant, so we have to bail out here. + if layout.for_variant(self, variant_index).is_uninhabited() { + throw_ub!(UninhabitedEnumVariantWritten(variant_index)) + } + + match layout.variants { abi::Variants::Single { .. } => { // The tag of a `Single` enum is like the tag of the niched // variant: there's no tag as the discriminant is encoded @@ -260,7 +263,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let discr = self.discriminant_for_variant(ty, variant_index)?; + let discr = self.discriminant_for_variant(layout.ty, variant_index)?; let discr_size = discr.layout.size; let discr_val = discr.to_scalar().to_bits(discr_size)?; let tag_size = tag_layout.size(self); @@ -286,11 +289,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .. } => { assert!(variant_index != untagged_variant); + // We checked that this variant is inhabited, so it must be in the niche range. + assert!( + niche_variants.contains(&variant_index), + "invalid variant index for this enum" + ); let variants_start = niche_variants.start().as_u32(); - let variant_index_relative = variant_index - .as_u32() - .checked_sub(variants_start) - .expect("overflow computing relative variant idx"); + let variant_index_relative = variant_index.as_u32().strict_sub(variants_start); // We need to use machine arithmetic when taking into account `niche_start`: // tag_val = variant_index_relative + niche_start_val let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 2a7408f1c70e..b5adf06b3001 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -10,6 +10,7 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(slice_ptr_get)] +#![feature(strict_overflow_ops)] #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unqualified_local_imports)] diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 66134b81b2a2..0d656f1b63b1 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -81,7 +81,7 @@ fn layout_of<'tcx>( record_layout_for_printing(&cx, layout); } - invariant::partially_check_layout(&cx, &layout); + invariant::layout_sanity_check(&cx, &layout); Ok(layout) } From 26d7b5da996ec8935c33638f1d7c29f58c96f8f0 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 13 Oct 2024 18:01:52 +0200 Subject: [PATCH 240/330] use stores of the correct size to set discriminants --- compiler/rustc_codegen_ssa/src/mir/place.rs | 24 ++++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index b8fa8c0351b1..c38484109d2c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,5 +1,6 @@ use rustc_abi::Primitive::{Int, Pointer}; -use rustc_abi::{Align, FieldsShape, Size, TagEncoding, VariantIdx, Variants}; +use rustc_abi::{Align, BackendRepr, FieldsShape, Size, TagEncoding, VariantIdx, Variants}; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -385,15 +386,22 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { if variant_index != untagged_variant { let niche = self.project_field(bx, tag_field); let niche_llty = bx.cx().immediate_backend_type(niche.layout); + let BackendRepr::Scalar(scalar) = niche.layout.backend_repr else { + bug!("expected a scalar placeref for the niche"); + }; + // We are supposed to compute `niche_value.wrapping_add(niche_start)` wrapping + // around the `niche`'s type. + // The easiest way to do that is to do wrapping arithmetic on `u128` and then + // masking off any extra bits that occur because we did the arithmetic with too many bits. let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = (niche_value as u128).wrapping_add(niche_start); - // FIXME(eddyb): check the actual primitive type here. - let niche_llval = if niche_value == 0 { - // HACK(eddyb): using `c_null` as it works on all types. - bx.cx().const_null(niche_llty) - } else { - bx.cx().const_uint_big(niche_llty, niche_value) - }; + let niche_value = niche_value & niche.layout.size.unsigned_int_max(); + + let niche_llval = bx.cx().scalar_to_backend( + Scalar::from_uint(niche_value, niche.layout.size), + scalar, + niche_llty, + ); OperandValue::Immediate(niche_llval).store(bx, niche); } } From 484c561d78e3bb4f9e4ec6553303546efbb4ff38 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 30 Nov 2024 19:47:50 +0100 Subject: [PATCH 241/330] Add diagnostic item for `std::ops::ControlFlow` This will be used in Clippy to detect useless conversions done through `ControlFlow::map_break()` and `ControlFlow::map_continue()`. --- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/ops/control_flow.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3a07c283e0eb..c7fd677f7946 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -182,6 +182,7 @@ symbols! { ConstParamTy_, Context, Continue, + ControlFlow, Copy, Cow, Debug, diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 55deabbee8fb..c4429b3cd7d4 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -79,6 +79,7 @@ use crate::{convert, ops}; /// [`Break`]: ControlFlow::Break /// [`Continue`]: ControlFlow::Continue #[stable(feature = "control_flow_enum_type", since = "1.55.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "ControlFlow")] // ControlFlow should not implement PartialOrd or Ord, per RFC 3058: // https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From b118d05f5797e255febfc11822506bf898224973 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 30 Nov 2024 20:22:56 +0100 Subject: [PATCH 242/330] Extend documentation for `missing_doc_code_examples` rustdoc lint in the rustdoc book --- src/doc/rustdoc/src/unstable-features.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index e9524c0b78d5..db8426492eec 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -47,6 +47,10 @@ It can be enabled using: #![deny(rustdoc::missing_doc_code_examples)] ``` +It is not emitted for items that cannot be instantiated/called such as fields, variants, modules, +associated trait/impl items, impl blocks, statics and constants. +It is also not emitted for foreign items, aliases, extern crates and imports. + ## Extensions to the `#[doc]` attribute These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler From d38f01312c1b827a7a0186c186482579a82cdec3 Mon Sep 17 00:00:00 2001 From: Dominik Stolz Date: Thu, 28 Nov 2024 17:33:22 +0100 Subject: [PATCH 243/330] Remove hir::ArrayLen, introduce ConstArgKind::Infer Remove Node::ArrayLenInfer --- compiler/rustc_ast_lowering/src/expr.rs | 2 +- compiler/rustc_ast_lowering/src/index.rs | 13 +---- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++---- compiler/rustc_hir/src/hir.rs | 47 +++++++------------ compiler/rustc_hir/src/intravisit.rs | 16 ++----- compiler/rustc_hir_analysis/src/collect.rs | 8 ++-- .../src/collect/generics_of.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 4 +- .../src/hir_ty_lowering/generics.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 9 +--- compiler/rustc_hir_pretty/src/lib.rs | 15 ++---- compiler/rustc_hir_typeck/src/expr.rs | 14 +++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 18 ++----- .../rustc_hir_typeck/src/method/confirm.rs | 4 +- compiler/rustc_middle/src/hir/map/mod.rs | 2 - .../src/error_reporting/infer/mod.rs | 3 +- src/librustdoc/clean/mod.rs | 38 +++++++-------- src/librustdoc/clean/types.rs | 9 +++- .../clippy_lints/src/large_stack_arrays.rs | 6 +-- .../clippy/clippy_lints/src/utils/author.rs | 12 ++--- .../src/zero_repeat_side_effects.rs | 5 +- .../clippy/clippy_utils/src/hir_utils.rs | 30 ++++-------- src/tools/clippy/clippy_utils/src/lib.rs | 6 +-- .../clippy/tests/ui/author/repeat.stdout | 3 +- 24 files changed, 105 insertions(+), 182 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 3af29838b72c..a65cfec2713c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -118,7 +118,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Repeat(expr, count) => { let expr = self.lower_expr(expr); - let count = self.lower_array_length(count); + let count = self.lower_array_length_to_const_arg(count); hir::ExprKind::Repeat(expr, count) } ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 65e387de800c..c3ff7b4b8972 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -235,8 +235,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_anon_const(&mut self, constant: &'hir AnonConst) { - // FIXME: use real span? - self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant)); + self.insert(constant.span, constant.hir_id, Node::AnonConst(constant)); self.with_parent(constant.hir_id, |this| { intravisit::walk_anon_const(this, constant); @@ -252,8 +251,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) { - // FIXME: use real span? - self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg)); + self.insert(const_arg.span(), const_arg.hir_id, Node::ConstArg(const_arg)); self.with_parent(const_arg.hir_id, |this| { intravisit::walk_const_arg(this, const_arg); @@ -387,13 +385,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_array_length(&mut self, len: &'hir ArrayLen<'hir>) { - match len { - ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), - ArrayLen::Body(..) => intravisit::walk_array_len(self, len), - } - } - fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) { self.visit_pat(p) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dae816663e00..660a80ee6221 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1277,9 +1277,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )) } - TyKind::Array(ty, length) => { - hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) - } + TyKind::Array(ty, length) => hir::TyKind::Array( + self.lower_ty(ty, itctx), + self.lower_array_length_to_const_arg(length), + ), TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)), TyKind::TraitObject(bounds, kind) => { let mut lifetime_bound = None; @@ -2029,14 +2030,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.expr_block(block) } - fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> { + fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> { match c.value.kind { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer() { - hir::ArrayLen::Infer(hir::InferArg { - hir_id: self.lower_node_id(c.id), - span: self.lower_span(c.value.span), - }) + let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); + self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind }) } else { feature_err( &self.tcx.sess, @@ -2045,10 +2044,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fluent_generated::ast_lowering_underscore_array_length_unstable, ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); - hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)) + self.lower_anon_const_to_const_arg(c) } } - _ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)), + _ => self.lower_anon_const_to_const_arg(c), } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 12dec75e65cf..97aa88c1de8d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -275,6 +275,7 @@ impl<'hir> ConstArg<'hir> { match self.kind { ConstArgKind::Path(path) => path.span(), ConstArgKind::Anon(anon) => anon.span, + ConstArgKind::Infer(span) => span, } } } @@ -289,6 +290,11 @@ pub enum ConstArgKind<'hir> { /// However, in the future, we'll be using it for all of those. Path(QPath<'hir>), Anon(&'hir AnonConst), + /// **Note:** Not all inferred consts are represented as + /// `ConstArgKind::Infer`. In cases where it is ambiguous whether + /// a generic arg is a type or a const, inference variables are + /// represented as `GenericArg::Infer` instead. + Infer(Span), } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -308,6 +314,10 @@ pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), Const(&'hir ConstArg<'hir>), + /// **Note:** Inference variables are only represented as + /// `GenericArg::Infer` in cases where it is ambiguous whether + /// a generic arg is a type or a const. Otherwise, inference variables + /// are represented as `TyKind::Infer` or `ConstArgKind::Infer`. Infer(InferArg), } @@ -1645,29 +1655,6 @@ impl fmt::Display for ConstContext { /// A literal. pub type Lit = Spanned; -#[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum ArrayLen<'hir> { - Infer(InferArg), - Body(&'hir ConstArg<'hir>), -} - -impl ArrayLen<'_> { - pub fn span(self) -> Span { - match self { - ArrayLen::Infer(arg) => arg.span, - ArrayLen::Body(body) => body.span(), - } - } - - pub fn hir_id(self) -> HirId { - match self { - ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(&ConstArg { hir_id, .. }) => { - hir_id - } - } - } -} - /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -2115,7 +2102,7 @@ pub enum ExprKind<'hir> { /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, ArrayLen<'hir>), + Repeat(&'hir Expr<'hir>, &'hir ConstArg<'hir>), /// A suspension point for coroutines (i.e., `yield `). Yield(&'hir Expr<'hir>, YieldSource), @@ -2625,7 +2612,7 @@ impl<'hir> Ty<'hir> { TyKind::Infer => true, TyKind::Slice(ty) => ty.is_suggestable_infer_ty(), TyKind::Array(ty, length) => { - ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(..)) + ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..)) } TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty), TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(), @@ -2834,7 +2821,7 @@ pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, ArrayLen<'hir>), + Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2861,6 +2848,11 @@ pub enum TyKind<'hir> { Typeof(&'hir AnonConst), /// `TyKind::Infer` means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. + /// + /// **Note:** Not all inferred types are represented as + /// `TyKind::Infer`. In cases where it is ambiguous whether + /// a generic arg is a type or a const, inference variables are + /// represented as `GenericArg::Infer` instead. Infer, /// Placeholder for a type that has failed to be defined. Err(rustc_span::ErrorGuaranteed), @@ -3801,8 +3793,6 @@ pub enum Node<'hir> { Crate(&'hir Mod<'hir>), Infer(&'hir InferArg), WherePredicate(&'hir WherePredicate<'hir>), - // FIXME: Merge into `Node::Infer`. - ArrayLenInfer(&'hir InferArg), PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), // Created by query feeding Synthetic, @@ -3856,7 +3846,6 @@ impl<'hir> Node<'hir> { | Node::OpaqueTy(..) | Node::Infer(..) | Node::WherePredicate(..) - | Node::ArrayLenInfer(..) | Node::Synthetic | Node::Err(..) => None, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index faaea41047fc..602aa8be740a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -343,9 +343,6 @@ pub trait Visitor<'v>: Sized { fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result { walk_pat_field(self, f) } - fn visit_array_length(&mut self, len: &'v ArrayLen<'v>) -> Self::Result { - walk_array_len(self, len) - } fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { walk_anon_const(self, c) } @@ -710,14 +707,6 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' visitor.visit_pat(field.pat) } -pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>) -> V::Result { - match len { - // FIXME: Use `visit_infer` here. - ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), - ArrayLen::Body(c) => visitor.visit_const_arg(c), - } -} - pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result { try_visit!(visitor.visit_id(constant.hir_id)); visitor.visit_nested_body(constant.body) @@ -739,6 +728,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( match &const_arg.kind { ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()), ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), + ConstArgKind::Infer(..) => V::Result::output(), } } @@ -753,7 +743,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) } ExprKind::Repeat(ref element, ref count) => { try_visit!(visitor.visit_expr(element)); - try_visit!(visitor.visit_array_length(count)); + try_visit!(visitor.visit_const_arg(count)); } ExprKind::Struct(ref qpath, fields, ref optional_base) => { try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); @@ -901,7 +891,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul } TyKind::Array(ref ty, ref length) => { try_visit!(visitor.visit_ty(ty)); - try_visit!(visitor.visit_array_length(length)); + try_visit!(visitor.visit_const_arg(length)); } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { for bound in bounds { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 93be3e06e5d9..7bc1827098bd 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -150,11 +150,11 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { _ => {} } } - fn visit_array_length(&mut self, length: &'v hir::ArrayLen<'v>) { - if let hir::ArrayLen::Infer(inf) = length { - self.0.push(inf.span); + fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) { + if let hir::ConstArgKind::Infer(span) = const_arg.kind { + self.0.push(span); } - intravisit::walk_array_len(self, length) + intravisit::walk_const_arg(self, const_arg) } } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c31bff28fd34..077696ac1f24 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -181,7 +181,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // expressions' count (i.e. `N` in `[x; N]`), and explicit // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // as they shouldn't be able to cause query cycle errors. - Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. }) + Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. }) if ct.anon_const_hir_id() == Some(hir_id) => { Some(parent_did) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 816761fd00fa..e07fdc98e78c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -144,7 +144,7 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span // Easy case: arrays repeat expressions. Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - if constant.hir_id() == arg_hir_id => + if constant.hir_id == arg_hir_id => { return tcx.types.usize; } @@ -578,8 +578,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ x => bug!("unexpected non-type Node::GenericParam: {:?}", x), }, - Node::ArrayLenInfer(_) => tcx.types.usize, - x => { bug!("unexpected sort of node in type_of(): {:?}", x); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index ae1279d428c1..c3f4fc8699a3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -104,7 +104,7 @@ fn generic_arg_mismatch_err( GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), GenericParamDefKind::Const { .. }, ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => { - let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id())); + let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id)); if let Ok(snippet) = snippet { err.span_suggestion( arg.span(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 01276abec22b..ecfbbd697b7a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2089,6 +2089,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { format!("Const::lower_const_arg: invalid qpath {qpath:?}"), ), hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id), + hir::ConstArgKind::Infer(span) => self.ct_infer(None, span), } } @@ -2309,13 +2310,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.at(span).type_of(def_id).instantiate(tcx, args) } hir::TyKind::Array(ty, length) => { - let length = match length { - hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), - hir::ArrayLen::Body(constant) => { - self.lower_const_arg(constant, FeedConstTy::No) - } - }; - + let length = self.lower_const_arg(length, FeedConstTy::No); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 64c6969d4b9c..bba1dff02431 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -118,7 +118,6 @@ impl<'a> State<'a> { Node::LetStmt(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), Node::WherePredicate(pred) => self.print_where_predicate(pred), - Node::ArrayLenInfer(_) => self.word("_"), Node::Synthetic => unreachable!(), Node::Err(_) => self.word("/*ERROR*/"), } @@ -315,7 +314,7 @@ impl<'a> State<'a> { self.word("["); self.print_type(ty); self.word("; "); - self.print_array_length(length); + self.print_const_arg(length); self.word("]"); } hir::TyKind::Typeof(ref e) => { @@ -986,13 +985,6 @@ impl<'a> State<'a> { self.print_else(elseopt) } - fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) { - match len { - hir::ArrayLen::Infer(..) => self.word("_"), - hir::ArrayLen::Body(ct) => self.print_const_arg(ct), - } - } - fn print_anon_const(&mut self, constant: &hir::AnonConst) { self.ann.nested(self, Nested::Body(constant.body)) } @@ -1001,6 +993,7 @@ impl<'a> State<'a> { match &const_arg.kind { ConstArgKind::Path(qpath) => self.print_qpath(qpath, true), ConstArgKind::Anon(anon) => self.print_anon_const(anon), + ConstArgKind::Infer(..) => self.word("_"), } } @@ -1077,12 +1070,12 @@ impl<'a> State<'a> { self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen<'_>) { + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ConstArg<'_>) { self.ibox(INDENT_UNIT); self.word("["); self.print_expr(element); self.word_space(";"); - self.print_array_length(count); + self.print_const_arg(count); self.word("]"); self.end() } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b4715839cf56..4699b342cec2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -19,7 +19,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; -use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _; +use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::traits::ObligationCause; @@ -425,7 +425,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::Node::Crate(_) | hir::Node::Infer(_) | hir::Node::WherePredicate(_) - | hir::Node::ArrayLenInfer(_) | hir::Node::PreciseCapturingNonLifetimeArg(_) | hir::Node::OpaqueTy(_) => { unreachable!("no sub-expr expected for {parent_node:?}") @@ -1673,9 +1672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { else { return; }; - if let hir::TyKind::Array(_, length) = ty.peel_refs().kind - && let hir::ArrayLen::Body(ct) = length - { + if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind { let span = ct.span(); self.dcx().try_steal_modify_and_emit_err( span, @@ -1713,13 +1710,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, - count: &'tcx hir::ArrayLen<'tcx>, + count: &'tcx hir::ConstArg<'tcx>, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let count_span = count.span(); - let count = self.try_structurally_resolve_const(count_span, self.lower_array_length(count)); + let count = self.try_structurally_resolve_const( + count_span, + self.normalize(count_span, self.lower_const_arg(count, FeedConstTy::No)), + ); if let Some(count) = count.try_to_target_usize(tcx) { self.suggest_array_len(expr, count); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 47af8c681da0..753fc39b0e94 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -486,24 +486,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { - match length { - hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), - hir::ArrayLen::Body(const_arg) => { - let span = const_arg.span(); - let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No); - self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None)); - self.normalize(span, c) - } - } - } - pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, - param_def_id: DefId, + feed: FeedConstTy, ) -> ty::Const<'tcx> { - let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id)); + let ct = self.lowerer().lower_const_arg(const_arg, feed); self.register_wf_obligation( ct.into(), self.tcx.hir().span(const_arg.hir_id), @@ -1278,7 +1266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.lower_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.fcx.lower_const_arg(ct, param.def_id).into() + self.fcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.fcx.ty_infer(Some(param), inf.span).into() diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 3754fd024282..b31ee1a55d63 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -7,7 +7,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; use rustc_hir_analysis::hir_ty_lowering::{ - GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, + FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; @@ -429,7 +429,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.cfcx.lower_ty(ty).raw.into() } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.cfcx.lower_const_arg(ct, param.def_id).into() + self.cfcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { self.cfcx.ty_infer(Some(param), inf.span).into() diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4900575c36e3..0c701c834f27 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -948,7 +948,6 @@ impl<'hir> Map<'hir> { Node::LetStmt(local) => local.span, Node::Crate(item) => item.spans.inner_span, Node::WherePredicate(pred) => pred.span, - Node::ArrayLenInfer(inf) => inf.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::Synthetic => unreachable!(), Node::Err(span) => span, @@ -1226,7 +1225,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { } Node::Crate(..) => String::from("(root_crate)"), Node::WherePredicate(_) => node_str("where predicate"), - Node::ArrayLenInfer(_) => node_str("array len infer"), Node::Synthetic => unreachable!(), Node::Err(_) => node_str("error"), Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 0f9d4cb1982d..8ba7969207e8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1837,11 +1837,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if let Some(tykind) = tykind && let hir::TyKind::Array(_, length) = tykind - && let hir::ArrayLen::Body(ct) = length && let Some((scalar, ty)) = sz.found.try_to_scalar() && ty == self.tcx.types.usize { - let span = ct.span(); + let span = length.span(); Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: scalar.to_target_usize(&self.tcx).unwrap(), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 093f216accbe..5b407ea9a2b4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -290,6 +290,7 @@ pub(crate) fn clean_const<'tcx>( ConstantKind::Path { path: qpath_to_string(qpath).into() } } hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, + hir::ConstArgKind::Infer(..) => ConstantKind::Infer, } } @@ -1803,30 +1804,27 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()), - TyKind::Array(ty, ref length) => { - let length = match length { - hir::ArrayLen::Infer(..) => "_".to_string(), - hir::ArrayLen::Body(const_arg) => { - // NOTE(min_const_generics): We can't use `const_eval_poly` for constants - // as we currently do not supply the parent generics to anonymous constants - // but do allow `ConstKind::Param`. - // - // `const_eval_poly` tries to first substitute generic parameters which - // results in an ICE while manually constructing the constant and using `eval` - // does nothing for `ConstKind::Param`. + TyKind::Array(ty, ref const_arg) => { + // NOTE(min_const_generics): We can't use `const_eval_poly` for constants + // as we currently do not supply the parent generics to anonymous constants + // but do allow `ConstKind::Param`. + // + // `const_eval_poly` tries to first substitute generic parameters which + // results in an ICE while manually constructing the constant and using `eval` + // does nothing for `ConstKind::Param`. + let length = match const_arg.kind { + hir::ConstArgKind::Infer(..) => "_".to_string(), + hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => { + let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); + let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); + let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); + print_const(cx, ct) + } + hir::ConstArgKind::Path(..) => { let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); - let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = - const_arg.kind - { - let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); - cx.tcx.normalize_erasing_regions(typing_env, ct) - } else { - ct - }; print_const(cx, ct) } }; - Array(Box::new(clean_ty(ty, cx)), length.into()) } TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 01d2661f73ed..715bf68374a5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2399,6 +2399,8 @@ pub(crate) enum ConstantKind { Extern { def_id: DefId }, /// `const FOO: u32 = ...;` Local { def_id: DefId, body: BodyId }, + /// An inferred constant as in `[10u8; _]`. + Infer, } impl Constant { @@ -2424,6 +2426,7 @@ impl ConstantKind { ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body)) } + ConstantKind::Infer { .. } => "_".to_string(), } } @@ -2431,7 +2434,8 @@ impl ConstantKind { match *self { ConstantKind::TyConst { .. } | ConstantKind::Path { .. } - | ConstantKind::Anonymous { .. } => None, + | ConstantKind::Anonymous { .. } + | ConstantKind::Infer => None, ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { print_evaluated_const(tcx, def_id, true, true) } @@ -2442,7 +2446,8 @@ impl ConstantKind { match *self { ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } - | ConstantKind::Path { .. } => false, + | ConstantKind::Path { .. } + | ConstantKind::Infer => false, ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { is_literal_expr(tcx, body.hir_id) } diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 4ef881f11d59..46d7df6995a9 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -5,7 +5,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use clippy_utils::macros::macro_backtrace; use clippy_utils::source::snippet; -use rustc_hir::{ArrayLen, Expr, ExprKind, Item, ItemKind, Node}; +use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ConstKind}; @@ -118,13 +118,13 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { /// Only giving help messages if the expr does not contains macro expanded codes. fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool { - /// Check if the span of `ArrayLen` of a repeat expression is within the expr's span, + /// Check if the span of `ConstArg` of a repeat expression is within the expr's span, /// if not, meaning this repeat expr is definitely from some proc-macro. /// /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the /// correct result. fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool { - let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else { + let ExprKind::Repeat(_, len_ct) = expr.kind else { return false; }; !expr.span.contains(len_ct.span()) diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 1bf24083665f..51001d374b44 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -3,7 +3,7 @@ use rustc_ast::LitIntType; use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{ - self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, + self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -278,6 +278,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind"); self.body(field!(anon_const.body)); }, + ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), } } @@ -611,14 +612,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { bind!(self, value, length); kind!("Repeat({value}, {length})"); self.expr(value); - match length.value { - ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"), - ArrayLen::Body(const_arg) => { - bind!(self, const_arg); - chain!(self, "let ArrayLen::Body({const_arg}) = {length}"); - self.const_arg(const_arg); - }, - } + self.const_arg(length); }, ExprKind::Err(_) => kind!("Err(_)"), ExprKind::DropTemps(expr) => { diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs index fdc1d06e67a1..05f856507697 100644 --- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs @@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures; use rustc_ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node}; +use rustc_hir::{ConstArgKind, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::declare_lint_pass; @@ -60,8 +60,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects { // doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg. // the const item depends on `#[cfg]s` and has different values in different compilation // sessions). - else if let ExprKind::Repeat(inner_expr, length) = expr.kind - && let ArrayLen::Body(const_arg) = length + else if let ExprKind::Repeat(inner_expr, const_arg) = expr.kind && let ConstArgKind::Anon(anon_const) = const_arg.kind && let length_expr = hir_map.body(anon_const.body).value && !length_expr.span.from_expansion() diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index ea866a78d87f..920562f4b93f 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHasher; use rustc_hir::MatchSource::TryDesugar; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ - ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, + AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty, TyKind, @@ -266,14 +266,6 @@ impl HirEqInterExpr<'_, '_, '_> { }) } - pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool { - match (left, right) { - (ArrayLen::Infer(..), ArrayLen::Infer(..)) => true, - (ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct), - (_, _) => false, - } - } - pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool { // swap out TypeckResults when hashing a body let old_maybe_typeck_results = self.inner.maybe_typeck_results.replace(( @@ -383,7 +375,7 @@ impl HirEqInterExpr<'_, '_, '_> { }, (ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r), (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => { - self.eq_expr(le, re) && self.eq_array_length(ll, rl) + self.eq_expr(le, re) && self.eq_const_arg(ll, rl) }, (ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)), (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => { @@ -469,8 +461,10 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), + (ConstArgKind::Infer(..), ConstArgKind::Infer(..)) => true, // Use explicit match for now since ConstArg is undergoing flux. - (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => { + (ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) + | (ConstArgKind::Infer(..), _) | (_, ConstArgKind::Infer(..)) => { false }, } @@ -589,7 +583,7 @@ impl HirEqInterExpr<'_, '_, '_> { pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { match (&left.kind, &right.kind) { (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), - (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl), + (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl), (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) @@ -1002,7 +996,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, ExprKind::Repeat(e, len) => { self.hash_expr(e); - self.hash_array_length(len); + self.hash_const_arg(len); }, ExprKind::Ret(ref e) => { if let Some(e) = *e { @@ -1195,7 +1189,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, &TyKind::Array(ty, len) => { self.hash_ty(ty); - self.hash_array_length(len); + self.hash_const_arg(len); }, TyKind::Pat(ty, pat) => { self.hash_ty(ty); @@ -1246,13 +1240,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_array_length(&mut self, length: ArrayLen<'_>) { - match length { - ArrayLen::Infer(..) => {}, - ArrayLen::Body(ct) => self.hash_const_arg(ct), - } - } - pub fn hash_body(&mut self, body_id: BodyId) { // swap out TypeckResults when hashing a body let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id)); @@ -1264,6 +1251,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &const_arg.kind { ConstArgKind::Path(path) => self.hash_qpath(path), ConstArgKind::Anon(anon) => self.hash_body(anon.body), + ConstArgKind::Infer(..) => {}, } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 6408cc938cb8..82699211489e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -102,7 +102,7 @@ use rustc_hir::definitions::{DefPath, DefPathData}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{ - self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, + self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, @@ -921,7 +921,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { _ => false, }, ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), - ExprKind::Repeat(x, ArrayLen::Body(len)) => { + ExprKind::Repeat(x, len) => { if let ConstArgKind::Anon(anon_const) = len.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node @@ -951,7 +951,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: & .. }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String), ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), - ExprKind::Repeat(_, ArrayLen::Body(len)) => { + ExprKind::Repeat(_, len) => { if let ConstArgKind::Anon(anon_const) = len.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let LitKind::Int(v, _) = const_lit.node diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout index d9e3f864f12f..1a608734ada9 100644 --- a/src/tools/clippy/tests/ui/author/repeat.stdout +++ b/src/tools/clippy/tests/ui/author/repeat.stdout @@ -1,8 +1,7 @@ if let ExprKind::Repeat(value, length) = expr.kind && let ExprKind::Lit(ref lit) = value.kind && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node - && let ArrayLen::Body(const_arg) = length - && let ConstArgKind::Anon(anon_const) = const_arg.kind + && let ConstArgKind::Anon(anon_const) = length.kind && expr1 = &cx.tcx.hir().body(anon_const.body).value && let ExprKind::Lit(ref lit1) = expr1.kind && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node From 4cb158278c406312b2a406a693e1b4d5b5140175 Mon Sep 17 00:00:00 2001 From: HomelikeBrick42 <64717463+HomelikeBrick42@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:31:09 +1300 Subject: [PATCH 244/330] Fixed typos by changing `happend` to `happened` --- compiler/rustc_lint/messages.ftl | 6 +++--- tests/ui/lint/reference_casting.stderr | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 9df0c50868cb..4aeaf6168160 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -450,15 +450,15 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - .label = casting happend here + .label = casting happened here lint_invalid_reference_casting_bigger_layout = casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused - .label = casting happend here + .label = casting happened here .alloc = backing allocation comes from here .layout = casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes) lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - .label = casting happend here + .label = casting happened here lint_invalid_reference_casting_note_book = for more information, visit diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr index 26af60b6bc51..4205d406b515 100644 --- a/tests/ui/lint/reference_casting.stderr +++ b/tests/ui/lint/reference_casting.stderr @@ -103,7 +103,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:45:16 | LL | let deferred = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here LL | let _num = &mut *deferred; | ^^^^^^^^^^^^^^ | @@ -113,7 +113,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:48:16 | LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; - | ---------------------------------------------------------------------------- casting happend here + | ---------------------------------------------------------------------------- casting happened here LL | let _num = &mut *deferred; | ^^^^^^^^^^^^^^ | @@ -123,7 +123,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:51:16 | LL | let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; - | ---------------------------------------------------------------------------- casting happend here + | ---------------------------------------------------------------------------- casting happened here ... LL | let _num = &mut *deferred_rebind; | ^^^^^^^^^^^^^^^^^^^^^ @@ -150,7 +150,7 @@ error: casting `&T` to `&mut T` is undefined behavior, even if the reference is --> $DIR/reference_casting.rs:62:16 | LL | let num = NUM as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | let _num = &mut *num; | ^^^^^^^^^ @@ -279,7 +279,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:115:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here LL | *value = 1; | ^^^^^^^^^^ | @@ -289,7 +289,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:119:5 | LL | let value = value as *mut i32; - | ----------------- casting happend here + | ----------------- casting happened here LL | *value = 1; | ^^^^^^^^^^ | @@ -299,7 +299,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:122:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here LL | *value = 1; | ^^^^^^^^^^ | @@ -309,7 +309,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:125:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | *value_rebind = 1; | ^^^^^^^^^^^^^^^^^ @@ -336,7 +336,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:131:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | std::ptr::write(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -347,7 +347,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:133:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | std::ptr::write_unaligned(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell` --> $DIR/reference_casting.rs:135:5 | LL | let value = num as *const i32 as *mut i32; - | ----------------------------- casting happend here + | ----------------------------- casting happened here ... LL | std::ptr::write_volatile(value, 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -496,7 +496,7 @@ LL | let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _; | -------------------------------- | | | | | backing allocation comes from here - | casting happend here + | casting happened here LL | let w: *mut [u16] = unsafe {&mut *w}; | ^^^^^^^ | From c02032cd6a215f9f4da63320b96329b2477f4cbc Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 13:44:46 -0800 Subject: [PATCH 245/330] Eliminate precedence arithmetic from rustc_ast_pretty --- .../rustc_ast_pretty/src/pprust/state/expr.rs | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e9c49e9f682f..c95e47021882 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -276,21 +276,22 @@ impl<'a> State<'a> { fixup: FixupContext, ) { let assoc_op = AssocOp::from_ast_binop(op.node); - let prec = assoc_op.precedence() as i8; - let fixity = assoc_op.fixity(); + let binop_prec = assoc_op.precedence() as i8; + let left_prec = lhs.precedence(); + let right_prec = rhs.precedence(); - let (left_prec, right_prec) = match fixity { - Fixity::Left => (prec, prec + 1), - Fixity::Right => (prec + 1, prec), - Fixity::None => (prec + 1, prec + 1), + let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() { + Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), + Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), + Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - let left_prec = match (&lhs.kind, op.node) { + match (&lhs.kind, op.node) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => { - parser::PREC_FORCE_PAREN + left_needs_paren = true; } // We are given `(let _ = a) OP b`. // @@ -300,26 +301,16 @@ impl<'a> State<'a> { // - Otherwise, e.g. when we have `(let a = b) < c` in AST, // parens are required since the parser would interpret `let a = b < c` as // `let a = (b < c)`. To achieve this, we force parens. - (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => { - parser::PREC_FORCE_PAREN + (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => { + left_needs_paren = true; } - _ => left_prec, - }; - - self.print_expr_cond_paren( - lhs, - lhs.precedence() < left_prec, - fixup.leftmost_subexpression(), - ); + _ => {} + } + self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression()); self.space(); self.word_space(op.node.as_str()); - - self.print_expr_cond_paren( - rhs, - rhs.precedence() < right_prec, - fixup.subsequent_subexpression(), - ); + self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression()); } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) { From 34a65f203f4e6c12f45914ac1c1de406e8b56428 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 13:50:04 -0800 Subject: [PATCH 246/330] Eliminate precedence arithmetic from rustc_hir_pretty --- compiler/rustc_hir_pretty/src/lib.rs | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 5a5b39c694f8..c53fb71dca1a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1162,32 +1162,33 @@ impl<'a> State<'a> { fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { let assoc_op = AssocOp::from_ast_binop(op.node); - let prec = assoc_op.precedence() as i8; - let fixity = assoc_op.fixity(); + let binop_prec = assoc_op.precedence() as i8; + let left_prec = lhs.precedence(); + let right_prec = rhs.precedence(); - let (left_prec, right_prec) = match fixity { - Fixity::Left => (prec, prec + 1), - Fixity::Right => (prec + 1, prec), - Fixity::None => (prec + 1, prec + 1), + let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() { + Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), + Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec), + Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec), }; - let left_prec = match (&lhs.kind, op.node) { + match (&lhs.kind, op.node) { // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead // of `(x as i32) < ...`. We need to convince it _not_ to do that. (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Lt | hir::BinOpKind::Shl) => { - parser::PREC_FORCE_PAREN + left_needs_paren = true; } - (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => { - parser::PREC_FORCE_PAREN + (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => { + left_needs_paren = true; } - _ => left_prec, - }; + _ => {} + } - self.print_expr_cond_paren(lhs, lhs.precedence() < left_prec); + self.print_expr_cond_paren(lhs, left_needs_paren); self.space(); self.word_space(op.node.as_str()); - self.print_expr_cond_paren(rhs, rhs.precedence() < right_prec) + self.print_expr_cond_paren(rhs, right_needs_paren); } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { From ca8f47439efab15137f2896697c99a34e0366065 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 13:52:28 -0800 Subject: [PATCH 247/330] Eliminate PREC_FORCE_PAREN --- compiler/rustc_ast/src/util/parser.rs | 1 - compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 8 ++++---- compiler/rustc_hir_pretty/src/lib.rs | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index ed9265d51598..07c72141cc96 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -235,7 +235,6 @@ pub const PREC_RANGE: i8 = -10; // The range 2..=14 is reserved for AssocOp binary operator precedences. pub const PREC_PREFIX: i8 = 50; pub const PREC_UNAMBIGUOUS: i8 = 60; -pub const PREC_FORCE_PAREN: i8 = 100; /// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`. pub fn prec_let_scrutinee_needs_par() -> usize { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index c95e47021882..679f7c4fb593 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -212,9 +212,9 @@ impl<'a> State<'a> { } fn print_expr_call(&mut self, func: &ast::Expr, args: &[P], fixup: FixupContext) { - let prec = match func.kind { - ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, - _ => parser::PREC_UNAMBIGUOUS, + let needs_paren = match func.kind { + ast::ExprKind::Field(..) => true, + _ => func.precedence() < parser::PREC_UNAMBIGUOUS, }; // Independent of parenthesization related to precedence, we must @@ -233,7 +233,7 @@ impl<'a> State<'a> { // because the latter is valid syntax but with the incorrect meaning. // It's a match-expression followed by tuple-expression, not a function // call. - self.print_expr_cond_paren(func, func.precedence() < prec, fixup.leftmost_subexpression()); + self.print_expr_cond_paren(func, needs_paren, fixup.leftmost_subexpression()); self.print_call_post(args) } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index c53fb71dca1a..880e527a2bbb 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1132,12 +1132,12 @@ impl<'a> State<'a> { } fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { - let prec = match func.kind { - hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN, - _ => parser::PREC_UNAMBIGUOUS, + let needs_paren = match func.kind { + hir::ExprKind::Field(..) => true, + _ => func.precedence() < parser::PREC_UNAMBIGUOUS, }; - self.print_expr_cond_paren(func, func.precedence() < prec); + self.print_expr_cond_paren(func, needs_paren); self.print_call_post(args) } From 539c863eaf36d8f8b414cf03b422c6e959505f52 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 14:03:16 -0800 Subject: [PATCH 248/330] Eliminate precedence arithmetic from rustc_parse --- compiler/rustc_parse/src/parser/expr.rs | 31 ++++++++++++++----------- compiler/rustc_parse/src/parser/pat.rs | 7 ++++-- compiler/rustc_parse/src/parser/stmt.rs | 5 ++-- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4430d2d14313..a3b0076f5ad7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,7 +1,7 @@ // ignore-tidy-filelength use core::mem; -use core::ops::ControlFlow; +use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; use ast::token::IdentIsRaw; @@ -120,7 +120,7 @@ impl<'a> Parser<'a> { r: Restrictions, attrs: AttrWrapper, ) -> PResult<'a, (P, bool)> { - self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs)) + self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs)) } /// Parses an associative expression with operators of at least `min_prec` precedence. @@ -128,7 +128,7 @@ impl<'a> Parser<'a> { /// followed by a subexpression (e.g. `1 + 2`). pub(super) fn parse_expr_assoc_with( &mut self, - min_prec: usize, + min_prec: Bound, attrs: AttrWrapper, ) -> PResult<'a, (P, bool)> { let lhs = if self.token.is_range_separator() { @@ -144,7 +144,7 @@ impl<'a> Parser<'a> { /// was actually parsed. pub(super) fn parse_expr_assoc_rest_with( &mut self, - min_prec: usize, + min_prec: Bound, starts_stmt: bool, mut lhs: P, ) -> PResult<'a, (P, bool)> { @@ -163,7 +163,11 @@ impl<'a> Parser<'a> { self.restrictions }; let prec = op.node.precedence(); - if prec < min_prec { + if match min_prec { + Bound::Included(min_prec) => prec < min_prec, + Bound::Excluded(min_prec) => prec <= min_prec, + Bound::Unbounded => false, + } { break; } // Check for deprecated `...` syntax @@ -276,16 +280,16 @@ impl<'a> Parser<'a> { } let fixity = op.fixity(); - let prec_adjustment = match fixity { - Fixity::Right => 0, - Fixity::Left => 1, + let min_prec = match fixity { + Fixity::Right => Bound::Included(prec), + Fixity::Left => Bound::Excluded(prec), // We currently have no non-associative operators that are not handled above by // the special cases. The code is here only for future convenience. - Fixity::None => 1, + Fixity::None => Bound::Excluded(prec), }; let (rhs, _) = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(prec + prec_adjustment, attrs) + this.parse_expr_assoc_with(min_prec, attrs) })?; let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); @@ -460,7 +464,7 @@ impl<'a> Parser<'a> { let maybe_lt = self.token.clone(); let attrs = self.parse_outer_attributes()?; Some( - self.parse_expr_assoc_with(prec + 1, attrs) + self.parse_expr_assoc_with(Bound::Excluded(prec), attrs) .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))? .0, ) @@ -518,7 +522,7 @@ impl<'a> Parser<'a> { let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs) + this.parse_expr_assoc_with(Bound::Excluded(op.unwrap().precedence()), attrs) .map(|(x, _)| (lo.to(x.span), Some(x))) .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { @@ -2643,7 +2647,8 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; } let attrs = self.parse_outer_attributes()?; - let (expr, _) = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; + let (expr, _) = + self.parse_expr_assoc_with(Bound::Excluded(prec_let_scrutinee_needs_par()), attrs)?; let span = lo.to(expr.span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bb976e092bf4..32efe9af0c97 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1,3 +1,5 @@ +use std::ops::Bound; + use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; @@ -435,8 +437,9 @@ impl<'a> Parser<'a> { // Parse an associative expression such as `+ expr`, `% expr`, ... // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. - let Ok((expr, _)) = - snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) + let Ok((expr, _)) = snapshot + .parse_expr_assoc_rest_with(Bound::Unbounded, false, expr) + .map_err(|err| err.cancel()) else { // We got a trailing method/operator, but that wasn't an expression. return None; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 190cd9ed0610..5fa2e01fc863 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::mem; +use std::ops::Bound; use ast::Label; use rustc_ast as ast; @@ -207,7 +208,7 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens` closure, since our // outer attributes do not apply to this part of the expression. let (expr, _) = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_expr_assoc_rest_with(0, true, expr) + this.parse_expr_assoc_rest_with(Bound::Unbounded, true, expr) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -240,7 +241,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?; - let (e, _) = self.parse_expr_assoc_rest_with(0, false, e)?; + let (e, _) = self.parse_expr_assoc_rest_with(Bound::Unbounded, false, e)?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) From 7ced18f329470e5dbdbee54d273193d19e3b43f4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 12:47:18 -0800 Subject: [PATCH 249/330] Eliminate magic numbers from expression precedence --- compiler/rustc_ast/src/ast.rs | 22 +++--- compiler/rustc_ast/src/util/parser.rs | 74 +++++++++++++------ .../rustc_ast_pretty/src/pprust/state/expr.rs | 49 ++++++------ compiler/rustc_errors/src/diagnostic_impls.rs | 7 ++ compiler/rustc_hir/src/hir.rs | 18 ++--- compiler/rustc_hir_pretty/src/lib.rs | 37 +++++----- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/cast.rs | 3 +- .../src/fn_ctxt/suggestions.rs | 10 +-- compiler/rustc_parse/src/errors.rs | 3 +- compiler/rustc_parse/src/parser/expr.rs | 8 +- compiler/rustc_parse/src/parser/pat.rs | 16 ++-- .../clippy/clippy_lints/src/dereference.rs | 28 +++---- .../src/loops/single_element_loop.rs | 4 +- .../clippy_lints/src/matches/manual_utils.rs | 4 +- .../clippy/clippy_lints/src/neg_multiply.rs | 4 +- .../clippy_lints/src/redundant_slicing.rs | 4 +- .../transmutes_expressible_as_ptr_casts.rs | 5 +- 18 files changed, 162 insertions(+), 138 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 56b20e0ad893..14205f66491c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -39,9 +39,7 @@ pub use crate::format::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream}; -use crate::util::parser::{ - AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_RANGE, PREC_UNAMBIGUOUS, -}; +use crate::util::parser::{AssocOp, ExprPrecedence}; /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: @@ -1317,29 +1315,29 @@ impl Expr { Some(P(Ty { kind, id: self.id, span: self.span, tokens: None })) } - pub fn precedence(&self) -> i8 { + pub fn precedence(&self) -> ExprPrecedence { match self.kind { - ExprKind::Closure(..) => PREC_CLOSURE, + ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Yield(..) | ExprKind::Yeet(..) - | ExprKind::Become(..) => PREC_JUMP, + | ExprKind::Become(..) => ExprPrecedence::Jump, // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence // ensures that `pprust` will add parentheses in the right places to get the desired // parse. - ExprKind::Range(..) => PREC_RANGE, + ExprKind::Range(..) => ExprPrecedence::Range, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8, - ExprKind::Cast(..) => AssocOp::As.precedence() as i8, + ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | - ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8, + ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix ExprKind::AddrOf(..) @@ -1348,7 +1346,7 @@ impl Expr { // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. | ExprKind::Let(..) - | ExprKind::Unary(..) => PREC_PREFIX, + | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Never need parens ExprKind::Array(_) @@ -1381,7 +1379,7 @@ impl Expr { | ExprKind::Underscore | ExprKind::While(..) | ExprKind::Err(_) - | ExprKind::Dummy => PREC_UNAMBIGUOUS, + | ExprKind::Dummy => ExprPrecedence::Unambiguous, } } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 07c72141cc96..e88bf27021af 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -128,21 +128,21 @@ impl AssocOp { } /// Gets the precedence of this operator - pub fn precedence(&self) -> usize { + pub fn precedence(&self) -> ExprPrecedence { use AssocOp::*; match *self { - As => 14, - Multiply | Divide | Modulus => 13, - Add | Subtract => 12, - ShiftLeft | ShiftRight => 11, - BitAnd => 10, - BitXor => 9, - BitOr => 8, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7, - LAnd => 6, - LOr => 5, - DotDot | DotDotEq => 4, - Assign | AssignOp(_) => 2, + As => ExprPrecedence::Cast, + Multiply | Divide | Modulus => ExprPrecedence::Product, + Add | Subtract => ExprPrecedence::Sum, + ShiftLeft | ShiftRight => ExprPrecedence::Shift, + BitAnd => ExprPrecedence::BitAnd, + BitXor => ExprPrecedence::BitXor, + BitOr => ExprPrecedence::BitOr, + Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare, + LAnd => ExprPrecedence::LAnd, + LOr => ExprPrecedence::LOr, + DotDot | DotDotEq => ExprPrecedence::Range, + Assign | AssignOp(_) => ExprPrecedence::Assign, } } @@ -229,16 +229,44 @@ impl AssocOp { } } -pub const PREC_CLOSURE: i8 = -40; -pub const PREC_JUMP: i8 = -30; -pub const PREC_RANGE: i8 = -10; -// The range 2..=14 is reserved for AssocOp binary operator precedences. -pub const PREC_PREFIX: i8 = 50; -pub const PREC_UNAMBIGUOUS: i8 = 60; +#[derive(Clone, Copy, PartialEq, PartialOrd)] +pub enum ExprPrecedence { + Closure, + // return, break, yield + Jump, + // = += -= *= /= %= &= |= ^= <<= >>= + Assign, + // .. ..= + Range, + // || + LOr, + // && + LAnd, + // == != < > <= >= + Compare, + // | + BitOr, + // ^ + BitXor, + // & + BitAnd, + // << >> + Shift, + // + - + Sum, + // * / % + Product, + // as + Cast, + // unary - * ! & &mut + Prefix, + // paths, loops, function calls, array indexing, field expressions, method calls + Unambiguous, +} /// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`. -pub fn prec_let_scrutinee_needs_par() -> usize { - AssocOp::LAnd.precedence() +pub fn prec_let_scrutinee_needs_par() -> ExprPrecedence { + ExprPrecedence::LAnd } /// Suppose we have `let _ = e` and the `order` of `e`. @@ -246,8 +274,8 @@ pub fn prec_let_scrutinee_needs_par() -> usize { /// /// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`. /// Can we print this as `let _ = a OP b`? -pub fn needs_par_as_let_scrutinee(order: i8) -> bool { - order <= prec_let_scrutinee_needs_par() as i8 +pub fn needs_par_as_let_scrutinee(order: ExprPrecedence) -> bool { + order <= prec_let_scrutinee_needs_par() } /// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 679f7c4fb593..c239cb249c3c 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -5,7 +5,7 @@ use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::util::classify; use rustc_ast::util::literal::escape_byte_str_symbol; -use rustc_ast::util::parser::{self, AssocOp, Fixity}; +use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign, FormatTrait, token, @@ -214,7 +214,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &ast::Expr, args: &[P], fixup: FixupContext) { let needs_paren = match func.kind { ast::ExprKind::Field(..) => true, - _ => func.precedence() < parser::PREC_UNAMBIGUOUS, + _ => func.precedence() < ExprPrecedence::Unambiguous, }; // Independent of parenthesization related to precedence, we must @@ -256,7 +256,7 @@ impl<'a> State<'a> { // a statement containing an expression. self.print_expr_cond_paren( receiver, - receiver.precedence() < parser::PREC_UNAMBIGUOUS, + receiver.precedence() < ExprPrecedence::Unambiguous, fixup, ); @@ -276,7 +276,7 @@ impl<'a> State<'a> { fixup: FixupContext, ) { let assoc_op = AssocOp::from_ast_binop(op.node); - let binop_prec = assoc_op.precedence() as i8; + let binop_prec = assoc_op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); @@ -317,7 +317,7 @@ impl<'a> State<'a> { self.word(op.as_str()); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_PREFIX, + expr.precedence() < ExprPrecedence::Prefix, fixup.subsequent_subexpression(), ); } @@ -339,7 +339,7 @@ impl<'a> State<'a> { } self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_PREFIX, + expr.precedence() < ExprPrecedence::Prefix, fixup.subsequent_subexpression(), ); } @@ -423,10 +423,9 @@ impl<'a> State<'a> { self.print_token_literal(lit, expr.span) } ast::ExprKind::Cast(expr, ty) => { - let prec = AssocOp::As.precedence() as i8; self.print_expr_cond_paren( expr, - expr.precedence() < prec, + expr.precedence() < ExprPrecedence::Cast, fixup.leftmost_subexpression(), ); self.space(); @@ -503,7 +502,7 @@ impl<'a> State<'a> { MatchKind::Postfix => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup, ); self.word_nbsp(".match"); @@ -567,31 +566,31 @@ impl<'a> State<'a> { ast::ExprKind::Await(expr, _) => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup, ); self.word(".await"); } ast::ExprKind::Assign(lhs, rhs, _) => { - let prec = AssocOp::Assign.precedence() as i8; self.print_expr_cond_paren( lhs, - lhs.precedence() <= prec, + // Ranges are allowed on the right-hand side of assignment, + // but not the left. `(a..b) = c` needs parentheses. + lhs.precedence() <= ExprPrecedence::Range, fixup.leftmost_subexpression(), ); self.space(); self.word_space("="); self.print_expr_cond_paren( rhs, - rhs.precedence() < prec, + rhs.precedence() < ExprPrecedence::Assign, fixup.subsequent_subexpression(), ); } ast::ExprKind::AssignOp(op, lhs, rhs) => { - let prec = AssocOp::Assign.precedence() as i8; self.print_expr_cond_paren( lhs, - lhs.precedence() <= prec, + lhs.precedence() <= ExprPrecedence::Range, fixup.leftmost_subexpression(), ); self.space(); @@ -599,14 +598,14 @@ impl<'a> State<'a> { self.word_space("="); self.print_expr_cond_paren( rhs, - rhs.precedence() < prec, + rhs.precedence() < ExprPrecedence::Assign, fixup.subsequent_subexpression(), ); } ast::ExprKind::Field(expr, ident) => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup, ); self.word("."); @@ -615,7 +614,7 @@ impl<'a> State<'a> { ast::ExprKind::Index(expr, index, _) => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup.leftmost_subexpression(), ); self.word("["); @@ -627,7 +626,7 @@ impl<'a> State<'a> { // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`. // Here we use a fake precedence value so that any child with lower precedence than // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.) - let fake_prec = AssocOp::LOr.precedence() as i8; + let fake_prec = ExprPrecedence::LOr; if let Some(e) = start { self.print_expr_cond_paren( e, @@ -662,7 +661,7 @@ impl<'a> State<'a> { expr, // Parenthesize if required by precedence, or in the // case of `break 'inner: loop { break 'inner 1 } + 1` - expr.precedence() < parser::PREC_JUMP + expr.precedence() < ExprPrecedence::Jump || (opt_label.is_none() && classify::leading_labeled_expr(expr)), fixup.subsequent_subexpression(), ); @@ -681,7 +680,7 @@ impl<'a> State<'a> { self.word(" "); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -694,7 +693,7 @@ impl<'a> State<'a> { self.word(" "); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -704,7 +703,7 @@ impl<'a> State<'a> { self.word(" "); self.print_expr_cond_paren( result, - result.precedence() < parser::PREC_JUMP, + result.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -758,13 +757,13 @@ impl<'a> State<'a> { self.space(); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } } ast::ExprKind::Try(e) => { - self.print_expr_cond_paren(e, e.precedence() < parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren(e, e.precedence() < ExprPrecedence::Unambiguous, fixup); self.word("?") } ast::ExprKind::TryBlock(blk) => { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 798668b8bc1f..b45103713239 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use std::process::ExitStatus; use rustc_abi::TargetDataLayoutErrors; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast_pretty::pprust; use rustc_macros::Subdiagnostic; use rustc_span::Span; @@ -298,6 +299,12 @@ impl IntoDiagArg for hir::def::Namespace { } } +impl IntoDiagArg for ExprPrecedence { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Number(self as i32) + } +} + #[derive(Clone)] pub struct DiagSymbolList(Vec); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 12dec75e65cf..f13289ac48ff 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_abi::ExternAbi; -use rustc_ast::util::parser::{AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_UNAMBIGUOUS}; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence}; use rustc_ast::{ self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind, TraitObjectSyntax, UintTy, @@ -1708,22 +1708,22 @@ pub struct Expr<'hir> { } impl Expr<'_> { - pub fn precedence(&self) -> i8 { + pub fn precedence(&self) -> ExprPrecedence { match self.kind { - ExprKind::Closure { .. } => PREC_CLOSURE, + ExprKind::Closure { .. } => ExprPrecedence::Closure, ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Yield(..) - | ExprKind::Become(..) => PREC_JUMP, + | ExprKind::Become(..) => ExprPrecedence::Jump, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8, - ExprKind::Cast(..) => AssocOp::As.precedence() as i8, + ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | - ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8, + ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix ExprKind::AddrOf(..) @@ -1732,7 +1732,7 @@ impl Expr<'_> { // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. | ExprKind::Let(..) - | ExprKind::Unary(..) => PREC_PREFIX, + | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Never need parens ExprKind::Array(_) @@ -1753,7 +1753,7 @@ impl Expr<'_> { | ExprKind::Struct(..) | ExprKind::Tup(_) | ExprKind::Type(..) - | ExprKind::Err(_) => PREC_UNAMBIGUOUS, + | ExprKind::Err(_) => ExprPrecedence::Unambiguous, ExprKind::DropTemps(ref expr, ..) => expr.precedence(), } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 880e527a2bbb..9099e14b3304 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,7 +10,7 @@ use std::cell::Cell; use std::vec; use rustc_abi::ExternAbi; -use rustc_ast::util::parser::{self, AssocOp, Fixity}; +use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; @@ -1134,7 +1134,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let needs_paren = match func.kind { hir::ExprKind::Field(..) => true, - _ => func.precedence() < parser::PREC_UNAMBIGUOUS, + _ => func.precedence() < ExprPrecedence::Unambiguous, }; self.print_expr_cond_paren(func, needs_paren); @@ -1148,7 +1148,7 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_cond_paren(receiver, receiver.precedence() < parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous); self.word("."); self.print_ident(segment.ident); @@ -1162,7 +1162,7 @@ impl<'a> State<'a> { fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { let assoc_op = AssocOp::from_ast_binop(op.node); - let binop_prec = assoc_op.precedence() as i8; + let binop_prec = assoc_op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); @@ -1193,7 +1193,7 @@ impl<'a> State<'a> { fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { self.word(op.as_str()); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); } fn print_expr_addr_of( @@ -1210,7 +1210,7 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); } fn print_literal(&mut self, lit: &hir::Lit) { @@ -1348,8 +1348,7 @@ impl<'a> State<'a> { self.print_literal(lit); } hir::ExprKind::Cast(expr, ty) => { - let prec = AssocOp::As.precedence() as i8; - self.print_expr_cond_paren(expr, expr.precedence() < prec); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast); self.space(); self.word_space("as"); self.print_type(ty); @@ -1450,27 +1449,25 @@ impl<'a> State<'a> { self.print_block(blk); } hir::ExprKind::Assign(lhs, rhs, _) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_cond_paren(lhs, lhs.precedence() <= prec); + self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); self.word_space("="); - self.print_expr_cond_paren(rhs, rhs.precedence() < prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::AssignOp(op, lhs, rhs) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_cond_paren(lhs, lhs.precedence() <= prec); + self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_cond_paren(rhs, rhs.precedence() < prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::Field(expr, ident) => { - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); self.word("."); self.print_ident(ident); } hir::ExprKind::Index(expr, index, _) => { - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); self.word("["); self.print_expr(index); self.word("]"); @@ -1484,7 +1481,7 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } } hir::ExprKind::Continue(destination) => { @@ -1498,13 +1495,13 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } } hir::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_cond_paren(result, result.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump); } hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); @@ -1529,7 +1526,7 @@ impl<'a> State<'a> { } hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } hir::ExprKind::Err(_) => { self.popen(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a92482e6a0e3..ee44c799757c 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -1,6 +1,6 @@ use std::iter; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; @@ -606,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Ok(rest_snippet) = rest_snippet { - let sugg = if callee_expr.precedence() >= PREC_UNAMBIGUOUS { + let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous { vec![ (up_to_rcvr_span, "".to_string()), (rest_span, format!(".{}({rest_snippet}", segment.ident)), diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0c3f21d540dc..80b91c215980 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -28,6 +28,7 @@ //! expression, `e as U2` is not necessarily so (in fact it will only be valid if //! `U1` coerces to `U2`). +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; @@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { let expr_prec = self.expr.precedence(); - let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS; + let needs_parens = expr_prec < ExprPrecedence::Unambiguous; let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize)); let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b493a61b9f44..61260dbd16c5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2,7 +2,7 @@ use core::cmp::min; use core::iter; use hir::def_id::LocalDefId; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir as hir; @@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so we remove the user's `clone` call. { vec![(receiver_method.ident.span, conversion_method.name.to_string())] - } else if expr.precedence() < PREC_UNAMBIGUOUS { + } else if expr.precedence() < ExprPrecedence::Unambiguous { vec![ (expr.span.shrink_to_lo(), "(".to_string()), (expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)), @@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); - let mut sugg = if expr.precedence() >= PREC_UNAMBIGUOUS { + let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -3000,7 +3000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`", ); - let close_paren = if expr.precedence() < PREC_UNAMBIGUOUS { + let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous { sugg.push((expr.span.shrink_to_lo(), "(".to_string())); ")" } else { @@ -3025,7 +3025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = src.trim_end_matches(&checked_ty.to_string()).len(); expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) }, - if expr.precedence() < PREC_UNAMBIGUOUS { + if expr.precedence() < ExprPrecedence::Unambiguous { // Readd `)` format!("{expected_ty})") } else { diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 91e8ba2e1f99..2579e4c1f259 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc_ast::token::Token; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ @@ -2686,7 +2687,7 @@ pub(crate) struct UnexpectedExpressionInPattern { /// Was a `RangePatternBound` expected? pub is_bound: bool, /// The unexpected expr's precedence (used in match arm guard suggestions). - pub expr_precedence: i8, + pub expr_precedence: ExprPrecedence, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a3b0076f5ad7..8d16d44b0a26 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -10,7 +10,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::util::classify; -use rustc_ast::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, @@ -128,7 +128,7 @@ impl<'a> Parser<'a> { /// followed by a subexpression (e.g. `1 + 2`). pub(super) fn parse_expr_assoc_with( &mut self, - min_prec: Bound, + min_prec: Bound, attrs: AttrWrapper, ) -> PResult<'a, (P, bool)> { let lhs = if self.token.is_range_separator() { @@ -144,7 +144,7 @@ impl<'a> Parser<'a> { /// was actually parsed. pub(super) fn parse_expr_assoc_rest_with( &mut self, - min_prec: Bound, + min_prec: Bound, starts_stmt: bool, mut lhs: P, ) -> PResult<'a, (P, bool)> { @@ -455,7 +455,7 @@ impl<'a> Parser<'a> { /// The other two variants are handled in `parse_prefix_range_expr` below. fn parse_expr_range( &mut self, - prec: usize, + prec: ExprPrecedence, lhs: P, op: AssocOp, cur_op_span: Span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 32efe9af0c97..e08b925f0089 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -3,12 +3,11 @@ use std::ops::Bound; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, - Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, - StmtKind, + self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability, + Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind, }; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey}; @@ -548,10 +547,7 @@ impl<'a> Parser<'a> { // HACK: a neater way would be preferable. let expr = match &err.args["expr_precedence"] { DiagArgValue::Number(expr_precedence) => { - if *expr_precedence - <= AssocOp::from_ast_binop(BinOpKind::Eq).precedence() - as i32 - { + if *expr_precedence <= ExprPrecedence::Compare as i32 { format!("({expr})") } else { format!("{expr}") @@ -573,9 +569,7 @@ impl<'a> Parser<'a> { } Some(guard) => { // Are parentheses required around the old guard? - let wrap_guard = guard.precedence() - <= AssocOp::from_ast_binop(BinOpKind::And).precedence() - as i8; + let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd; err.subdiagnostic( UnexpectedExpressionInPatternSugg::UpdateGuard { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index b1d192adff9a..c449a1a875b9 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -7,7 +7,7 @@ use clippy_utils::{ peel_middle_ty_refs, }; use core::mem; -use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS}; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -963,7 +963,7 @@ fn report<'tcx>( // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary. /* - expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX { + expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix { Cow::Owned(format!("({expr_str})")) } else { expr_str @@ -999,13 +999,13 @@ fn report<'tcx>( data.first_expr.span, state.msg, |diag| { - let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { + let needs_paren = 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_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))), - _ => (e.precedence(), false), + ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false, + ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)), + _ => expr.precedence() < e.precedence(), }, - _ => (0, false), + _ => false, }; let is_in_tuple = matches!( get_parent_expr(cx, data.first_expr), @@ -1016,7 +1016,7 @@ fn report<'tcx>( ); let sugg = if !snip_is_macro - && (calls_field || expr.precedence() < precedence) + && needs_paren && !has_enclosing_paren(&snip) && !is_in_tuple { @@ -1049,16 +1049,16 @@ fn report<'tcx>( } } - let (prefix, precedence) = match mutability { + let (prefix, needs_paren) = match mutability { Some(mutability) if !ty.is_ref() => { let prefix = match mutability { Mutability::Not => "&", Mutability::Mut => "&mut ", }; - (prefix, PREC_PREFIX) + (prefix, expr.precedence() < ExprPrecedence::Prefix) }, - None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0), - _ => ("", 0), + None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false), + _ => ("", false), }; span_lint_hir_and_then( cx, @@ -1070,7 +1070,7 @@ fn report<'tcx>( let mut app = Applicability::MachineApplicable; let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); - let sugg = if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) { + let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) { format!("{prefix}({snip})") } else { format!("{prefix}{snip}") @@ -1157,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> { }, Some(parent) if !parent.span.from_expansion() => { // Double reference might be needed at this point. - if parent.precedence() == PREC_UNAMBIGUOUS { + if parent.precedence() == ExprPrecedence::Unambiguous { // Parentheses would be needed here, don't lint. *outer_pat = None; } else { diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index 35dc8e9aa4e2..12719c4f94bf 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, snippet, snippet_with_applicability}; use clippy_utils::visitors::contains_break_or_continue; use rustc_ast::Mutability; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal}; use rustc_lint::LateContext; @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( if !prefix.is_empty() && ( // Precedence of internal expression is less than or equal to precedence of `&expr`. - arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression) + arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression) ) { arg_snip = format!("({arg_snip})").into(); diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 9c6df4d8ac0d..bac5cf88cfbf 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -7,7 +7,7 @@ use clippy_utils::{ CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, }; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::def::Res; @@ -117,7 +117,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous { format!("({scrutinee_str})") } else { scrutinee_str.into() diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index a0ba2aaf5523..429afff9b664 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::has_enclosing_paren; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { { let mut applicability = Applicability::MachineApplicable; let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); - let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) { + let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) { format!("-({snip})") } else { format!("-{snip}") diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 79baa914b031..8e3472b1b5a1 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{get_parent_expr, peel_middle_ty_refs}; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint}; @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr)); let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); - let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX); + let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix); if expr_ty == indexed_ty { if expr_ref_count > indexed_ref_count { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 8d71036084d3..0d5cf45a5e65 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -1,7 +1,7 @@ use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{Expr, Node}; use rustc_hir_typeck::cast::check_cast; @@ -44,8 +44,7 @@ pub(super) fn check<'tcx>( }; if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id) - && parent.precedence() - > i8::try_from(AssocOp::As.precedence()).expect("AssocOp always returns a precedence < 128") + && parent.precedence() > ExprPrecedence::Cast { sugg = format!("({sugg})"); } From 805649b6482f65dfcbdc7dfc96d4b14f5bf1ad99 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 1 Dec 2024 03:01:00 +0000 Subject: [PATCH 250/330] Check let source before suggesting annotation --- compiler/rustc_hir_typeck/src/fallback.rs | 3 ++- ...lint-breaking-2024-assign-underscore.fixed | 17 ++++++++++++ .../lint-breaking-2024-assign-underscore.rs | 17 ++++++++++++ ...int-breaking-2024-assign-underscore.stderr | 26 +++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed create mode 100644 tests/ui/never_type/lint-breaking-2024-assign-underscore.rs create mode 100644 tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 7719facccc7b..ddd146fe785e 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -705,7 +705,8 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) -> Self::Result { // For a local, try suggest annotating the type if it's missing. - if let None = local.ty + if let hir::LocalSource::Normal = local.source + && let None = local.ty && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(local.hir_id) && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed b/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed new file mode 100644 index 000000000000..f9f2b59a8c28 --- /dev/null +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed @@ -0,0 +1,17 @@ +//@ run-rustfix + +#![allow(unused)] +#![deny(dependency_on_unit_never_type_fallback)] + +fn foo() -> Result { + Err(()) +} + +fn test() -> Result<(), ()> { + //~^ ERROR this function depends on never type fallback being `()` + //~| WARN this was previously accepted by the compiler but is being phased out + _ = foo::<()>()?; + Ok(()) +} + +fn main() {} diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs b/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs new file mode 100644 index 000000000000..8a2f3d311ab9 --- /dev/null +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs @@ -0,0 +1,17 @@ +//@ run-rustfix + +#![allow(unused)] +#![deny(dependency_on_unit_never_type_fallback)] + +fn foo() -> Result { + Err(()) +} + +fn test() -> Result<(), ()> { + //~^ ERROR this function depends on never type fallback being `()` + //~| WARN this was previously accepted by the compiler but is being phased out + _ = foo()?; + Ok(()) +} + +fn main() {} diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr new file mode 100644 index 000000000000..dc4ffa0d6f4e --- /dev/null +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr @@ -0,0 +1,26 @@ +error: this function depends on never type fallback being `()` + --> $DIR/lint-breaking-2024-assign-underscore.rs:10:1 + | +LL | fn test() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see issue #123748 + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/lint-breaking-2024-assign-underscore.rs:13:9 + | +LL | _ = foo()?; + | ^^^^^ +note: the lint level is defined here + --> $DIR/lint-breaking-2024-assign-underscore.rs:4:9 + | +LL | #![deny(dependency_on_unit_never_type_fallback)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | _ = foo::<()>()?; + | ++++++ + +error: aborting due to 1 previous error + From 17c6efa9788cf9396750c4edacd4e724e8a7bb2b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Nov 2024 01:44:16 +0000 Subject: [PATCH 251/330] Disentangle hir node match logic in adjust_fulfillment_errors --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 111 ++++++++++-------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index b09d78614c32..eb564f96bc02 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -94,71 +94,82 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate); } - let (expr, qpath) = match self.tcx.hir_node(hir_id) { - hir::Node::Expr(expr) => { - if self.closure_span_overlaps_error(error, expr.span) { + match self.tcx.hir_node(hir_id) { + hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(qpath), span, .. }) => { + if self.closure_span_overlaps_error(error, span) { return false; } - let qpath = - if let hir::ExprKind::Path(qpath) = expr.kind { Some(qpath) } else { None }; - (Some(&expr.kind), qpath) - } - hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => (None, Some(*qpath)), - _ => return false, - }; + if let Some(param) = predicate_self_type_to_point_at + && self.point_at_path_if_possible(error, def_id, param, &qpath) + { + return true; + } - if let Some(qpath) = qpath { - // Prefer pointing at the turbofished arg that corresponds to the - // self type of the failing predicate over anything else. - if let Some(param) = predicate_self_type_to_point_at - && self.point_at_path_if_possible(error, def_id, param, &qpath) - { - return true; - } + if let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Call(callee, args), + hir_id: call_hir_id, + span: call_span, + .. + }) = self.tcx.parent_hir_node(hir_id) + && callee.hir_id == hir_id + { + if self.closure_span_overlaps_error(error, *call_span) { + return false; + } - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Call(callee, args), - hir_id: call_hir_id, - span: call_span, - .. - }) = self.tcx.parent_hir_node(hir_id) - && callee.hir_id == hir_id - { - if self.closure_span_overlaps_error(error, *call_span) { - return false; + for param in + [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.blame_specific_arg_if_possible( + error, + def_id, + param, + *call_hir_id, + callee.span, + None, + args, + ) { + return true; + } + } } for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] .into_iter() .flatten() { - if self.blame_specific_arg_if_possible( - error, - def_id, - param, - *call_hir_id, - callee.span, - None, - args, - ) { + if self.point_at_path_if_possible(error, def_id, param, &qpath) { return true; } } } - - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => { + for param in [ + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ] .into_iter() .flatten() - { - if self.point_at_path_if_possible(error, def_id, param, &qpath) { - return true; + { + if self.point_at_path_if_possible(error, def_id, param, &qpath) { + return true; + } } } - } + hir::Node::Expr(&hir::Expr { + kind: hir::ExprKind::MethodCall(segment, receiver, args, ..), + span, + .. + }) => { + if self.closure_span_overlaps_error(error, span) { + return false; + } - match expr { - Some(hir::ExprKind::MethodCall(segment, receiver, args, ..)) => { if let Some(param) = predicate_self_type_to_point_at && self.point_at_generic_if_possible(error, def_id, param, segment) { @@ -208,7 +219,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - Some(hir::ExprKind::Struct(qpath, fields, ..)) => { + hir::Node::Expr(&hir::Expr { + kind: hir::ExprKind::Struct(qpath, fields, ..), + span, + .. + }) => { + if self.closure_span_overlaps_error(error, span) { + return false; + } + if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = self.typeck_results.borrow().qpath_res(qpath, hir_id) { From 30afeb0357006bf87c8f41f067896e3c0abe11dd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 24 Nov 2024 01:15:04 +0000 Subject: [PATCH 252/330] Adjust HostEffect error spans correctly to point at args --- compiler/rustc_hir_typeck/src/callee.rs | 19 +++- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 107 +++++++++++++++--- compiler/rustc_hir_typeck/src/place_op.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 4 + .../src/error_reporting/traits/suggestions.rs | 5 +- .../ui/consts/const-block-const-bound.stderr | 12 +- ...constifconst-call-in-const-position.stderr | 4 +- tests/ui/consts/fn_trait_refs.stderr | 75 ++++++++++-- .../impl-trait/normalize-tait-in-const.stderr | 12 +- ...assoc-type-const-bound-usage-fail-2.stderr | 4 +- .../assoc-type-const-bound-usage-fail.stderr | 4 +- .../const-traits/call-const-closure.stderr | 4 +- .../call-const-in-tilde-const.stderr | 2 +- .../call-const-trait-method-fail.stderr | 2 +- .../call-generic-method-nonconst.stderr | 12 +- .../const-default-method-bodies.stderr | 4 +- .../const-traits/const-drop-bound.stderr | 12 +- .../const-drop-fail-2.precise.stderr | 16 +-- .../const-drop-fail-2.stock.stderr | 16 +-- .../const-drop-fail.precise.stderr | 39 +++---- .../ui/traits/const-traits/const-drop-fail.rs | 4 +- .../const-traits/const-drop-fail.stock.stderr | 39 +++---- .../const-traits/const-opaque.no.stderr | 16 ++- .../const-traits/cross-crate.gatednc.stderr | 4 +- ...-method-body-is-const-body-checking.stderr | 10 +- ...-method-body-is-const-same-trait-ck.stderr | 4 +- .../effects/minicore-fn-fail.stderr | 12 +- .../effects/no-explicit-const-params.stderr | 4 +- .../specializing-constness-2.stderr | 4 +- .../super-traits-fail-2.yn.stderr | 4 +- .../super-traits-fail-2.yy.stderr | 4 +- .../super-traits-fail-3.yn.stderr | 4 +- .../tilde-const-and-const-params.stderr | 4 +- .../trait-where-clause-const.stderr | 18 ++- .../unsatisfied-const-trait-bound.stderr | 8 +- 36 files changed, 361 insertions(+), 136 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a92482e6a0e3..b0afbab8e01b 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -4,7 +4,7 @@ use rustc_ast::util::parser::PREC_UNAMBIGUOUS; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, HirId, LangItem}; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::infer; use rustc_infer::traits::{self, Obligation, ObligationCause, ObligationCauseCode}; @@ -428,7 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let (fn_sig, def_id) = match *callee_ty.kind() { ty::FnDef(def_id, args) => { - self.enforce_context_effects(call_expr.span, def_id, args); + self.enforce_context_effects(Some(call_expr.hir_id), call_expr.span, def_id, args); let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args); // Unit testing: function items annotated with @@ -837,6 +837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[tracing::instrument(level = "debug", skip(self, span))] pub(super) fn enforce_context_effects( &self, + call_hir_id: Option, span: Span, callee_did: DefId, callee_args: GenericArgsRef<'tcx>, @@ -867,10 +868,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.is_conditionally_const(callee_did) { let q = self.tcx.const_conditions(callee_did); // FIXME(const_trait_impl): Use this span with a better cause code. - for (cond, _) in q.instantiate(self.tcx, callee_args) { + for (idx, (cond, pred_span)) in + q.instantiate(self.tcx, callee_args).into_iter().enumerate() + { + let cause = self.cause( + span, + if let Some(hir_id) = call_hir_id { + ObligationCauseCode::HostEffectInExpr(callee_did, pred_span, hir_id, idx) + } else { + ObligationCauseCode::WhereClause(callee_did, pred_span) + }, + ); self.register_predicate(Obligation::new( self.tcx, - self.misc(span), + cause, self.param_env, cond.to_host_effect_clause(self.tcx, host), )); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 47af8c681da0..76bbcfd1312d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -185,7 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, method: MethodCallee<'tcx>, ) { - self.enforce_context_effects(span, method.def_id, method.args); + self.enforce_context_effects(Some(hir_id), span, method.def_id, method.args); self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_args(hir_id, method.args); } @@ -263,6 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Adjust::Deref(Some(overloaded_deref)) => { self.enforce_context_effects( + None, expr.span, overloaded_deref.method_call(self.tcx), self.tcx.mk_args(&[a.target.into()]), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index eb564f96bc02..3dd82249d330 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -11,26 +11,56 @@ use rustc_trait_selection::traits; use crate::FnCtxt; +enum ClauseFlavor { + /// Predicate comes from `predicates_of`. + Where, + /// Predicate comes from `const_conditions`. + Const, +} + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn adjust_fulfillment_error_for_expr_obligation( &self, error: &mut traits::FulfillmentError<'tcx>, ) -> bool { - let ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) = - *error.obligation.cause.code().peel_derives() - else { - return false; + let (def_id, hir_id, idx, flavor) = match *error.obligation.cause.code().peel_derives() { + ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) => { + (def_id, hir_id, idx, ClauseFlavor::Where) + } + ObligationCauseCode::HostEffectInExpr(def_id, _, hir_id, idx) => { + (def_id, hir_id, idx, ClauseFlavor::Const) + } + _ => return false, }; - let Some(uninstantiated_pred) = self - .tcx - .predicates_of(def_id) - .instantiate_identity(self.tcx) - .predicates - .into_iter() - .nth(idx) - else { - return false; + let uninstantiated_pred = match flavor { + ClauseFlavor::Where => { + if let Some(pred) = self + .tcx + .predicates_of(def_id) + .instantiate_identity(self.tcx) + .predicates + .into_iter() + .nth(idx) + { + pred + } else { + return false; + } + } + ClauseFlavor::Const => { + if let Some((pred, _)) = self + .tcx + .const_conditions(def_id) + .instantiate_identity(self.tcx) + .into_iter() + .nth(idx) + { + pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe) + } else { + return false; + } + } }; let generics = self.tcx.generics_of(def_id); @@ -39,6 +69,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ClauseKind::Trait(pred) => { (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) } + ty::ClauseKind::HostEffect(pred) => { + (pred.trait_ref.args.to_vec(), Some(pred.self_ty().into())) + } ty::ClauseKind::Projection(pred) => (pred.projection_term.args.to_vec(), None), ty::ClauseKind::ConstArgHasType(arg, ty) => (vec![ty.into(), arg.into()], None), ty::ClauseKind::ConstEvaluatable(e) => (vec![e.into()], None), @@ -95,6 +128,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } match self.tcx.hir_node(hir_id) { + hir::Node::Expr(&hir::Expr { + kind: + hir::ExprKind::Call( + hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. }, + args, + ), + span, + .. + }) => { + if self.closure_span_overlaps_error(error, span) { + return false; + } + + if let Some(param) = predicate_self_type_to_point_at + && self.point_at_path_if_possible(error, def_id, param, &qpath) + { + return true; + } + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.blame_specific_arg_if_possible( + error, + def_id, + param, + hir_id, + *callee_span, + None, + args, + ) { + return true; + } + } + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.point_at_path_if_possible(error, def_id, param, &qpath) { + return true; + } + } + } hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(qpath), span, .. }) => { if self.closure_span_overlaps_error(error, span) { return false; @@ -544,7 +622,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> { match obligation_cause_code { - traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) => { + traits::ObligationCauseCode::WhereClauseInExpr(_, _, _, _) + | ObligationCauseCode::HostEffectInExpr(..) => { // This is the "root"; we assume that the `expr` is already pointing here. // Therefore, we return `Ok` so that this `expr` can be refined further. Ok(expr) diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 3d401cef76f7..7c667511aa99 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -296,7 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); }; *deref = OverloadedDeref { mutbl, span: deref.span }; - self.enforce_context_effects(expr.span, method.def_id, method.args); + self.enforce_context_effects(None, expr.span, method.def_id, method.args); // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514). // This helps avoid accidental drops. if inside_union diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d61ef7641ee9..0a77c3bc42fb 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -204,6 +204,10 @@ pub enum ObligationCauseCode<'tcx> { /// list of the item. WhereClauseInExpr(DefId, Span, HirId, usize), + /// Like `WhereClauseinExpr`, but indexes into the `const_conditions` + /// rather than the `predicates_of`. + HostEffectInExpr(DefId, Span, HirId, usize), + /// A type like `&'a T` is WF only if `T: 'a`. ReferenceOutlivesReferent(Ty<'tcx>), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 27b45f709464..2bb503f17b4e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2803,6 +2803,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::WhereClause(item_def_id, span) | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..) + | ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..) if !span.is_dummy() => { if let ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, pos) = &cause_code { @@ -2966,7 +2967,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.help(help); } } - ObligationCauseCode::WhereClause(..) | ObligationCauseCode::WhereClauseInExpr(..) => { + ObligationCauseCode::WhereClause(..) + | ObligationCauseCode::WhereClauseInExpr(..) + | ObligationCauseCode::HostEffectInExpr(..) => { // We hold the `DefId` of the item introducing the obligation, but displaying it // doesn't add user usable information. It always point at an associated item. } diff --git a/tests/ui/consts/const-block-const-bound.stderr b/tests/ui/consts/const-block-const-bound.stderr index b2b2f62c58f2..0931eff2175b 100644 --- a/tests/ui/consts/const-block-const-bound.stderr +++ b/tests/ui/consts/const-block-const-bound.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `UnconstDrop: const Destruct` is not satisfied - --> $DIR/const-block-const-bound.rs:18:9 + --> $DIR/const-block-const-bound.rs:18:11 | LL | f(UnconstDrop); - | ^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `f` + --> $DIR/const-block-const-bound.rs:8:15 + | +LL | const fn f(x: T) {} + | ^^^^^^ required by this bound in `f` error: aborting due to 1 previous error diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr index 6add83dc52c5..c778299560fa 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.stderr +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `T: const Tr` is not satisfied --> $DIR/constifconst-call-in-const-position.rs:17:38 | LL | const fn foo() -> [u8; T::a()] { - | ^^^^^^ + | ^ error[E0277]: the trait bound `T: const Tr` is not satisfied --> $DIR/constifconst-call-in-const-position.rs:18:9 | LL | [0; T::a()] - | ^^^^^^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 108500217139..11e13c3efdd1 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -121,34 +121,89 @@ LL | T: ~const FnMut<()> + ~const Destruct, = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `fn() -> i32 {one}: const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:70:24 + --> $DIR/fn_trait_refs.rs:70:32 | LL | let test_one = test_fn(one); - | ^^^^^^^^^^^^ + | ------- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `test_fn` + --> $DIR/fn_trait_refs.rs:35:24 + | +LL | const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) + | ------- required by a bound in this function +LL | where +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ required by this bound in `test_fn` error[E0277]: the trait bound `fn() -> i32 {two}: const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:73:24 + --> $DIR/fn_trait_refs.rs:73:36 | LL | let test_two = test_fn_mut(two); - | ^^^^^^^^^^^^^^^^ + | ----------- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `test_fn_mut` + --> $DIR/fn_trait_refs.rs:49:27 + | +LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) + | ----------- required by a bound in this function +LL | where +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^ required by this bound in `test_fn_mut` error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:39:9 + --> $DIR/fn_trait_refs.rs:39:19 | LL | tester_fn(&f), - | ^^^^^^^^^^^^^ + | --------- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `tester_fn` + --> $DIR/fn_trait_refs.rs:14:24 + | +LL | const fn tester_fn(f: T) -> T::Output + | --------- required by a bound in this function +LL | where +LL | T: ~const Fn<()> + ~const Destruct, + | ^^^^^^ required by this bound in `tester_fn` error[E0277]: the trait bound `&T: ~const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:41:9 + --> $DIR/fn_trait_refs.rs:41:23 | LL | tester_fn_mut(&f), - | ^^^^^^^^^^^^^^^^^ + | ------------- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `tester_fn_mut` + --> $DIR/fn_trait_refs.rs:21:27 + | +LL | const fn tester_fn_mut(mut f: T) -> T::Output + | ------------- required by a bound in this function +LL | where +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^ required by this bound in `tester_fn_mut` error[E0277]: the trait bound `&mut T: ~const Destruct` is not satisfied - --> $DIR/fn_trait_refs.rs:53:9 + --> $DIR/fn_trait_refs.rs:53:23 | LL | tester_fn_mut(&mut f), - | ^^^^^^^^^^^^^^^^^^^^^ + | ------------- ^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `tester_fn_mut` + --> $DIR/fn_trait_refs.rs:21:27 + | +LL | const fn tester_fn_mut(mut f: T) -> T::Output + | ------------- required by a bound in this function +LL | where +LL | T: ~const FnMut<()> + ~const Destruct, + | ^^^^^^ required by this bound in `tester_fn_mut` error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:16:5 diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index bb874cbe41b3..203fbfc1d2c5 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -13,10 +13,18 @@ LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruc = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `for<'a, 'b> fn(&'a foo::Alias<'b>) {foo}: const Destruct` is not satisfied - --> $DIR/normalize-tait-in-const.rs:33:5 + --> $DIR/normalize-tait-in-const.rs:33:19 | LL | with_positive(foo); - | ^^^^^^^^^^^^^^^^^^ + | ------------- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `with_positive` + --> $DIR/normalize-tait-in-const.rs:26:62 + | +LL | const fn with_positive ~const Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^^^^ required by this bound in `with_positive` error[E0015]: cannot call non-const closure in constant functions --> $DIR/normalize-tait-in-const.rs:27:5 diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr index 86bd07a5f593..c7af0a220ca3 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `::Assoc: ~const Trait` is not sati --> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5 | LL | T::Assoc::::func(); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error[E0277]: the trait bound `::Assoc: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5 | LL | ::Assoc::::func(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr index 145fe2c41dd4..99fc924ad06b 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.stderr @@ -2,13 +2,13 @@ error[E0277]: the trait bound `T: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 | LL | T::Assoc::func(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error[E0277]: the trait bound `T: ~const Trait` is not satisfied --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 | LL | ::Assoc::func(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/call-const-closure.stderr b/tests/ui/traits/const-traits/call-const-closure.stderr index 3fed67f5d088..fe7c115aaab4 100644 --- a/tests/ui/traits/const-traits/call-const-closure.stderr +++ b/tests/ui/traits/const-traits/call-const-closure.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): ~const Bar` is not satisfied - --> $DIR/call-const-closure.rs:17:15 + --> $DIR/call-const-closure.rs:17:18 | LL | (const || ().foo())(); - | ^^^^^^^^ + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr index e56968b90972..b9dabceb5de4 100644 --- a/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr +++ b/tests/ui/traits/const-traits/call-const-in-tilde-const.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: const Foo` is not satisfied --> $DIR/call-const-in-tilde-const.rs:9:13 | LL | const { T::foo() } - | ^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr index b461fd9e39e3..64850335c2ab 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied --> $DIR/call-const-trait-method-fail.rs:26:5 | LL | a.plus(b) - | ^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr index d881bd5f4de6..74a22186a163 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `S: const Foo` is not satisfied - --> $DIR/call-generic-method-nonconst.rs:24:22 + --> $DIR/call-generic-method-nonconst.rs:24:34 | LL | pub const EQ: bool = equals_self(&S); - | ^^^^^^^^^^^^^^^ + | ----------- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `equals_self` + --> $DIR/call-generic-method-nonconst.rs:17:25 + | +LL | const fn equals_self(t: &T) -> bool { + | ^^^^^^ required by this bound in `equals_self` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.stderr b/tests/ui/traits/const-traits/const-default-method-bodies.stderr index 5879330f1582..903f7d37f9d8 100644 --- a/tests/ui/traits/const-traits/const-default-method-bodies.stderr +++ b/tests/ui/traits/const-traits/const-default-method-bodies.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied - --> $DIR/const-default-method-bodies.rs:25:5 + --> $DIR/const-default-method-bodies.rs:25:18 | LL | NonConstImpl.a(); - | ^^^^^^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-bound.stderr b/tests/ui/traits/const-traits/const-drop-bound.stderr index 60718cc84c10..78ba0279566d 100644 --- a/tests/ui/traits/const-traits/const-drop-bound.stderr +++ b/tests/ui/traits/const-traits/const-drop-bound.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `Foo: ~const Destruct` is not satisfied - --> $DIR/const-drop-bound.rs:23:5 + --> $DIR/const-drop-bound.rs:23:9 | LL | foo(res) - | ^^^^^^^^ + | --- ^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/const-drop-bound.rs:9:61 + | +LL | const fn foo(res: Result) -> Option where E: ~const Destruct { + | ^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr index bb9966c7ec39..7b2cafb61244 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr @@ -1,12 +1,14 @@ error[E0277]: the trait bound `ConstDropImplWithBounds: const Destruct` is not satisfied - --> $DIR/const-drop-fail-2.rs:31:15 + --> $DIR/const-drop-fail-2.rs:31:23 | -LL | const _: () = check::>( - | _______________^ -LL | | -LL | | ConstDropImplWithBounds(PhantomData) -LL | | ); - | |_^ +LL | const _: () = check::>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `check` + --> $DIR/const-drop-fail-2.rs:21:19 + | +LL | const fn check(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr index bb9966c7ec39..7b2cafb61244 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr @@ -1,12 +1,14 @@ error[E0277]: the trait bound `ConstDropImplWithBounds: const Destruct` is not satisfied - --> $DIR/const-drop-fail-2.rs:31:15 + --> $DIR/const-drop-fail-2.rs:31:23 | -LL | const _: () = check::>( - | _______________^ -LL | | -LL | | ConstDropImplWithBounds(PhantomData) -LL | | ); - | |_^ +LL | const _: () = check::>( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `check` + --> $DIR/const-drop-fail-2.rs:21:19 + | +LL | const fn check(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr index 67e774fbd059..8b3e777a0b09 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.precise.stderr @@ -1,31 +1,32 @@ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:32:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ | - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 + | +LL | const fn check(_: T) {} + | ^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:34:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 + | +LL | const fn check(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs index 08435266e1f8..5e05b9db474a 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.rs +++ b/tests/ui/traits/const-traits/const-drop-fail.rs @@ -25,14 +25,14 @@ const fn check(_: T) {} macro_rules! check_all { ($($exp:expr),*$(,)?) => {$( const _: () = check($exp); - //~^ ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied - //~| ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied )*}; } check_all! { NonTrivialDrop, + //~^ ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied ConstImplWithDropGlue(NonTrivialDrop), + //~^ ERROR the trait bound `NonTrivialDrop: const Destruct` is not satisfied } fn main() {} diff --git a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr index 67e774fbd059..8b3e777a0b09 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.stock.stderr @@ -1,31 +1,32 @@ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:32:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | NonTrivialDrop, + | ^^^^^^^^^^^^^^ | - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 + | +LL | const fn check(_: T) {} + | ^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:27:23 + --> $DIR/const-drop-fail.rs:34:5 | -LL | const _: () = check($exp); - | ^^^^^^^^^^^ +LL | const _: () = check($exp); + | ----- required by a bound introduced by this call ... -LL | / check_all! { -LL | | NonTrivialDrop, -LL | | ConstImplWithDropGlue(NonTrivialDrop), -LL | | } - | |_- in this macro invocation +LL | ConstImplWithDropGlue(NonTrivialDrop), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info) +note: required by a bound in `check` + --> $DIR/const-drop-fail.rs:23:19 + | +LL | const fn check(_: T) {} + | ^^^^^^ required by this bound in `check` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-opaque.no.stderr b/tests/ui/traits/const-traits/const-opaque.no.stderr index e43a6b603fda..1278e1257467 100644 --- a/tests/ui/traits/const-traits/const-opaque.no.stderr +++ b/tests/ui/traits/const-traits/const-opaque.no.stderr @@ -1,14 +1,22 @@ error[E0277]: the trait bound `(): const Foo` is not satisfied - --> $DIR/const-opaque.rs:31:18 + --> $DIR/const-opaque.rs:31:22 | LL | let opaque = bar(()); - | ^^^^^^^ + | --- ^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/const-opaque.rs:26:17 + | +LL | const fn bar(t: T) -> impl ~const Foo { + | ^^^^^^ required by this bound in `bar` error[E0277]: the trait bound `(): const Foo` is not satisfied - --> $DIR/const-opaque.rs:33:5 + --> $DIR/const-opaque.rs:33:12 | LL | opaque.method(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr index b6f2434140d6..4d5abf643a8c 100644 --- a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr +++ b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied - --> $DIR/cross-crate.rs:19:5 + --> $DIR/cross-crate.rs:19:14 | LL | NonConst.func(); - | ^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr index 0534f3eb8d29..8c284bde67e7 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr @@ -1,8 +1,14 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied - --> $DIR/default-method-body-is-const-body-checking.rs:12:9 + --> $DIR/default-method-body-is-const-body-checking.rs:12:15 | LL | foo::<()>(); - | ^^^^^^^^^^^ + | ^^ + | +note: required by a bound in `foo` + --> $DIR/default-method-body-is-const-body-checking.rs:7:28 + | +LL | const fn foo() where T: ~const Tr {} + | ^^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr index d987cad6f145..2bd71c940e73 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied - --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:9 + --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12 | LL | ().a() - | ^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr b/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr index cf158643b347..fa8be631a26b 100644 --- a/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr +++ b/tests/ui/traits/const-traits/effects/minicore-fn-fail.stderr @@ -1,8 +1,16 @@ error[E0277]: the trait bound `(): ~const Foo` is not satisfied - --> $DIR/minicore-fn-fail.rs:19:5 + --> $DIR/minicore-fn-fail.rs:19:19 | LL | call_indirect(&foo::<()>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------------- ^^^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `call_indirect` + --> $DIR/minicore-fn-fail.rs:11:27 + | +LL | const fn call_indirect(t: &T) { t() } + | ^^^^^^ required by this bound in `call_indirect` error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr index 0b8e4696c461..9bd2c2cb8da2 100644 --- a/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr +++ b/tests/ui/traits/const-traits/effects/no-explicit-const-params.stderr @@ -27,10 +27,10 @@ LL | trait Bar { | ^^^ error[E0277]: the trait bound `(): const Bar` is not satisfied - --> $DIR/no-explicit-const-params.rs:24:5 + --> $DIR/no-explicit-const-params.rs:24:6 | LL | <() as Bar>::bar(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^ error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/no-explicit-const-params.rs:15:5 diff --git a/tests/ui/traits/const-traits/specializing-constness-2.stderr b/tests/ui/traits/const-traits/specializing-constness-2.stderr index 4ad5e3157d4f..edba836aac35 100644 --- a/tests/ui/traits/const-traits/specializing-constness-2.stderr +++ b/tests/ui/traits/const-traits/specializing-constness-2.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: ~const A` is not satisfied - --> $DIR/specializing-constness-2.rs:27:5 + --> $DIR/specializing-constness-2.rs:27:6 | LL | ::a(); - | ^^^^^^^^^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr index 01ae209016a1..ee49810bacec 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -11,10 +11,10 @@ LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:20:5 + --> $DIR/super-traits-fail-2.rs:20:7 | LL | x.a(); - | ^^^^^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr index ae4c65e4aee1..a213273c1c78 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:20:5 + --> $DIR/super-traits-fail-2.rs:20:7 | LL | x.a(); - | ^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr index 8fcada1bfd1d..ecee348222d1 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yn.stderr @@ -25,10 +25,10 @@ LL | const fn foo(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-3.rs:24:5 + --> $DIR/super-traits-fail-3.rs:24:7 | LL | x.a(); - | ^^^^^ + | ^ error: aborting due to 4 previous errors diff --git a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr index 78bf85e9c6de..f77d63db054a 100644 --- a/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr +++ b/tests/ui/traits/const-traits/tilde-const-and-const-params.stderr @@ -26,13 +26,13 @@ error[E0277]: the trait bound `A: const Add42` is not satisfied --> $DIR/tilde-const-and-const-params.rs:27:61 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^ + | ^ error[E0277]: the trait bound `A: const Add42` is not satisfied --> $DIR/tilde-const-and-const-params.rs:9:44 | LL | fn add(self) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^ + | ^ error: aborting due to 4 previous errors diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index d7735ef282f7..4100ae1c6bfd 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -2,13 +2,25 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^^^^^^ + | ^ + | +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause-const.rs:15:24 + | +LL | fn b() where Self: ~const Bar; + | ^^^^^^ required by this bound in `Foo::b` error[E0277]: the trait bound `T: ~const Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:5 + --> $DIR/trait-where-clause-const.rs:23:12 | LL | T::c::(); - | ^^^^^^^^^^^ + | ^ + | +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause-const.rs:16:13 + | +LL | fn c(); + | ^^^^^^ required by this bound in `Foo::c` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index d04143fc4641..bda6a029cc2a 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -10,19 +10,19 @@ error[E0277]: the trait bound `T: const Trait` is not satisfied --> $DIR/unsatisfied-const-trait-bound.rs:29:37 | LL | fn accept0(_: Container<{ T::make() }>) {} - | ^^^^^^^^^ + | ^ error[E0277]: the trait bound `T: const Trait` is not satisfied --> $DIR/unsatisfied-const-trait-bound.rs:33:50 | LL | const fn accept1(_: Container<{ T::make() }>) {} - | ^^^^^^^^^ + | ^ error[E0277]: the trait bound `Ty: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:22:5 + --> $DIR/unsatisfied-const-trait-bound.rs:22:15 | LL | require::(); - | ^^^^^^^^^^^^^^^ + | ^^ | note: required by a bound in `require` --> $DIR/unsatisfied-const-trait-bound.rs:8:15 From d5c5d58a37db02f533993187ba1f12f1bde32a54 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 1 Dec 2024 05:11:38 +0000 Subject: [PATCH 253/330] Pull out expr handling --- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 244 +++++++++--------- 1 file changed, 124 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 3dd82249d330..6eaba641888c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -128,102 +128,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } match self.tcx.hir_node(hir_id) { - hir::Node::Expr(&hir::Expr { - kind: - hir::ExprKind::Call( - hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. }, - args, - ), - span, - .. - }) => { - if self.closure_span_overlaps_error(error, span) { - return false; - } + hir::Node::Expr(expr) => self.point_at_expr_if_possible( + error, + def_id, + expr, + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ), - if let Some(param) = predicate_self_type_to_point_at - && self.point_at_path_if_possible(error, def_id, param, &qpath) - { - return true; - } - - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.blame_specific_arg_if_possible( - error, - def_id, - param, - hir_id, - *callee_span, - None, - args, - ) { - return true; - } - } - - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.point_at_path_if_possible(error, def_id, param, &qpath) { - return true; - } - } - } - hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(qpath), span, .. }) => { - if self.closure_span_overlaps_error(error, span) { - return false; - } - - if let Some(param) = predicate_self_type_to_point_at - && self.point_at_path_if_possible(error, def_id, param, &qpath) - { - return true; - } - - if let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Call(callee, args), - hir_id: call_hir_id, - span: call_span, - .. - }) = self.tcx.parent_hir_node(hir_id) - && callee.hir_id == hir_id - { - if self.closure_span_overlaps_error(error, *call_span) { - return false; - } - - for param in - [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.blame_specific_arg_if_possible( - error, - def_id, - param, - *call_hir_id, - callee.span, - None, - args, - ) { - return true; - } - } - } - - for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] - .into_iter() - .flatten() - { - if self.point_at_path_if_possible(error, def_id, param, &qpath) { - return true; - } - } - } hir::Node::Ty(hir::Ty { kind: hir::TyKind::Path(qpath), .. }) => { for param in [ predicate_self_type_to_point_at, @@ -238,18 +152,107 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } + + false } - hir::Node::Expr(&hir::Expr { - kind: hir::ExprKind::MethodCall(segment, receiver, args, ..), - span, - .. - }) => { - if self.closure_span_overlaps_error(error, span) { - return false; + + _ => false, + } + } + + fn point_at_expr_if_possible( + &self, + error: &mut traits::FulfillmentError<'tcx>, + callee_def_id: DefId, + expr: &'tcx hir::Expr<'tcx>, + predicate_self_type_to_point_at: Option>, + param_to_point_at: Option>, + fallback_param_to_point_at: Option>, + self_param_to_point_at: Option>, + ) -> bool { + if self.closure_span_overlaps_error(error, expr.span) { + return false; + } + + match expr.kind { + hir::ExprKind::Call( + hir::Expr { kind: hir::ExprKind::Path(qpath), span: callee_span, .. }, + args, + ) => { + if let Some(param) = predicate_self_type_to_point_at + && self.point_at_path_if_possible(error, callee_def_id, param, &qpath) + { + return true; } + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.blame_specific_arg_if_possible( + error, + callee_def_id, + param, + expr.hir_id, + *callee_span, + None, + args, + ) { + return true; + } + } + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) { + return true; + } + } + } + hir::ExprKind::Path(qpath) => { + // If the parent is an call, then process this as a call. + // + // This is because the `WhereClauseInExpr` obligations come from + // the well-formedness of the *path* expression, but we care to + // point at the call expression (namely, its args). + if let hir::Node::Expr( + call_expr @ hir::Expr { kind: hir::ExprKind::Call(callee, ..), .. }, + ) = self.tcx.parent_hir_node(expr.hir_id) + && callee.hir_id == expr.hir_id + { + return self.point_at_expr_if_possible( + error, + callee_def_id, + call_expr, + predicate_self_type_to_point_at, + param_to_point_at, + fallback_param_to_point_at, + self_param_to_point_at, + ); + } + + // Otherwise, just try to point at path components. + if let Some(param) = predicate_self_type_to_point_at - && self.point_at_generic_if_possible(error, def_id, param, segment) + && self.point_at_path_if_possible(error, callee_def_id, param, &qpath) + { + return true; + } + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() + { + if self.point_at_path_if_possible(error, callee_def_id, param, &qpath) { + return true; + } + } + } + hir::ExprKind::MethodCall(segment, receiver, args, ..) => { + if let Some(param) = predicate_self_type_to_point_at + && self.point_at_generic_if_possible(error, callee_def_id, param, segment) { // HACK: This is not correct, since `predicate_self_type_to_point_at` might // not actually correspond to the receiver of the method call. But we @@ -259,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error.obligation.cause.map_code(|parent_code| { ObligationCauseCode::FunctionArg { arg_hir_id: receiver.hir_id, - call_hir_id: hir_id, + call_hir_id: expr.hir_id, parent_code, } }); @@ -272,9 +275,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if self.blame_specific_arg_if_possible( error, - def_id, + callee_def_id, param, - hir_id, + expr.hir_id, segment.ident.span, Some(receiver), args, @@ -283,7 +286,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if let Some(param_to_point_at) = param_to_point_at - && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment) + && self.point_at_generic_if_possible( + error, + callee_def_id, + param_to_point_at, + segment, + ) { return true; } @@ -297,25 +305,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - hir::Node::Expr(&hir::Expr { - kind: hir::ExprKind::Struct(qpath, fields, ..), - span, - .. - }) => { - if self.closure_span_overlaps_error(error, span) { - return false; - } - + hir::ExprKind::Struct(qpath, fields, ..) => { if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = - self.typeck_results.borrow().qpath_res(qpath, hir_id) + self.typeck_results.borrow().qpath_res(qpath, expr.hir_id) { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] .into_iter() .flatten() { - let refined_expr = - self.point_at_field_if_possible(def_id, param, variant_def_id, fields); + let refined_expr = self.point_at_field_if_possible( + callee_def_id, + param, + variant_def_id, + fields, + ); match refined_expr { None => {} @@ -339,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .flatten() { - if self.point_at_path_if_possible(error, def_id, param, qpath) { + if self.point_at_path_if_possible(error, callee_def_id, param, qpath) { return true; } } From b87e935407c1d90845e21388ac569d7449e4293a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 26 Nov 2024 00:07:11 +0000 Subject: [PATCH 254/330] Revert "Reject raw lifetime followed by \' as well" This reverts commit 1990f1560801ca3f9e6a3286e58204aa329ee037. --- compiler/rustc_lexer/src/lib.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b584e7afd98f..6caeec1b5cc9 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -707,17 +707,7 @@ impl Cursor<'_> { self.bump(); self.bump(); self.eat_while(is_id_continue); - match self.first() { - '\'' => { - // Check if after skipping literal contents we've met a closing - // single quote (which means that user attempted to create a - // string with single quotes). - self.bump(); - let kind = Char { terminated: true }; - return Literal { kind, suffix_start: self.pos_within_token() }; - } - _ => return RawLifetime, - } + return RawLifetime; } // Either a lifetime or a character literal with From d878fd8877669005ee05de0c5c60021109580934 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 26 Nov 2024 00:28:55 +0000 Subject: [PATCH 255/330] Only error raw lifetime followed by \' in edition 2021+ --- compiler/rustc_parse/src/lexer/mod.rs | 23 +++++++++++++++++-- ...> immediately-followed-by-lt.e2021.stderr} | 2 +- .../raw/immediately-followed-by-lt.rs | 8 +++++-- 3 files changed, 28 insertions(+), 5 deletions(-) rename tests/ui/lifetimes/raw/{immediately-followed-by-lt.stderr => immediately-followed-by-lt.e2021.stderr} (84%) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 8a42cf388f9b..d97f05dc7eb7 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -300,6 +300,26 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let prefix_span = self.mk_sp(start, ident_start); if prefix_span.at_least_rust_2021() { + // If the raw lifetime is followed by \' then treat it a normal + // lifetime followed by a \', which is to interpret it as a character + // literal. In this case, it's always an invalid character literal + // since the literal must necessarily have >3 characters (r#...) inside + // of it, which is invalid. + if self.cursor.as_str().starts_with('\'') { + let lit_span = self.mk_sp(start, self.pos + BytePos(1)); + let contents = self.str_from_to(start + BytePos(1), self.pos); + emit_unescape_error( + self.dcx(), + contents, + lit_span, + lit_span, + Mode::Char, + 0..contents.len(), + EscapeError::MoreThanOneChar, + ) + .expect("expected error"); + } + let span = self.mk_sp(start, self.pos); let lifetime_name_without_tick = @@ -371,8 +391,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - rustc_lexer::TokenKind::Unknown - | rustc_lexer::TokenKind::InvalidIdent => { + rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { // Don't emit diagnostics for sequences of the same invalid token if swallow_next_invalid > 0 { swallow_next_invalid -= 1; diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr b/tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr similarity index 84% rename from tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr rename to tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr index 1caeec84b22c..e600cc37fc42 100644 --- a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.e2021.stderr @@ -1,5 +1,5 @@ error: character literal may only contain one codepoint - --> $DIR/immediately-followed-by-lt.rs:11:4 + --> $DIR/immediately-followed-by-lt.rs:15:4 | LL | w!('r#long'id); | ^^^^^^^^ diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs index fe2b6de7bb3e..eb161f9c8556 100644 --- a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs @@ -1,4 +1,8 @@ -//@ edition: 2021 +//@ revisions: e2015 e2021 + +//@[e2021] edition: 2021 +//@[e2015] edition: 2015 +//@[e2015] check-pass // Make sure we reject the case where a raw lifetime is immediately followed by another // lifetime. This reserves a modest amount of space for changing lexing to, for example, @@ -9,6 +13,6 @@ macro_rules! w { } w!('r#long'id); -//~^ ERROR character literal may only contain one codepoint +//[e2021]~^ ERROR character literal may only contain one codepoint fn main() {} From dd2ac08cfefd66cf827b1ced863d98cc7f09d279 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 11:04:17 +0100 Subject: [PATCH 256/330] fix cargo path logic --- src/bootstrap/src/core/build_steps/test.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index f670452f4eff..4fa91c1a5714 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -305,9 +305,10 @@ impl Step for Cargo { // those features won't be able to land. cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1"); cargo.env("PATH", path_for_cargo(builder, compiler)); - // Cargo's test suite requires configurations from its own `.cargo/config.toml`. - // Change to the directory so Cargo can read from it. - cargo.current_dir(builder.src.join(Self::CRATE_PATH)); + // Cargo's test suite uses `CARGO_RUSTC_CURRENT_DIR` to determine the path that `file!` is + // relative to. Cargo no longer sets this env var, so we have to do that. This has to be the + // same value as `-Zroot-dir`. + cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string()); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( From b88478f7073bab189f05ff4fb4c486f3776fbafa Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 16 Oct 2024 16:24:43 +0200 Subject: [PATCH 257/330] Stabilize unsigned `num_midpoint` feature --- library/core/src/num/f128.rs | 5 ++--- library/core/src/num/f16.rs | 5 ++--- library/core/src/num/f32.rs | 20 ++++++++++---------- library/core/src/num/f64.rs | 6 +++--- library/core/src/num/mod.rs | 28 ++++++++++++++-------------- library/core/src/num/nonzero.rs | 5 ++--- library/core/tests/lib.rs | 2 +- 7 files changed, 34 insertions(+), 37 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index abeccb7eea24..4ebeaf046114 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -807,7 +807,6 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// #![feature(num_midpoint)] /// # // Using aarch64 because `reliable_f128_math` is needed /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] { /// @@ -817,8 +816,8 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - // #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f128) -> f128 { + #[rustc_const_unstable(feature = "f128", issue = "116909")] + pub const fn midpoint(self, other: f128) -> f128 { const LO: f128 = f128::MIN_POSITIVE * 2.; const HI: f128 = f128::MAX / 2.; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 0d3e92695707..5e1098c877f5 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -795,7 +795,6 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// #![feature(num_midpoint)] /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 /// /// assert_eq!(1f16.midpoint(4.0), 2.5); @@ -804,8 +803,8 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - // #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f16) -> f16 { + #[rustc_const_unstable(feature = "f128", issue = "116909")] + pub const fn midpoint(self, other: f16) -> f16 { const LO: f16 = f16::MIN_POSITIVE * 2.; const HI: f16 = f16::MAX / 2.; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 47dfce7530fb..4c0d95f95e56 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -984,27 +984,27 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] /// assert_eq!(1f32.midpoint(4.0), 2.5); /// assert_eq!((-5.5f32).midpoint(8.0), 1.25); /// ``` #[inline] - #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f32) -> f32 { + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + pub const fn midpoint(self, other: f32) -> f32 { cfg_if! { + // Allow faster implementation that have known good 64-bit float + // implementations. Falling back to the branchy code on targets that don't + // have 64-bit hardware floats or buggy implementations. + // https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 if #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", - all(any(target_arch="riscv32", target_arch= "riscv64"), target_feature="d"), - all(target_arch = "arm", target_feature="vfp2"), + all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "d"), + all(target_arch = "arm", target_feature = "vfp2"), target_arch = "wasm32", target_arch = "wasm64", ))] { - // whitelist the faster implementation to targets that have known good 64-bit float - // implementations. Falling back to the branchy code on targets that don't have - // 64-bit hardware floats or buggy implementations. - // see: https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 - ((f64::from(self) + f64::from(other)) / 2.0) as f32 + ((self as f64 + other as f64) / 2.0) as f32 } else { const LO: f32 = f32::MIN_POSITIVE * 2.; const HI: f32 = f32::MAX / 2.; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index c89023c1ae49..77ca56df0670 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1002,13 +1002,13 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] /// assert_eq!(1f64.midpoint(4.0), 2.5); /// assert_eq!((-5.5f64).midpoint(8.0), 1.25); /// ``` #[inline] - #[unstable(feature = "num_midpoint", issue = "110840")] - pub fn midpoint(self, other: f64) -> f64 { + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + pub const fn midpoint(self, other: f64) -> f64 { const LO: f64 = f64::MIN_POSITIVE * 2.; const HI: f64 = f64::MAX / 2.; diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 9d9897b9cf05..ce5ab108674e 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -103,18 +103,18 @@ macro_rules! midpoint_impl { ($SelfT:ty, unsigned) => { /// Calculates the middle point of `self` and `rhs`. /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large unsigned integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. /// /// # Examples /// /// ``` - /// #![feature(num_midpoint)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -134,14 +134,14 @@ macro_rules! midpoint_impl { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] + /// #![feature(num_midpoint_signed)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")] #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[unstable(feature = "num_midpoint_signed", issue = "110840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -157,18 +157,18 @@ macro_rules! midpoint_impl { ($SelfT:ty, $WideT:ty, unsigned) => { /// Calculates the middle point of `self` and `rhs`. /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. + /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a + /// sufficiently-large unsigned integral type. This implies that the result is + /// always rounded towards zero and that no overflow will ever occur. /// /// # Examples /// /// ``` - /// #![feature(num_midpoint)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -186,14 +186,14 @@ macro_rules! midpoint_impl { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] + /// #![feature(num_midpoint_signed)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")] #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")] #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[unstable(feature = "num_midpoint_signed", issue = "110840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index b883a0c2ec7f..1ca4a8783d65 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1509,8 +1509,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Examples /// /// ``` - /// #![feature(num_midpoint)] - /// /// # use std::num::NonZero; /// # /// # fn main() { test().unwrap(); } @@ -1524,7 +1522,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # Some(()) /// # } /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] + #[stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "num_midpoint", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index f7825571cd7a..61290868c5b0 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -66,7 +66,7 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(noop_waker)] -#![feature(num_midpoint)] +#![feature(num_midpoint_signed)] #![feature(numfmt)] #![feature(pattern)] #![feature(pointer_is_aligned_to)] From 20630c54aa416b6fc7282ac3555b45122a948d89 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 1 Dec 2024 20:21:58 +0300 Subject: [PATCH 258/330] add "profiler" option coverage for ci-rustc Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 68 ++++++++++++++++--------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index b0fbff79b901..cabd62dea9db 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2505,6 +2505,7 @@ impl Config { // Check the config compatibility // FIXME: this doesn't cover `--set` flags yet. let res = check_incompatible_options_for_ci_rustc( + self.build, current_config_toml, ci_config_toml, ); @@ -3086,17 +3087,18 @@ pub(crate) fn check_incompatible_options_for_ci_llvm( /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options. /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing. fn check_incompatible_options_for_ci_rustc( + host: TargetSelection, current_config_toml: TomlConfig, ci_config_toml: TomlConfig, ) -> Result<(), String> { macro_rules! err { - ($current:expr, $expected:expr) => { + ($current:expr, $expected:expr, $config_section:expr) => { if let Some(current) = &$current { if Some(current) != $expected.as_ref() { return Err(format!( - "ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \ + "ERROR: Setting `{}` is incompatible with `rust.download-rustc`. \ Current value: {:?}, Expected value(s): {}{:?}", - stringify!($expected).replace("_", "-"), + format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")), $current, if $expected.is_some() { "None/" } else { "" }, $expected, @@ -3107,13 +3109,13 @@ fn check_incompatible_options_for_ci_rustc( } macro_rules! warn { - ($current:expr, $expected:expr) => { + ($current:expr, $expected:expr, $config_section:expr) => { if let Some(current) = &$current { if Some(current) != $expected.as_ref() { println!( - "WARNING: `rust.{}` has no effect with `rust.download-rustc`. \ + "WARNING: `{}` has no effect with `rust.download-rustc`. \ Current value: {:?}, Expected value(s): {}{:?}", - stringify!($expected).replace("_", "-"), + format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")), $current, if $expected.is_some() { "None/" } else { "" }, $expected, @@ -3123,6 +3125,26 @@ fn check_incompatible_options_for_ci_rustc( }; } + err!( + current_config_toml.build.as_ref().and_then(|b| b.profiler), + ci_config_toml.build.as_ref().and_then(|b| b.profiler), + "build" + ); + + // We always build the in-tree compiler on cross targets, so we only care + // about the host target here. + let host_str = host.to_string(); + if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str)) { + if current_cfg.profiler.is_some() { + let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str)); + let ci_cfg = ci_target_toml.ok_or(format!( + "Target specific config for '{host_str}' is not present for CI-rustc" + ))?; + + err!(current_cfg.profiler, ci_cfg.profiler, "build"); + } + } + let (Some(current_rust_config), Some(ci_rust_config)) = (current_config_toml.rust, ci_config_toml.rust) else { @@ -3196,24 +3218,24 @@ fn check_incompatible_options_for_ci_rustc( // If the option belongs to the first category, we call `err` macro for a hard error; // otherwise, we just print a warning with `warn` macro. - err!(current_rust_config.optimize, optimize); - err!(current_rust_config.randomize_layout, randomize_layout); - err!(current_rust_config.debug_logging, debug_logging); - err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc); - err!(current_rust_config.rpath, rpath); - err!(current_rust_config.strip, strip); - err!(current_rust_config.lld_mode, lld_mode); - err!(current_rust_config.llvm_tools, llvm_tools); - err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker); - err!(current_rust_config.jemalloc, jemalloc); - err!(current_rust_config.default_linker, default_linker); - err!(current_rust_config.stack_protector, stack_protector); - err!(current_rust_config.lto, lto); - err!(current_rust_config.std_features, std_features); + err!(current_rust_config.optimize, optimize, "rust"); + err!(current_rust_config.randomize_layout, randomize_layout, "rust"); + err!(current_rust_config.debug_logging, debug_logging, "rust"); + err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc, "rust"); + err!(current_rust_config.rpath, rpath, "rust"); + err!(current_rust_config.strip, strip, "rust"); + err!(current_rust_config.lld_mode, lld_mode, "rust"); + err!(current_rust_config.llvm_tools, llvm_tools, "rust"); + err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker, "rust"); + err!(current_rust_config.jemalloc, jemalloc, "rust"); + err!(current_rust_config.default_linker, default_linker, "rust"); + err!(current_rust_config.stack_protector, stack_protector, "rust"); + err!(current_rust_config.lto, lto, "rust"); + err!(current_rust_config.std_features, std_features, "rust"); - warn!(current_rust_config.channel, channel); - warn!(current_rust_config.description, description); - warn!(current_rust_config.incremental, incremental); + warn!(current_rust_config.channel, channel, "rust"); + warn!(current_rust_config.description, description, "rust"); + warn!(current_rust_config.incremental, incremental, "rust"); Ok(()) } From 611a99188e86bdff0cb7c2e1806eff77fedc54b1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 19:33:23 +0100 Subject: [PATCH 259/330] fix safe-transmute handling of enums --- compiler/rustc_abi/src/lib.rs | 6 +- .../src/interpret/discriminant.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 + compiler/rustc_transmute/src/layout/tree.rs | 57 +++++++++---------- tests/crashes/126267.rs | 30 ---------- tests/ui/transmutability/uninhabited.rs | 16 ++++++ tests/ui/transmutability/uninhabited.stderr | 24 +++++++- 7 files changed, 74 insertions(+), 63 deletions(-) delete mode 100644 tests/crashes/126267.rs diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 7ae8b027e3e5..15a27c0b6ee0 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1505,7 +1505,11 @@ impl BackendRepr { #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub enum Variants { /// Single enum variants, structs/tuples, unions, and all non-ADTs. - Single { index: VariantIdx }, + Single { + /// Always 0 for non-enums/generators. + /// For enums without a variant, this is an invalid index! + index: VariantIdx, + }, /// Enum-likes with more than one variant: each variant comes with /// a *discriminant* (usually the same as the variant index but the user can diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index c7c8a2902e29..6faac1582ab8 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -70,7 +70,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if ty.is_enum() { // Hilariously, `Single` is used even for 0-variant enums. // (See https://github.com/rust-lang/rust/issues/89765). - if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) { + if ty.ty_adt_def().unwrap().variants().is_empty() { throw_ub!(UninhabitedEnumVariantRead(index)) } // For consistency with `write_discriminant`, and to make sure that diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0f2a6d598a0f..75cd0c0dd46c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1086,6 +1086,8 @@ rustc_queries! { } /// Computes the tag (if any) for a given type and variant. + /// `None` means that the variant doesn't need a tag (because it is niched). + /// Will panic for uninhabited variants. query tag_for_variant( key: (Ty<'tcx>, abi::VariantIdx) ) -> Option { diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index f19a567cd849..83463babc4f4 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -319,38 +319,35 @@ pub(crate) mod rustc { ) -> Result { assert!(def.is_enum()); - // Computes the variant of a given index. - let layout_of_variant = |index, encoding: Option>| { - let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index)); - let variant_def = Def::Variant(def.variant(index)); - let variant_layout = ty_variant(cx, (ty, layout), index); - Self::from_variant( - variant_def, - tag.map(|tag| (tag, index, encoding.unwrap())), - (ty, variant_layout), - layout.size, - cx, - ) - }; + // Computes the layout of a variant. + let layout_of_variant = + |index, encoding: Option>| -> Result { + let variant_layout = ty_variant(cx, (ty, layout), index); + if variant_layout.is_uninhabited() { + return Ok(Self::uninhabited()); + } + let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index)); + let variant_def = Def::Variant(def.variant(index)); + Self::from_variant( + variant_def, + tag.map(|tag| (tag, index, encoding.unwrap())), + (ty, variant_layout), + layout.size, + cx, + ) + }; - // We consider three kinds of enums, each demanding a different - // treatment of their layout computation: - // 1. enums that are uninhabited ZSTs - // 2. enums that delegate their layout to a variant - // 3. enums with multiple variants match layout.variants() { - Variants::Single { .. } if layout.is_uninhabited() && layout.size == Size::ZERO => { - // The layout representation of uninhabited, ZST enums is - // defined to be like that of the `!` type, as opposed of a - // typical enum. Consequently, they cannot be descended into - // as if they typical enums. We therefore special-case this - // scenario and simply return an uninhabited `Tree`. - Ok(Self::uninhabited()) - } Variants::Single { index } => { - // `Variants::Single` on enums with variants denotes that - // the enum delegates its layout to the variant at `index`. - layout_of_variant(*index, None) + // Hilariously, `Single` is used even for 0-variant enums; + // `index` is just junk in that case. + if ty.ty_adt_def().unwrap().variants().is_empty() { + Ok(Self::uninhabited()) + } else { + // `Variants::Single` on enums with variants denotes that + // the enum delegates its layout to the variant at `index`. + layout_of_variant(*index, None) + } } Variants::Multiple { tag, tag_encoding, tag_field, .. } => { // `Variants::Multiple` denotes an enum with multiple @@ -369,7 +366,7 @@ pub(crate) mod rustc { }, )?; - return Ok(Self::def(Def::Adt(def)).then(variants)); + Ok(Self::def(Def::Adt(def)).then(variants)) } } } diff --git a/tests/crashes/126267.rs b/tests/crashes/126267.rs deleted file mode 100644 index 728578179ed3..000000000000 --- a/tests/crashes/126267.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ known-bug: rust-lang/rust#126267 - -#![feature(transmutability)] -#![crate_type = "lib"] - -pub enum ApiError {} -pub struct TokioError { - b: bool, -} -pub enum Error { - Api { source: ApiError }, - Ethereum, - Tokio { source: TokioError }, -} - -mod assert { - use std::mem::TransmuteFrom; - - pub fn is_transmutable() - where - Dst: TransmuteFrom, // safety is NOT assumed - { - } -} - -fn test() { - struct Src; - type Dst = Error; - assert::is_transmutable::(); -} diff --git a/tests/ui/transmutability/uninhabited.rs b/tests/ui/transmutability/uninhabited.rs index 74f7a1a2e898..274104ffb391 100644 --- a/tests/ui/transmutability/uninhabited.rs +++ b/tests/ui/transmutability/uninhabited.rs @@ -91,3 +91,19 @@ fn distant_void() { assert::is_maybe_transmutable::(); assert::is_maybe_transmutable::(); //~ ERROR: cannot be safely transmuted } + +fn issue_126267() { + pub enum ApiError {} + pub struct TokioError { + b: bool, + } + pub enum Error { + Api { source: ApiError }, // this variant is uninhabited + Ethereum, + Tokio { source: TokioError }, + } + + struct Src; + type Dst = Error; + assert::is_maybe_transmutable::(); //~ERROR: cannot be safely transmuted +} diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index 3fa02f0867cc..f112d2fbe44f 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -110,7 +110,29 @@ LL | | } LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` -error: aborting due to 7 previous errors +error[E0277]: `Src` cannot be safely transmuted into `issue_126267::Error` + --> $DIR/uninhabited.rs:108:42 + | +LL | assert::is_maybe_transmutable::(); + | ^^^ the size of `Src` is smaller than the size of `issue_126267::Error` + | +note: required by a bound in `is_maybe_transmutable` + --> $DIR/uninhabited.rs:10:14 + | +LL | pub fn is_maybe_transmutable() + | --------------------- required by a bound in this function +LL | where +LL | Dst: TransmuteFrom + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0080, E0277. For more information about an error, try `rustc --explain E0080`. From a17294dc0fe106f0a8f12f8bc61ab17eacf251ef Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 14:47:10 +0100 Subject: [PATCH 260/330] fix ICE when promoted has layout size overflow --- .../rustc_const_eval/src/const_eval/error.rs | 17 ++++-- .../src/interpret/eval_context.rs | 11 ++-- .../rustc_middle/src/mir/interpret/error.rs | 26 +++----- tests/crashes/125476.rs | 4 -- .../unevaluated-const-ice-119731.stderr | 14 +++++ tests/ui/consts/const-integer-bool-ops.stderr | 60 +++++++++++++++++++ .../consts/const-mut-refs/issue-76510.stderr | 6 ++ tests/ui/consts/const-tup-index-span.stderr | 6 ++ tests/ui/consts/issue-54954.stderr | 18 ++++++ .../consts/missing_assoc_const_type2.stderr | 6 ++ ..._running_out_of_memory_issue-130687.stderr | 6 -- tests/ui/consts/promoted_size_overflow.rs | 7 +++ tests/ui/consts/promoted_size_overflow.stderr | 9 +++ .../consts/uninhabited-const-issue-61744.rs | 6 +- .../uninhabited-const-issue-61744.stderr | 14 ----- tests/ui/enum-discriminant/issue-41394.stderr | 6 ++ .../ctfe-id-unlimited.return.stderr | 6 -- .../base-layout-is-sized-ice-123078.stderr | 6 ++ tests/ui/limits/issue-55878.stderr | 17 ------ ...om-outer-item-in-const-item.default.stderr | 14 +++++ ...m-in-const-item.generic_const_items.stderr | 14 +++++ tests/ui/resolve/issue-50599.stderr | 6 ++ .../avoid-invalid-mir.stderr | 6 ++ ...bitrary-self-from-method-substs-ice.stderr | 6 ++ .../type-dependent-def-issue-49241.stderr | 6 ++ 25 files changed, 218 insertions(+), 79 deletions(-) delete mode 100644 tests/crashes/125476.rs create mode 100644 tests/ui/consts/promoted_size_overflow.rs create mode 100644 tests/ui/consts/promoted_size_overflow.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 1271d9d2d0da..3cb77d1dcb5c 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -139,12 +139,14 @@ where match error { // Don't emit a new diagnostic for these errors, they are already reported elsewhere or // should remain silent. + err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span), err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { ErrorHandled::TooGeneric(span) } - err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span), err_inval!(Layout(LayoutError::ReferencesError(guar))) => { - ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span) + // This can occur in infallible promoteds e.g. when a non-existent type or field is + // encountered. + ErrorHandled::Reported(ReportedErrorInfo::allowed_in_infallible(guar), span) } // Report remaining errors. _ => { @@ -152,7 +154,12 @@ where let span = span.substitute_dummy(our_span); let err = mk(span, frames); let mut err = tcx.dcx().create_err(err); - let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_)); + // We allow invalid programs in infallible promoteds since invalid layouts can occur + // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time. + let allowed_in_infallible = matches!( + error, + InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_) + ); let msg = error.diagnostic_message(); error.add_args(&mut err); @@ -160,8 +167,8 @@ where // Use *our* span to label the interp error err.span_label(our_span, msg); let g = err.emit(); - let reported = if can_be_spurious { - ReportedErrorInfo::spurious(g) + let reported = if allowed_in_infallible { + ReportedErrorInfo::allowed_in_infallible(g) } else { ReportedErrorInfo::from(g) }; diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index fe93a48c2f2c..241be5e175cd 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // do not continue if typeck errors occurred (can only occur in local crate) if let Some(err) = body.tainted_by_errors { - throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err))); + throw_inval!(AlreadyReported(ReportedErrorInfo::from(err))); } interp_ok(body) } @@ -585,13 +585,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { match err { ErrorHandled::TooGeneric(..) => {}, ErrorHandled::Reported(reported, span) => { - if reported.is_tainted_by_errors() { - // const-eval will return "tainted" errors if e.g. the layout cannot - // be computed as the type references non-existing names. - // See . - } else if reported.can_be_spurious() { + if reported.is_allowed_in_infallible() { // These errors can just sometimes happen, even when the expression - // is nominally "infallible", e.g. when running out of memory. + // is nominally "infallible", e.g. when running out of memory + // or when some layout could not be computed. } else { // Looks like the const is not captured by `required_consts`, that's bad. span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts"); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 08afa33c6b43..ad5d678178de 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -46,7 +46,7 @@ impl ErrorHandled { pub fn emit_note(&self, tcx: TyCtxt<'_>) { match self { &ErrorHandled::Reported(err, span) => { - if !err.is_tainted_by_errors && !span.is_dummy() { + if !err.allowed_in_infallible && !span.is_dummy() { tcx.dcx().emit_note(error::ErroneousConstant { span }); } } @@ -58,34 +58,26 @@ impl ErrorHandled { #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub struct ReportedErrorInfo { error: ErrorGuaranteed, - is_tainted_by_errors: bool, - /// Whether this is the kind of error that can sometimes occur, and sometimes not. - /// Used for resource exhaustion errors. - can_be_spurious: bool, + /// Whether this error is allowed to show up even in otherwise "infallible" promoteds. + /// This is for things like overflows during size computation or resource exhaustion. + allowed_in_infallible: bool, } impl ReportedErrorInfo { #[inline] - pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error } - } - #[inline] - pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error } + pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo { + ReportedErrorInfo { allowed_in_infallible: true, error } } - pub fn is_tainted_by_errors(&self) -> bool { - self.is_tainted_by_errors - } - pub fn can_be_spurious(&self) -> bool { - self.can_be_spurious + pub fn is_allowed_in_infallible(&self) -> bool { + self.allowed_in_infallible } } impl From for ReportedErrorInfo { #[inline] fn from(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error } + ReportedErrorInfo { allowed_in_infallible: false, error } } } diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs deleted file mode 100644 index ad739639b722..000000000000 --- a/tests/crashes/125476.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: rust-lang/rust#125476 -//@ only-x86_64 -pub struct Data([u8; usize::MAX >> 2]); -const _: &'static [Data] = &[]; diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 30a45ce377e7..4eb374b20204 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -72,6 +72,20 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | +note: erroneous constant encountered + --> $DIR/unevaluated-const-ice-119731.rs:22:19 + | +LL | impl v17<512, v0> { + | ^^ + +note: erroneous constant encountered + --> $DIR/unevaluated-const-ice-119731.rs:22:19 + | +LL | impl v17<512, v0> { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:28:37 | diff --git a/tests/ui/consts/const-integer-bool-ops.stderr b/tests/ui/consts/const-integer-bool-ops.stderr index 4e503e5a5c0a..d58a8e93ff6f 100644 --- a/tests/ui/consts/const-integer-bool-ops.stderr +++ b/tests/ui/consts/const-integer-bool-ops.stderr @@ -16,6 +16,12 @@ error[E0308]: mismatched types LL | const X: usize = 42 && 39; | ^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:8:18 + | +LL | const ARR: [i32; X] = [99; 34]; + | ^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:10:19 | @@ -34,6 +40,12 @@ error[E0308]: mismatched types LL | const X1: usize = 42 || 39; | ^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:17:19 + | +LL | const ARR1: [i32; X1] = [99; 47]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:19:19 | @@ -52,6 +64,12 @@ error[E0308]: mismatched types LL | const X2: usize = -42 || -39; | ^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:26:19 + | +LL | const ARR2: [i32; X2] = [99; 18446744073709551607]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:28:19 | @@ -70,42 +88,84 @@ error[E0308]: mismatched types LL | const X3: usize = -42 && -39; | ^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:35:19 + | +LL | const ARR3: [i32; X3] = [99; 6]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:37:18 | LL | const Y: usize = 42.0 == 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:40:19 + | +LL | const ARRR: [i32; Y] = [99; 1]; + | ^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:42:19 | LL | const Y1: usize = 42.0 >= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:45:20 + | +LL | const ARRR1: [i32; Y1] = [99; 1]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:47:19 | LL | const Y2: usize = 42.0 <= 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:50:20 + | +LL | const ARRR2: [i32; Y2] = [99; 1]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:52:19 | LL | const Y3: usize = 42.0 > 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:55:20 + | +LL | const ARRR3: [i32; Y3] = [99; 0]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:57:19 | LL | const Y4: usize = 42.0 < 42.0; | ^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:60:20 + | +LL | const ARRR4: [i32; Y4] = [99; 0]; + | ^^ + error[E0308]: mismatched types --> $DIR/const-integer-bool-ops.rs:62:19 | LL | const Y5: usize = 42.0 != 42.0; | ^^^^^^^^^^^^ expected `usize`, found `bool` +note: erroneous constant encountered + --> $DIR/const-integer-bool-ops.rs:65:20 + | +LL | const ARRR5: [i32; Y5] = [99; 0]; + | ^^ + error: aborting due to 18 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.stderr b/tests/ui/consts/const-mut-refs/issue-76510.stderr index aff86e83578d..a63be676fdab 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.stderr +++ b/tests/ui/consts/const-mut-refs/issue-76510.stderr @@ -4,6 +4,12 @@ error[E0764]: mutable references are not allowed in the final value of constants LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ +note: erroneous constant encountered + --> $DIR/issue-76510.rs:7:70 + | +LL | let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + | ^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0764`. diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr index 792e18aa8fd4..2a3f0cfb06df 100644 --- a/tests/ui/consts/const-tup-index-span.stderr +++ b/tests/ui/consts/const-tup-index-span.stderr @@ -11,6 +11,12 @@ help: use a trailing comma to create a tuple with one element LL | const TUP: (usize,) = (5usize << 64,); | + ++ +note: erroneous constant encountered + --> $DIR/const-tup-index-span.rs:6:18 + | +LL | const ARR: [i32; TUP.0] = []; + | ^^^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr index b8c983eb7b81..ed6aa9c44a3d 100644 --- a/tests/ui/consts/issue-54954.stderr +++ b/tests/ui/consts/issue-54954.stderr @@ -19,6 +19,24 @@ LL | | core::mem::size_of::() LL | | } | |_____- `Tt::const_val` defined here +note: erroneous constant encountered + --> $DIR/issue-54954.rs:11:15 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-54954.rs:11:34 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-54954.rs:16:22 + | +LL | let _ = f([1f32; ARR_LEN]); + | ^^^^^^^ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0379, E0790. diff --git a/tests/ui/consts/missing_assoc_const_type2.stderr b/tests/ui/consts/missing_assoc_const_type2.stderr index 1255ca2d102b..3279a077464b 100644 --- a/tests/ui/consts/missing_assoc_const_type2.stderr +++ b/tests/ui/consts/missing_assoc_const_type2.stderr @@ -4,5 +4,11 @@ error: missing type for `const` item LL | const FIRST: = 10; | ^ help: provide a type for the associated constant: `u8` +note: erroneous constant encountered + --> $DIR/missing_assoc_const_type2.rs:18:5 + | +LL | TwoDigits::FIRST as usize + | ^^^^^^^^^^^^^^^^ + error: aborting due to 1 previous error diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr index 50e920f05f93..f5d767efceb7 100644 --- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr +++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr @@ -4,12 +4,6 @@ error[E0080]: evaluation of constant value failed LL | const _: &'static Data = &Data([0; (1 << 47) - 1]); | ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler -note: erroneous constant encountered - --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:26 - | -LL | const _: &'static Data = &Data([0; (1 << 47) - 1]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/promoted_size_overflow.rs b/tests/ui/consts/promoted_size_overflow.rs new file mode 100644 index 000000000000..3d606905e782 --- /dev/null +++ b/tests/ui/consts/promoted_size_overflow.rs @@ -0,0 +1,7 @@ +//@ only-64bit +pub struct Data([u8; usize::MAX >> 2]); +const _: &'static [Data] = &[]; +//~^ERROR: evaluation of constant value failed +//~| too big for the target architecture + +fn main() {} diff --git a/tests/ui/consts/promoted_size_overflow.stderr b/tests/ui/consts/promoted_size_overflow.stderr new file mode 100644 index 000000000000..cfb8260bed04 --- /dev/null +++ b/tests/ui/consts/promoted_size_overflow.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/promoted_size_overflow.rs:3:29 + | +LL | const _: &'static [Data] = &[]; + | ^^ values of the type `[u8; 4611686018427387903]` are too big for the target architecture + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/uninhabited-const-issue-61744.rs b/tests/ui/consts/uninhabited-const-issue-61744.rs index 6168268bfedc..19ee842c36bf 100644 --- a/tests/ui/consts/uninhabited-const-issue-61744.rs +++ b/tests/ui/consts/uninhabited-const-issue-61744.rs @@ -5,15 +5,15 @@ pub const unsafe fn fake_type() -> T { } pub const unsafe fn hint_unreachable() -> ! { - fake_type() + fake_type() //~ inside } trait Const { - const CONSTANT: i32 = unsafe { fake_type() }; + const CONSTANT: i32 = unsafe { fake_type() }; //~ inside } impl Const for T {} pub fn main() -> () { - dbg!(i32::CONSTANT); //~ constant + dbg!(i32::CONSTANT); } diff --git a/tests/ui/consts/uninhabited-const-issue-61744.stderr b/tests/ui/consts/uninhabited-const-issue-61744.stderr index c6dd11ee5db9..7575ad730b30 100644 --- a/tests/ui/consts/uninhabited-const-issue-61744.stderr +++ b/tests/ui/consts/uninhabited-const-issue-61744.stderr @@ -645,20 +645,6 @@ note: inside `::CONSTANT` LL | const CONSTANT: i32 = unsafe { fake_type() }; | ^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/uninhabited-const-issue-61744.rs:18:10 - | -LL | dbg!(i32::CONSTANT); - | ^^^^^^^^^^^^^ - -note: erroneous constant encountered - --> $DIR/uninhabited-const-issue-61744.rs:18:10 - | -LL | dbg!(i32::CONSTANT); - | ^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/enum-discriminant/issue-41394.stderr b/tests/ui/enum-discriminant/issue-41394.stderr index e81562df04f5..9bf4fc79b1b0 100644 --- a/tests/ui/enum-discriminant/issue-41394.stderr +++ b/tests/ui/enum-discriminant/issue-41394.stderr @@ -6,6 +6,12 @@ LL | A = "" + 1 | | | &str +note: erroneous constant encountered + --> $DIR/issue-41394.rs:7:9 + | +LL | A = Foo::A as isize + | ^^^^^^^^^^^^^^^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr index 4a1e50b4111e..46769cdea8a7 100644 --- a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr +++ b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.return.stderr @@ -25,12 +25,6 @@ note: inside `ID_ED` LL | const ID_ED: u32 = rec_id(ORIGINAL); | ^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/ctfe-id-unlimited.rs:31:40 - | -LL | const ASSERT: () = assert!(ORIGINAL == ID_ED); - | ^^^^^ - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr index 455bd2cbf8b6..ee7f5162552d 100644 --- a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr +++ b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr @@ -25,6 +25,12 @@ LL | const C: S = unsafe { std::mem::transmute(()) }; = note: source type: `()` (0 bits) = note: target type: `S` (size can vary because of [u8]) +note: erroneous constant encountered + --> $DIR/base-layout-is-sized-ice-123078.rs:13:5 + | +LL | C; + | ^ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0277, E0512. diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index 0a5f17be8047..51c4837f4583 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -11,23 +11,6 @@ note: inside `main` LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: erroneous constant encountered - --> $DIR/issue-55878.rs:7:26 - | -LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) - -note: erroneous constant encountered - --> $DIR/issue-55878.rs:7:26 - | -LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index fbb9ede8aa17..c7e9df10d41c 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -29,6 +29,20 @@ LL | const _: u32 = T::C; | = note: a `const` is a separate item from the item that contains it +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 60aa94038c3a..64c436d3cebc 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -35,6 +35,20 @@ LL | const _: u32 = T::C; | = note: a `const` is a separate item from the item that contains it +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + +note: erroneous constant encountered + --> $DIR/generic-params-from-outer-item-in-const-item.rs:22:9 + | +LL | I + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr index 24fb3d580b8f..427dc9f20491 100644 --- a/tests/ui/resolve/issue-50599.stderr +++ b/tests/ui/resolve/issue-50599.stderr @@ -20,6 +20,12 @@ LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; LL + const M: usize = (f64::from(N) * LOG10_2) as usize; | +note: erroneous constant encountered + --> $DIR/issue-50599.rs:4:29 + | +LL | let mut digits = [0u32; M]; + | ^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr index 606f808f0936..eab2604d4c0c 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/avoid-invalid-mir.stderr @@ -6,5 +6,11 @@ LL | !let y = 42; | = note: only supported directly in conditions of `if` and `while` expressions +note: erroneous constant encountered + --> $DIR/avoid-invalid-mir.rs:11:13 + | +LL | x: [(); N] + | ^ + error: aborting due to 1 previous error diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr index cf4c219215e0..e4991823d28a 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr @@ -17,6 +17,12 @@ LL | const fn get>(self: R) -> u32 { LL | } | - value is dropped here +note: erroneous constant encountered + --> $DIR/arbitrary-self-from-method-substs-ice.rs:24:5 + | +LL | FOO; + | ^^^ + error[E0801]: invalid generic `self` parameter type: `R` --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49 | diff --git a/tests/ui/type/type-dependent-def-issue-49241.stderr b/tests/ui/type/type-dependent-def-issue-49241.stderr index cf372dc59681..4e55618e5cb1 100644 --- a/tests/ui/type/type-dependent-def-issue-49241.stderr +++ b/tests/ui/type/type-dependent-def-issue-49241.stderr @@ -9,6 +9,12 @@ help: consider using `let` instead of `const` LL | let l: usize = v.count(); | ~~~ +note: erroneous constant encountered + --> $DIR/type-dependent-def-issue-49241.rs:4:18 + | +LL | let s: [u32; l] = v.into_iter().collect(); + | ^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0435`. From 85e476556b5c3622ef5356f31b724d2c2b5d2a1d Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 29 Nov 2024 18:04:36 +0100 Subject: [PATCH 261/330] Add specific test for check-cfg "and X more" diagnostic --- tests/ui/check-cfg/and-more-diagnostic.rs | 13 +++++++++++++ tests/ui/check-cfg/and-more-diagnostic.stderr | 12 ++++++++++++ tests/ui/check-cfg/mix.rs | 2 -- tests/ui/check-cfg/mix.stderr | 11 +---------- 4 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 tests/ui/check-cfg/and-more-diagnostic.rs create mode 100644 tests/ui/check-cfg/and-more-diagnostic.stderr diff --git a/tests/ui/check-cfg/and-more-diagnostic.rs b/tests/ui/check-cfg/and-more-diagnostic.rs new file mode 100644 index 000000000000..82867f3b4354 --- /dev/null +++ b/tests/ui/check-cfg/and-more-diagnostic.rs @@ -0,0 +1,13 @@ +// This test makes sure that we don't emit a long list of possible values +// but that we stop at a fix point and say "and X more". +// +//@ check-pass +//@ no-auto-check-cfg +//@ compile-flags: --check-cfg=cfg() +//@ normalize-stderr-test: "and \d+ more" -> "and X more" +//@ normalize-stderr-test: "`[a-zA-Z0-9_-]+`" -> "`xxx`" + +fn main() { + cfg!(target_feature = "zebra"); + //~^ WARNING unexpected `cfg` condition value +} diff --git a/tests/ui/check-cfg/and-more-diagnostic.stderr b/tests/ui/check-cfg/and-more-diagnostic.stderr new file mode 100644 index 000000000000..2ac80c84c37d --- /dev/null +++ b/tests/ui/check-cfg/and-more-diagnostic.stderr @@ -0,0 +1,12 @@ +warning: unexpected `xxx` condition value: `xxx` + --> $DIR/and-more-diagnostic.rs:11:10 + | +LL | cfg!(target_feature = "zebra"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `xxx` are: `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, `xxx`, and `xxx` and X more + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs index ac244f4fc09d..e9a2de2f6728 100644 --- a/tests/ui/check-cfg/mix.rs +++ b/tests/ui/check-cfg/mix.rs @@ -75,8 +75,6 @@ fn test_cfg_macro() { //~^ WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value //~| WARNING unexpected `cfg` condition value - cfg!(target_feature = "zebra"); - //~^ WARNING unexpected `cfg` condition value } fn main() {} diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 32eb01c7018b..231236799c69 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -245,14 +245,5 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra")); = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))` = note: see for more information about checking conditional configuration -warning: unexpected `cfg` condition value: `zebra` - --> $DIR/mix.rs:78:10 - | -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`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 252 more - = note: see for more information about checking conditional configuration - -warning: 27 warnings emitted +warning: 26 warnings emitted From 1c4657d3cd1cef28dfd89d8f3a3e1970487d2ee0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 1 Dec 2024 18:18:19 +0100 Subject: [PATCH 262/330] compiletest: un-escape new-line in normalize replacement string --- src/tools/compiletest/src/header.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fe4c5fdd8b51..0a54f17725e2 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1135,6 +1135,8 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> { .captures(header)?; let regex = captures["regex"].to_owned(); let replacement = captures["replacement"].to_owned(); + // FIXME: Support escaped new-line in strings. + let replacement = replacement.replace("\\n", "\n"); Some((regex, replacement)) } From 77b2fe19443ea44fabc3b4221b429165d4137804 Mon Sep 17 00:00:00 2001 From: cod10129 <110200933+cod10129@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:54:04 -0600 Subject: [PATCH 263/330] add isatty alias for is_terminal --- library/std/src/io/stdio.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 35b38ed783ff..318c35082216 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1200,6 +1200,7 @@ pub trait IsTerminal: crate::sealed::Sealed { /// /// [changes]: io#platform-specific-behavior /// [`Stdin`]: crate::io::Stdin + #[doc(alias = "isatty")] #[stable(feature = "is_terminal", since = "1.70.0")] fn is_terminal(&self) -> bool; } From 8047340599763eeca43a0dcee1b1f6b65b6d4ecd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 21 Nov 2024 15:16:36 +0100 Subject: [PATCH 264/330] Stop cloning `Context` so much --- src/librustdoc/formats/renderer.rs | 70 +++++++------ src/librustdoc/html/markdown.rs | 113 ++++++++++++--------- src/librustdoc/html/render/context.rs | 75 ++++++++------ src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/render/write_shared.rs | 2 +- src/librustdoc/html/sources.rs | 4 +- src/librustdoc/json/mod.rs | 6 +- 7 files changed, 153 insertions(+), 119 deletions(-) diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index edd7d56b1798..f7ba5bff51bf 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,5 +1,5 @@ +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_middle::ty::TyCtxt; -use tracing::debug; use crate::clean; use crate::config::RenderOptions; @@ -17,6 +17,7 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { /// /// This is true for html, and false for json. See #80664 const RUN_ON_MODULE: bool; + type InfoType; /// Sets up any state required for the renderer. When this is called the cache has already been /// populated. @@ -28,7 +29,8 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { ) -> Result<(Self, clean::Crate), Error>; /// Make a new renderer to render a child of the item currently being rendered. - fn make_child_renderer(&self) -> Self; + fn make_child_renderer(&mut self) -> Self::InfoType; + fn set_back_info(&mut self, _info: Self::InfoType); /// Renders a single non-module item. This means no recursive sub-item rendering is required. fn item(&mut self, item: clean::Item) -> Result<(), Error>; @@ -47,6 +49,40 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { fn cache(&self) -> &Cache; } +fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>( + cx: &mut T, + item: clean::Item, + prof: &SelfProfilerRef, +) -> Result<(), Error> { + if item.is_mod() && T::RUN_ON_MODULE { + // modules are special because they add a namespace. We also need to + // recurse into the items of the module as well. + let _timer = + prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); + + cx.mod_item_in(&item)?; + let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = + item.inner.kind + else { + unreachable!() + }; + for it in module.items { + let info = cx.make_child_renderer(); + run_format_inner(cx, it, prof)?; + cx.set_back_info(info); + } + + cx.mod_item_out()?; + // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special + // cases. Use an explicit match instead. + } else if let Some(item_name) = item.name + && !item.is_extern_crate() + { + prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?; + } + Ok(()) +} + /// Main method for rendering a crate. pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( krate: clean::Crate, @@ -66,36 +102,8 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( } // Render the crate documentation - let mut work = vec![(format_renderer.make_child_renderer(), krate.module)]; + run_format_inner(&mut format_renderer, krate.module, prof)?; - while let Some((mut cx, item)) = work.pop() { - if item.is_mod() && T::RUN_ON_MODULE { - // modules are special because they add a namespace. We also need to - // recurse into the items of the module as well. - let _timer = - prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string()); - - cx.mod_item_in(&item)?; - let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = - item.inner.kind - else { - unreachable!() - }; - for it in module.items { - debug!("Adding {:?} to worklist", it.name); - work.push((cx.make_child_renderer(), it)); - } - - cx.mod_item_out()?; - // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special - // cases. Use an explicit match instead. - } else if let Some(item_name) = item.name - && !item.is_extern_crate() - { - prof.generic_activity_with_arg("render_item", item_name.as_str()) - .run(|| cx.item(item))?; - } - } prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr()) .run(|| format_renderer.after_krate()) } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b6829d5457ba..0f210270f788 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -37,7 +37,7 @@ use std::sync::OnceLock; use pulldown_cmark::{ BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, }; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Diag, DiagMessage}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; @@ -1887,65 +1887,74 @@ pub struct IdMap { } // The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly. -static DEFAULT_ID_MAP: OnceLock, usize>> = OnceLock::new(); +static DEFAULT_ID_MAP: OnceLock>> = OnceLock::new(); -fn init_id_map() -> FxHashMap, usize> { - let mut map = FxHashMap::default(); +fn init_id_map() -> FxHashSet> { + let mut map = FxHashSet::default(); // This is the list of IDs used in JavaScript. - map.insert("help".into(), 1); - map.insert("settings".into(), 1); - map.insert("not-displayed".into(), 1); - map.insert("alternative-display".into(), 1); - map.insert("search".into(), 1); - map.insert("crate-search".into(), 1); - map.insert("crate-search-div".into(), 1); + map.insert("help".into()); + map.insert("settings".into()); + map.insert("not-displayed".into()); + map.insert("alternative-display".into()); + map.insert("search".into()); + map.insert("crate-search".into()); + map.insert("crate-search-div".into()); // This is the list of IDs used in HTML generated in Rust (including the ones // used in tera template files). - map.insert("themeStyle".into(), 1); - map.insert("settings-menu".into(), 1); - map.insert("help-button".into(), 1); - map.insert("sidebar-button".into(), 1); - map.insert("main-content".into(), 1); - map.insert("toggle-all-docs".into(), 1); - map.insert("all-types".into(), 1); - map.insert("default-settings".into(), 1); - map.insert("sidebar-vars".into(), 1); - map.insert("copy-path".into(), 1); - map.insert("rustdoc-toc".into(), 1); - map.insert("rustdoc-modnav".into(), 1); + map.insert("themeStyle".into()); + map.insert("settings-menu".into()); + map.insert("help-button".into()); + map.insert("sidebar-button".into()); + map.insert("main-content".into()); + map.insert("toggle-all-docs".into()); + map.insert("all-types".into()); + map.insert("default-settings".into()); + map.insert("sidebar-vars".into()); + map.insert("copy-path".into()); + map.insert("rustdoc-toc".into()); + map.insert("rustdoc-modnav".into()); // This is the list of IDs used by rustdoc sections (but still generated by // rustdoc). - map.insert("fields".into(), 1); - map.insert("variants".into(), 1); - map.insert("implementors-list".into(), 1); - map.insert("synthetic-implementors-list".into(), 1); - map.insert("foreign-impls".into(), 1); - map.insert("implementations".into(), 1); - map.insert("trait-implementations".into(), 1); - map.insert("synthetic-implementations".into(), 1); - map.insert("blanket-implementations".into(), 1); - map.insert("required-associated-types".into(), 1); - map.insert("provided-associated-types".into(), 1); - map.insert("provided-associated-consts".into(), 1); - map.insert("required-associated-consts".into(), 1); - map.insert("required-methods".into(), 1); - map.insert("provided-methods".into(), 1); - map.insert("dyn-compatibility".into(), 1); - map.insert("implementors".into(), 1); - map.insert("synthetic-implementors".into(), 1); - map.insert("implementations-list".into(), 1); - map.insert("trait-implementations-list".into(), 1); - map.insert("synthetic-implementations-list".into(), 1); - map.insert("blanket-implementations-list".into(), 1); - map.insert("deref-methods".into(), 1); - map.insert("layout".into(), 1); - map.insert("aliased-type".into(), 1); + map.insert("fields".into()); + map.insert("variants".into()); + map.insert("implementors-list".into()); + map.insert("synthetic-implementors-list".into()); + map.insert("foreign-impls".into()); + map.insert("implementations".into()); + map.insert("trait-implementations".into()); + map.insert("synthetic-implementations".into()); + map.insert("blanket-implementations".into()); + map.insert("required-associated-types".into()); + map.insert("provided-associated-types".into()); + map.insert("provided-associated-consts".into()); + map.insert("required-associated-consts".into()); + map.insert("required-methods".into()); + map.insert("provided-methods".into()); + map.insert("dyn-compatibility".into()); + map.insert("implementors".into()); + map.insert("synthetic-implementors".into()); + map.insert("implementations-list".into()); + map.insert("trait-implementations-list".into()); + map.insert("synthetic-implementations-list".into()); + map.insert("blanket-implementations-list".into()); + map.insert("deref-methods".into()); + map.insert("layout".into()); + map.insert("aliased-type".into()); map } impl IdMap { pub fn new() -> Self { - IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 } + let mut id_map = IdMap { map: FxHashMap::default(), existing_footnotes: 0 }; + id_map.init_map(); + id_map + } + + #[allow(rustc::potential_query_instability)] + fn init_map(&mut self) { + for key in DEFAULT_ID_MAP.get_or_init(init_id_map).iter() { + self.map.insert(key.clone(), 1); + } } pub(crate) fn derive + ToString>(&mut self, candidate: S) -> String { @@ -1970,4 +1979,10 @@ impl IdMap { closure(self, &mut existing_footnotes); self.existing_footnotes = existing_footnotes; } + + pub(crate) fn clear(&mut self) { + self.map.clear(); + self.init_map(); + self.existing_footnotes = 0; + } } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 3a8144621747..0b87c1bb62ca 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -49,10 +49,6 @@ pub(crate) struct Context<'tcx> { /// The current destination folder of where HTML artifacts should be placed. /// This changes as the context descends into the module hierarchy. pub(crate) dst: PathBuf, - /// A flag, which when `true`, will render pages which redirect to the - /// real location of an item. This is used to allow external links to - /// publicly reused items to redirect to the right location. - pub(super) render_redirect_pages: bool, /// Tracks section IDs for `Deref` targets so they match in both the main /// body and the sidebar. pub(super) deref_id_map: DefIdMap, @@ -64,16 +60,33 @@ pub(crate) struct Context<'tcx> { /// /// [#82381]: https://github.com/rust-lang/rust/issues/82381 pub(crate) shared: Rc>, + /// Collection of all types with notable traits referenced in the current module. + pub(crate) types_with_notable_traits: FxIndexSet, + /// Contains information that needs to be saved and reset after rendering an item which is + /// not a module. + pub(crate) info: ContextInfo, +} + +#[derive(Clone, Copy)] +pub(crate) struct ContextInfo { + /// A flag, which when `true`, will render pages which redirect to the + /// real location of an item. This is used to allow external links to + /// publicly reused items to redirect to the right location. + pub(super) render_redirect_pages: bool, /// This flag indicates whether source links should be generated or not. If /// the source files are present in the html rendering, then this will be /// `true`. pub(crate) include_sources: bool, - /// Collection of all types with notable traits referenced in the current module. - pub(crate) types_with_notable_traits: FxIndexSet, /// Field used during rendering, to know if we're inside an inlined item. pub(crate) is_inside_inlined_module: bool, } +impl ContextInfo { + fn new(include_sources: bool) -> Self { + Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false } + } +} + // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. #[cfg(all(not(windows), target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Context<'_>, 192); @@ -174,14 +187,16 @@ impl<'tcx> Context<'tcx> { } fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String { - let mut render_redirect_pages = self.render_redirect_pages; + let mut render_redirect_pages = self.info.render_redirect_pages; // If the item is stripped but inlined, links won't point to the item so no need to generate // a file for it. if it.is_stripped() && let Some(def_id) = it.def_id() && def_id.is_local() { - if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) { + if self.info.is_inside_inlined_module + || self.shared.cache.inlined_items.contains(&def_id) + { // For now we're forced to generate a redirect page for stripped items until // `record_extern_fqn` correctly points to external items. render_redirect_pages = true; @@ -441,6 +456,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } const RUN_ON_MODULE: bool = true; + type InfoType = ContextInfo; fn init( krate: clean::Crate, @@ -562,13 +578,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let mut cx = Context { current: Vec::new(), dst, - render_redirect_pages: false, id_map, deref_id_map: Default::default(), shared: Rc::new(scx), - include_sources, types_with_notable_traits: FxIndexSet::default(), - is_inside_inlined_module: false, + info: ContextInfo::new(include_sources), }; if emit_crate { @@ -582,18 +596,15 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { Ok((cx, krate)) } - fn make_child_renderer(&self) -> Self { - Self { - current: self.current.clone(), - dst: self.dst.clone(), - render_redirect_pages: self.render_redirect_pages, - deref_id_map: Default::default(), - id_map: IdMap::new(), - shared: Rc::clone(&self.shared), - include_sources: self.include_sources, - types_with_notable_traits: FxIndexSet::default(), - is_inside_inlined_module: self.is_inside_inlined_module, - } + fn make_child_renderer(&mut self) -> Self::InfoType { + self.deref_id_map.clear(); + self.id_map.clear(); + self.types_with_notable_traits.clear(); + self.info + } + + fn set_back_info(&mut self, info: Self::InfoType) { + self.info = info; } fn after_krate(&mut self) -> Result<(), Error> { @@ -775,8 +786,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // External crates will provide links to these structures, so // these modules are recursed into, but not rendered normally // (a flag on the context). - if !self.render_redirect_pages { - self.render_redirect_pages = item.is_stripped(); + if !self.info.render_redirect_pages { + self.info.render_redirect_pages = item.is_stripped(); } let item_name = item.name.unwrap(); self.dst.push(item_name.as_str()); @@ -793,19 +804,19 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.shared.fs.write(joint_dst, buf)?; } } - if !self.is_inside_inlined_module { + if !self.info.is_inside_inlined_module { if let Some(def_id) = item.def_id() && self.cache().inlined_items.contains(&def_id) { - self.is_inside_inlined_module = true; + self.info.is_inside_inlined_module = true; } } else if !self.cache().document_hidden && item.is_doc_hidden() { // We're not inside an inlined module anymore since this one cannot be re-exported. - self.is_inside_inlined_module = false; + self.info.is_inside_inlined_module = false; } // Render sidebar-items.js used throughout this module. - if !self.render_redirect_pages { + if !self.info.render_redirect_pages { let (clean::StrippedItem(box clean::ModuleItem(ref module)) | clean::ModuleItem(ref module)) = item.kind else { @@ -836,8 +847,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // External crates will provide links to these structures, so // these modules are recursed into, but not rendered normally // (a flag on the context). - if !self.render_redirect_pages { - self.render_redirect_pages = item.is_stripped(); + if !self.info.render_redirect_pages { + self.info.render_redirect_pages = item.is_stripped(); } let buf = self.render_item(&item, false); @@ -850,7 +861,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let joint_dst = self.dst.join(file_name); self.shared.fs.write(joint_dst, buf)?; - if !self.render_redirect_pages { + if !self.info.render_redirect_pages { self.shared.all.borrow_mut().append(full_path(self, &item), &item_type); } // If the item is a macro, redirect from the old macro URL (with !) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index dc205252507c..a86b7966c260 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -223,7 +223,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. let src_href = - if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None }; + if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None }; let path_components = if item.is_primitive() || item.is_keyword() { vec![] diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 7c676469597d..1fb589d829e5 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -104,7 +104,7 @@ pub(crate) fn write_shared( &cx.shared.style_files, cx.shared.layout.css_file_extension.as_deref(), &cx.shared.resource_suffix, - cx.include_sources, + cx.info.include_sources, )?; match &opt.index_page { Some(index_page) if opt.enable_index_page => { diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 2fe9364c259c..71b110c943e2 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -124,7 +124,7 @@ struct SourceCollector<'a, 'tcx> { impl DocVisitor<'_> for SourceCollector<'_, '_> { fn visit_item(&mut self, item: &clean::Item) { - if !self.cx.include_sources { + if !self.cx.info.include_sources { return; } @@ -146,7 +146,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> { // something like that), so just don't include sources for the // entire crate. The other option is maintaining this mapping on a // per-file basis, but that's probably not worth it... - self.cx.include_sources = match self.emit_source(&filename, file_span) { + self.cx.info.include_sources = match self.emit_source(&filename, file_span) { Ok(()) => true, Err(e) => { self.cx.shared.tcx.dcx().span_err( diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 560ed872ef3a..9e512e87afc4 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -137,6 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { } const RUN_ON_MODULE: bool = false; + type InfoType = (); fn init( krate: clean::Crate, @@ -161,9 +162,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { )) } - fn make_child_renderer(&self) -> Self { - self.clone() - } + fn make_child_renderer(&mut self) -> Self::InfoType {} + fn set_back_info(&mut self, _info: Self::InfoType) {} /// Inserts an item into the index. This should be used rather than directly calling insert on /// the hashmap because certain items (traits and types) need to have their mappings for trait From 46afbc0588316cb3e5def6c8b4ccbaefdfaedb7f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 23 Nov 2024 01:03:31 +0100 Subject: [PATCH 265/330] Split ID maps in two parts: the constant one and the updated one --- src/librustdoc/html/markdown.rs | 118 +++++++++++++------------- src/librustdoc/html/render/context.rs | 6 -- 2 files changed, 57 insertions(+), 67 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 0f210270f788..3bf2bc0840ce 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -32,7 +32,6 @@ use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::path::PathBuf; use std::str::{self, CharIndices}; -use std::sync::OnceLock; use pulldown_cmark::{ BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, @@ -1883,83 +1882,81 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec, usize>, + defined_ids: FxHashSet<&'static str>, existing_footnotes: usize, } -// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly. -static DEFAULT_ID_MAP: OnceLock>> = OnceLock::new(); - -fn init_id_map() -> FxHashSet> { +fn init_id_map() -> FxHashSet<&'static str> { let mut map = FxHashSet::default(); // This is the list of IDs used in JavaScript. - map.insert("help".into()); - map.insert("settings".into()); - map.insert("not-displayed".into()); - map.insert("alternative-display".into()); - map.insert("search".into()); - map.insert("crate-search".into()); - map.insert("crate-search-div".into()); + map.insert("help"); + map.insert("settings"); + map.insert("not-displayed"); + map.insert("alternative-display"); + map.insert("search"); + map.insert("crate-search"); + map.insert("crate-search-div"); // This is the list of IDs used in HTML generated in Rust (including the ones // used in tera template files). - map.insert("themeStyle".into()); - map.insert("settings-menu".into()); - map.insert("help-button".into()); - map.insert("sidebar-button".into()); - map.insert("main-content".into()); - map.insert("toggle-all-docs".into()); - map.insert("all-types".into()); - map.insert("default-settings".into()); - map.insert("sidebar-vars".into()); - map.insert("copy-path".into()); - map.insert("rustdoc-toc".into()); - map.insert("rustdoc-modnav".into()); + map.insert("themeStyle"); + map.insert("settings-menu"); + map.insert("help-button"); + map.insert("sidebar-button"); + map.insert("main-content"); + map.insert("toggle-all-docs"); + map.insert("all-types"); + map.insert("default-settings"); + map.insert("sidebar-vars"); + map.insert("copy-path"); + map.insert("rustdoc-toc"); + map.insert("rustdoc-modnav"); // This is the list of IDs used by rustdoc sections (but still generated by // rustdoc). - map.insert("fields".into()); - map.insert("variants".into()); - map.insert("implementors-list".into()); - map.insert("synthetic-implementors-list".into()); - map.insert("foreign-impls".into()); - map.insert("implementations".into()); - map.insert("trait-implementations".into()); - map.insert("synthetic-implementations".into()); - map.insert("blanket-implementations".into()); - map.insert("required-associated-types".into()); - map.insert("provided-associated-types".into()); - map.insert("provided-associated-consts".into()); - map.insert("required-associated-consts".into()); - map.insert("required-methods".into()); - map.insert("provided-methods".into()); - map.insert("dyn-compatibility".into()); - map.insert("implementors".into()); - map.insert("synthetic-implementors".into()); - map.insert("implementations-list".into()); - map.insert("trait-implementations-list".into()); - map.insert("synthetic-implementations-list".into()); - map.insert("blanket-implementations-list".into()); - map.insert("deref-methods".into()); - map.insert("layout".into()); - map.insert("aliased-type".into()); + map.insert("fields"); + map.insert("variants"); + map.insert("implementors-list"); + map.insert("synthetic-implementors-list"); + map.insert("foreign-impls"); + map.insert("implementations"); + map.insert("trait-implementations"); + map.insert("synthetic-implementations"); + map.insert("blanket-implementations"); + map.insert("required-associated-types"); + map.insert("provided-associated-types"); + map.insert("provided-associated-consts"); + map.insert("required-associated-consts"); + map.insert("required-methods"); + map.insert("provided-methods"); + map.insert("dyn-compatibility"); + map.insert("implementors"); + map.insert("synthetic-implementors"); + map.insert("implementations-list"); + map.insert("trait-implementations-list"); + map.insert("synthetic-implementations-list"); + map.insert("blanket-implementations-list"); + map.insert("deref-methods"); + map.insert("layout"); + map.insert("aliased-type"); map } impl IdMap { pub fn new() -> Self { - let mut id_map = IdMap { map: FxHashMap::default(), existing_footnotes: 0 }; - id_map.init_map(); - id_map - } - - #[allow(rustc::potential_query_instability)] - fn init_map(&mut self) { - for key in DEFAULT_ID_MAP.get_or_init(init_id_map).iter() { - self.map.insert(key.clone(), 1); - } + IdMap { map: FxHashMap::default(), defined_ids: init_id_map(), existing_footnotes: 0 } } pub(crate) fn derive + ToString>(&mut self, candidate: S) -> String { let id = match self.map.get_mut(candidate.as_ref()) { - None => candidate.to_string(), + None => { + let candidate = candidate.to_string(); + if self.defined_ids.contains(candidate.as_str()) { + let id = format!("{}-{}", candidate, 1); + self.map.insert(candidate.into(), 2); + id + } else { + candidate + } + } Some(a) => { let id = format!("{}-{}", candidate.as_ref(), *a); *a += 1; @@ -1982,7 +1979,6 @@ impl IdMap { pub(crate) fn clear(&mut self) { self.map.clear(); - self.init_map(); self.existing_footnotes = 0; } } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 0b87c1bb62ca..bc1f0423c17c 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -87,12 +87,6 @@ impl ContextInfo { } } -// `Context` is cloned a lot, so we don't want the size to grow unexpectedly. -#[cfg(all(not(windows), target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 192); -#[cfg(all(windows, target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 200); - /// Shared mutable state used in [`Context`] and elsewhere. pub(crate) struct SharedContext<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, From 2e242f8af312607cb50bcc9b3b02ff1576dcfa9b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Nov 2024 14:58:32 +0100 Subject: [PATCH 266/330] Store default ID map in a static --- src/librustdoc/html/markdown.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 3bf2bc0840ce..d18673c8140d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -32,6 +32,7 @@ use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::path::PathBuf; use std::str::{self, CharIndices}; +use std::sync::OnceLock; use pulldown_cmark::{ BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, @@ -1882,10 +1883,13 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec, usize>, - defined_ids: FxHashSet<&'static str>, existing_footnotes: usize, } +// The map is pre-initialized and then can be used as is to prevent cloning it for each item +// (in the sidebar rendering). +static DEFAULT_ID_MAP: OnceLock> = OnceLock::new(); + fn init_id_map() -> FxHashSet<&'static str> { let mut map = FxHashSet::default(); // This is the list of IDs used in JavaScript. @@ -1942,14 +1946,14 @@ fn init_id_map() -> FxHashSet<&'static str> { impl IdMap { pub fn new() -> Self { - IdMap { map: FxHashMap::default(), defined_ids: init_id_map(), existing_footnotes: 0 } + IdMap { map: FxHashMap::default(), existing_footnotes: 0 } } pub(crate) fn derive + ToString>(&mut self, candidate: S) -> String { let id = match self.map.get_mut(candidate.as_ref()) { None => { let candidate = candidate.to_string(); - if self.defined_ids.contains(candidate.as_str()) { + if DEFAULT_ID_MAP.get_or_init(init_id_map).contains(candidate.as_str()) { let id = format!("{}-{}", candidate, 1); self.map.insert(candidate.into(), 2); id From 5fa1653c5cd175430d14c3c3d8416635772811da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 25 Nov 2024 16:19:02 +0100 Subject: [PATCH 267/330] Move `SharedContext` out of `Rc` --- src/librustdoc/html/render/context.rs | 45 ++++---- src/librustdoc/html/render/mod.rs | 70 ++++++------ src/librustdoc/html/render/print_item.rs | 117 ++++++++++----------- src/librustdoc/html/render/sidebar.rs | 72 +++++++++---- src/librustdoc/html/render/write_shared.rs | 23 ++-- src/librustdoc/html/sources.rs | 6 +- 6 files changed, 171 insertions(+), 162 deletions(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index bc1f0423c17c..81a9cce80d12 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::collections::BTreeMap; use std::io; use std::path::{Path, PathBuf}; -use std::rc::Rc; use std::sync::mpsc::{Receiver, channel}; use rinja::Template; @@ -51,17 +50,17 @@ pub(crate) struct Context<'tcx> { pub(crate) dst: PathBuf, /// Tracks section IDs for `Deref` targets so they match in both the main /// body and the sidebar. - pub(super) deref_id_map: DefIdMap, + pub(super) deref_id_map: RefCell>, /// The map used to ensure all generated 'id=' attributes are unique. - pub(super) id_map: IdMap, + pub(super) id_map: RefCell, /// Shared mutable state. /// /// Issue for improving the situation: [#82381][] /// /// [#82381]: https://github.com/rust-lang/rust/issues/82381 - pub(crate) shared: Rc>, + pub(crate) shared: SharedContext<'tcx>, /// Collection of all types with notable traits referenced in the current module. - pub(crate) types_with_notable_traits: FxIndexSet, + pub(crate) types_with_notable_traits: RefCell>, /// Contains information that needs to be saved and reset after rendering an item which is /// not a module. pub(crate) info: ContextInfo, @@ -170,8 +169,8 @@ impl<'tcx> Context<'tcx> { self.shared.tcx.sess } - pub(super) fn derive_id + ToString>(&mut self, id: S) -> String { - self.id_map.derive(id) + pub(super) fn derive_id + ToString>(&self, id: S) -> String { + self.id_map.borrow_mut().derive(id) } /// String representation of how to get back to the root path of the 'doc/' @@ -230,24 +229,23 @@ impl<'tcx> Context<'tcx> { }; if !render_redirect_pages { - let clone_shared = Rc::clone(&self.shared); + let mut page_buffer = Buffer::html(); + print_item(self, it, &mut page_buffer); let page = layout::Page { css_class: tyname_s, root_path: &self.root_path(), - static_root_path: clone_shared.static_root_path.as_deref(), + static_root_path: self.shared.static_root_path.as_deref(), title: &title, description: &desc, - resource_suffix: &clone_shared.resource_suffix, + resource_suffix: &self.shared.resource_suffix, rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo), }; - let mut page_buffer = Buffer::html(); - print_item(self, it, &mut page_buffer); layout::render( - &clone_shared.layout, + &self.shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), move |buf: &mut Buffer| buf.push_buffer(page_buffer), - &clone_shared.style_files, + &self.shared.style_files, ) } else { if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) { @@ -572,10 +570,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let mut cx = Context { current: Vec::new(), dst, - id_map, + id_map: RefCell::new(id_map), deref_id_map: Default::default(), - shared: Rc::new(scx), - types_with_notable_traits: FxIndexSet::default(), + shared: scx, + types_with_notable_traits: RefCell::new(FxIndexSet::default()), info: ContextInfo::new(include_sources), }; @@ -591,9 +589,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } fn make_child_renderer(&mut self) -> Self::InfoType { - self.deref_id_map.clear(); - self.id_map.clear(); - self.types_with_notable_traits.clear(); + self.deref_id_map.borrow_mut().clear(); + self.id_map.borrow_mut().clear(); + self.types_with_notable_traits.borrow_mut().clear(); self.info } @@ -612,7 +610,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if !root_path.ends_with('/') { root_path.push('/'); } - let shared = Rc::clone(&self.shared); + let shared = &self.shared; let mut page = layout::Page { title: "List of all items in this crate", css_class: "mod sys", @@ -759,11 +757,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { shared.fs.write(redirect_map_path, paths)?; } - // No need for it anymore. - drop(shared); - // Flush pending errors. - Rc::get_mut(&mut self.shared).unwrap().fs.close(); + self.shared.fs.close(); let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count(); if nb_errors > 0 { Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), "")) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7c5048cd164b..f43672575723 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -41,7 +41,6 @@ use std::collections::VecDeque; use std::fmt::{self, Write}; use std::iter::Peekable; use std::path::PathBuf; -use std::rc::Rc; use std::{fs, str}; use rinja::Template; @@ -504,7 +503,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { } fn document<'a, 'cx: 'a>( - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, item: &'a clean::Item, parent: Option<&'a clean::Item>, heading_offset: HeadingOffset, @@ -525,7 +524,7 @@ fn document<'a, 'cx: 'a>( /// Render md_text as markdown. fn render_markdown<'a, 'cx: 'a>( - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, md_text: &'a str, links: Vec, heading_offset: HeadingOffset, @@ -537,7 +536,7 @@ fn render_markdown<'a, 'cx: 'a>( Markdown { content: md_text, links: &links, - ids: &mut cx.id_map, + ids: &mut cx.id_map.borrow_mut(), error_codes: cx.shared.codes, edition: cx.shared.edition(), playground: &cx.shared.playground, @@ -552,7 +551,7 @@ fn render_markdown<'a, 'cx: 'a>( /// docs are longer, a "Read more" link is appended to the end. fn document_short<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, link: AssocItemLink<'a>, parent: &'a clean::Item, show_def_docs: bool, @@ -585,7 +584,7 @@ fn document_short<'a, 'cx: 'a>( fn document_full_collapsible<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { document_full_inner(item, cx, true, heading_offset) @@ -593,7 +592,7 @@ fn document_full_collapsible<'a, 'cx: 'a>( fn document_full<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { document_full_inner(item, cx, false, heading_offset) @@ -601,7 +600,7 @@ fn document_full<'a, 'cx: 'a>( fn document_full_inner<'a, 'cx: 'a>( item: &'a clean::Item, - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, is_collapsible: bool, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { @@ -644,7 +643,7 @@ struct ItemInfo { /// * Deprecated /// * Required features (through the `doc_cfg` feature) fn document_item_info( - cx: &mut Context<'_>, + cx: &Context<'_>, item: &clean::Item, parent: Option<&clean::Item>, ) -> ItemInfo { @@ -690,7 +689,7 @@ enum ShortItemInfo { /// the item's documentation. fn short_item_info( item: &clean::Item, - cx: &mut Context<'_>, + cx: &Context<'_>, parent: Option<&clean::Item>, ) -> Vec { let mut extra_info = vec![]; @@ -715,7 +714,8 @@ fn short_item_info( if let Some(note) = note { let note = note.as_str(); - let html = MarkdownItemInfo(note, &mut cx.id_map); + let mut id_map = cx.id_map.borrow_mut(); + let html = MarkdownItemInfo(note, &mut id_map); message.push_str(": "); message.push_str(&html.into_string()); } @@ -749,18 +749,17 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). pub(crate) fn render_impls( - cx: &mut Context<'_>, + cx: &Context<'_>, mut w: impl Write, impls: &[&Impl], containing_item: &clean::Item, toggle_open_by_default: bool, ) { - let tcx = cx.tcx(); let mut rendered_impls = impls .iter() .map(|i| { let did = i.trait_did().unwrap(); - let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx); + let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx()); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); let mut buffer = Buffer::new(); render_impl( @@ -906,7 +905,7 @@ fn assoc_method( d: &clean::FnDecl, link: AssocItemLink<'_>, parent: ItemType, - cx: &mut Context<'_>, + cx: &Context<'_>, render_mode: RenderMode, ) { let tcx = cx.tcx(); @@ -1071,7 +1070,7 @@ fn render_assoc_item( item: &clean::Item, link: AssocItemLink<'_>, parent: ItemType, - cx: &mut Context<'_>, + cx: &Context<'_>, render_mode: RenderMode, ) { match &item.kind { @@ -1191,7 +1190,7 @@ fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) { pub(crate) fn render_all_impls( mut w: impl Write, - cx: &mut Context<'_>, + cx: &Context<'_>, containing_item: &clean::Item, concrete: &[&Impl], synthetic: &[&Impl], @@ -1225,7 +1224,7 @@ pub(crate) fn render_all_impls( } fn render_assoc_items<'a, 'cx: 'a>( - cx: &'a mut Context<'cx>, + cx: &'a Context<'cx>, containing_item: &'a clean::Item, it: DefId, what: AssocItemRender<'a>, @@ -1240,15 +1239,14 @@ fn render_assoc_items<'a, 'cx: 'a>( fn render_assoc_items_inner( mut w: &mut dyn fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>, derefs: &mut DefIdSet, ) { info!("Documenting associated items of {:?}", containing_item.name); - let shared = Rc::clone(&cx.shared); - let cache = &shared.cache; + let cache = &cx.shared.cache; let Some(v) = cache.impls.get(&it) else { return }; let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { @@ -1276,7 +1274,7 @@ fn render_assoc_items_inner( ); tmp_buf.write_str(""); if let Some(def_id) = type_.def_id(cx.cache()) { - cx.deref_id_map.insert(def_id, id); + cx.deref_id_map.borrow_mut().insert(def_id, id); } (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#) } @@ -1340,7 +1338,7 @@ fn render_assoc_items_inner( fn render_deref_methods( mut w: impl Write, - cx: &mut Context<'_>, + cx: &Context<'_>, impl_: &Impl, container_item: &clean::Item, deref_mut: bool, @@ -1407,7 +1405,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } } -pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option { +pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option { let mut has_notable_trait = false; if ty.is_unit() { @@ -1450,7 +1448,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O } if has_notable_trait { - cx.types_with_notable_traits.insert(ty.clone()); + cx.types_with_notable_traits.borrow_mut().insert(ty.clone()); Some(format!( " ", ty = Escape(&format!("{:#}", ty.print(cx))), @@ -1554,7 +1552,7 @@ struct ImplRenderingParameters { fn render_impl( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, i: &Impl, parent: &clean::Item, link: AssocItemLink<'_>, @@ -1563,8 +1561,7 @@ fn render_impl( aliases: &[String], rendering_params: ImplRenderingParameters, ) { - let shared = Rc::clone(&cx.shared); - let cache = &shared.cache; + let cache = &cx.shared.cache; let traits = &cache.traits; let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = >::with_capacity(2); @@ -1577,7 +1574,7 @@ fn render_impl( fn doc_impl_item( boring: &mut Buffer, interesting: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, item: &clean::Item, parent: &clean::Item, link: AssocItemLink<'_>, @@ -1867,7 +1864,7 @@ fn render_impl( fn render_default_items( boring: &mut Buffer, interesting: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, t: &clean::Trait, i: &clean::Impl, parent: &clean::Item, @@ -1907,6 +1904,7 @@ fn render_impl( } } + let trait_is_none = trait_.is_none(); // If we've implemented a trait, then also emit documentation for all // default items which weren't overridden in the implementation block. // We don't emit documentation for default items if they appear in the @@ -1952,7 +1950,7 @@ fn render_impl( } if let Some(ref dox) = i.impl_item.opt_doc_value() { - if trait_.is_none() && impl_.items.is_empty() { + if trait_is_none && impl_.items.is_empty() { w.write_str( "
\
This impl block contains no items.
\ @@ -1965,7 +1963,7 @@ fn render_impl( Markdown { content: dox, links: &i.impl_item.links(cx), - ids: &mut cx.id_map, + ids: &mut cx.id_map.borrow_mut(), error_codes: cx.shared.codes, edition: cx.shared.edition(), playground: &cx.shared.playground, @@ -2025,7 +2023,7 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render pub(crate) fn render_impl_summary( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, i: &Impl, parent: &clean::Item, show_def_docs: bool, @@ -2186,7 +2184,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String /// implementations that are on concrete or partially generic types, only keeping implementations /// of the form `impl Trait for &T`. pub(crate) fn get_filtered_impls_for_reference<'a>( - shared: &'a Rc>, + shared: &'a SharedContext<'_>, it: &clean::Item, ) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) { let def_id = it.item_id.expect_def_id(); @@ -2423,14 +2421,14 @@ const MAX_FULL_EXAMPLES: usize = 5; const NUM_VISIBLE_LINES: usize = 10; /// Generates the HTML for example call locations generated via the --scrape-examples flag. -fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &clean::Item) { +fn render_call_locations(mut w: W, cx: &Context<'_>, item: &clean::Item) { let tcx = cx.tcx(); let def_id = item.item_id.expect_def_id(); let key = tcx.def_path_hash(def_id); let Some(call_locations) = cx.shared.call_locations.get(&key) else { return }; // Generate a unique ID so users can link to this section for a given method - let id = cx.id_map.derive("scraped-examples"); + let id = cx.derive_id("scraped-examples"); write!( &mut w, "
\ diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index a86b7966c260..4c8d704e65bc 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,7 +1,5 @@ -use std::cell::{RefCell, RefMut}; use std::cmp::Ordering; use std::fmt; -use std::rc::Rc; use itertools::Itertools; use rinja::Template; @@ -61,7 +59,7 @@ macro_rules! item_template { ( $(#[$meta:meta])* struct $name:ident<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, + cx: &'a Context<'cx>, it: &'a clean::Item, $($field_name:ident: $field_ty:ty),*, }, @@ -70,14 +68,14 @@ macro_rules! item_template { #[derive(Template)] $(#[$meta])* struct $name<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, + cx: &'a Context<'cx>, it: &'a clean::Item, $($field_name: $field_ty),* } impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for $name<'a, 'cx> { - fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { - (&self.it, self.cx.borrow_mut()) + fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>) { + (&self.it, &self.cx) } } @@ -95,8 +93,8 @@ macro_rules! item_template_methods { (document $($rest:tt)*) => { fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, mut cx) = self.item_and_mut_cx(); - let v = document(*cx, item, None, HeadingOffset::H2); + let (item, cx) = self.item_and_cx(); + let v = document(cx, item, None, HeadingOffset::H2); write!(f, "{v}") }) } @@ -105,9 +103,9 @@ macro_rules! item_template_methods { (document_type_layout $($rest:tt)*) => { fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, cx) = self.item_and_mut_cx(); + let (item, cx) = self.item_and_cx(); let def_id = item.item_id.expect_def_id(); - let v = document_type_layout(*cx, def_id); + let v = document_type_layout(cx, def_id); write!(f, "{v}") }) } @@ -116,8 +114,8 @@ macro_rules! item_template_methods { (render_attributes_in_pre $($rest:tt)*) => { fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, cx) = self.item_and_mut_cx(); - let v = render_attributes_in_pre(item, "", &cx); + let (item, cx) = self.item_and_cx(); + let v = render_attributes_in_pre(item, "", cx); write!(f, "{v}") }) } @@ -126,9 +124,9 @@ macro_rules! item_template_methods { (render_assoc_items $($rest:tt)*) => { fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let (item, mut cx) = self.item_and_mut_cx(); + let (item, cx) = self.item_and_cx(); let def_id = item.item_id.expect_def_id(); - let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All); + let v = render_assoc_items(cx, item, def_id, AssocItemRender::All); write!(f, "{v}") }) } @@ -175,7 +173,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>( len_before != buffer.len() } -pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) { +pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { debug_assert!(!item.is_stripped()); let typ = match item.kind { clean::ModuleItem(_) => { @@ -277,13 +275,14 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf } // Render notable-traits.js used for all methods in this module. - if !cx.types_with_notable_traits.is_empty() { + let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut(); + if !types_with_notable_traits.is_empty() { write!( buf, r#""#, - notable_traits_json(cx.types_with_notable_traits.iter(), cx) + notable_traits_json(types_with_notable_traits.iter(), cx) ); - cx.types_with_notable_traits.clear(); + types_with_notable_traits.clear(); } } @@ -308,10 +307,10 @@ fn toggle_close(mut w: impl fmt::Write) { } trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display { - fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); + fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>); } -fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { +fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) { write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); let mut not_stripped_items = @@ -594,7 +593,7 @@ fn extra_info_tags<'a, 'tcx: 'a>( }) } -fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) { +fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { let tcx = cx.tcx(); let header = it.fn_header(tcx).expect("printing a function which isn't a function"); debug!( @@ -649,7 +648,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); } -fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) { +fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) { let tcx = cx.tcx(); let bounds = bounds(&t.bounds, false, cx); let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::>(); @@ -801,7 +800,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // Trait documentation write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) { + fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) { let name = m.name.unwrap(); info!("Documenting {name} on {ty_name:?}", ty_name = t.name); let item_type = m.type_(); @@ -929,8 +928,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: // If there are methods directly on this trait object, render them here. write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)); - let cloned_shared = Rc::clone(&cx.shared); - let cache = &cloned_shared.cache; let mut extern_crates = FxIndexSet::default(); if !t.is_dyn_compatible(cx.tcx()) { @@ -950,12 +947,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: ); } - if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { + if let Some(implementors) = cx.shared.cache.implementors.get(&it.item_id.expect_def_id()) { // The DefId is for the first Type found with that name. The bool is // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap = FxHashMap::default(); for implementor in implementors { - if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache) + if let Some(did) = + implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache) && !did.is_local() { extern_crates.insert(did.krate); @@ -1036,7 +1034,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: it, w, &implementor_dups, - &collect_paths_for_type(implementor.inner_impl().for_.clone(), cache), + &collect_paths_for_type( + implementor.inner_impl().for_.clone(), + &cx.shared.cache, + ), ); } w.write_str("
"); @@ -1139,8 +1140,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: .chain(std::iter::once("trait.impl")) .collect(); if let Some(did) = it.item_id.as_def_id() - && let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) } - && let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern) + && let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) } + && let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern) { js_src_path.extend(fqp[..fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap())); @@ -1164,7 +1165,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn item_trait_alias( w: &mut impl fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias, ) { @@ -1190,7 +1191,7 @@ fn item_trait_alias( .unwrap(); } -fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { +fn item_type_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { wrap_item(w, |w| { write!( w, @@ -1355,8 +1356,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c // // [JSONP]: https://en.wikipedia.org/wiki/JSONP // [^115718]: https://github.com/rust-lang/rust/issues/115718 - let cloned_shared = Rc::clone(&cx.shared); - let cache = &cloned_shared.cache; + let cache = &cx.shared.cache; if let Some(target_did) = t.type_.def_id(cache) && let get_extern = { || cache.external_paths.get(&target_did) } && let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) && @@ -1380,11 +1380,11 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c } } -fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { +fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { item_template!( #[template(path = "item_union.html")] struct ItemUnion<'a, 'cx> { - cx: RefCell<&'a mut Context<'cx>>, + cx: &'a Context<'cx>, it: &'a clean::Item, s: &'a clean::Union, }, @@ -1394,8 +1394,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let cx = self.cx.borrow_mut(); - let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx); + let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx); write!(f, "{v}") }) } @@ -1405,15 +1404,13 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: field: &'a clean::Item, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + let v = document(self.cx, field, Some(self.it), HeadingOffset::H3); write!(f, "{v}") }) } fn stability_field(&self, field: &clean::Item) -> Option { - let cx = self.cx.borrow(); - field.stability_class(cx.tcx()) + field.stability_class(self.cx.tcx()) } fn print_ty<'b>( @@ -1421,8 +1418,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: ty: &'a clean::Type, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { - let cx = self.cx.borrow(); - let v = ty.print(*cx); + let v = ty.print(&self.cx); write!(f, "{v}") }) } @@ -1441,7 +1437,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: } } - ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap(); + ItemUnion { cx, it, s }.render_into(w).unwrap(); } fn print_tuple_struct_fields<'a, 'cx: 'a>( @@ -1471,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( }) } -fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { +fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { let count_variants = e.variants().count(); wrap_item(w, |w| { render_attributes_in_code(w, it, cx); @@ -1532,7 +1528,7 @@ fn should_show_enum_discriminant( fn display_c_like_variant( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, item: &clean::Item, variant: &clean::Variant, index: VariantIdx, @@ -1557,7 +1553,7 @@ fn display_c_like_variant( fn render_enum_fields( mut w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, g: Option<&clean::Generics>, variants: &IndexVec, count_variants: usize, @@ -1621,7 +1617,7 @@ fn render_enum_fields( fn item_variants( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, variants: &IndexVec, enum_def_id: DefId, @@ -1743,7 +1739,7 @@ fn item_variants( write!(w, "
"); } -fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { +fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) { wrap_item(w, |w| { // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`. if !t.macro_rules { @@ -1756,7 +1752,7 @@ fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn item_proc_macro( w: &mut impl fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro, ) { @@ -1790,7 +1786,7 @@ fn item_proc_macro( write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); } -fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) { +fn item_primitive(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) { let def_id = it.item_id.expect_def_id(); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { @@ -1798,8 +1794,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite } else { // We handle the "reference" primitive type on its own because we only want to list // implementations on generic types. - let shared = Rc::clone(&cx.shared); - let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it); + let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it); render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl); } @@ -1807,7 +1802,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite fn item_constant( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, generics: &clean::Generics, ty: &clean::Type, @@ -1862,7 +1857,7 @@ fn item_constant( write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } -fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { +fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) { wrap_item(w, |w| { render_attributes_in_code(w, it, cx); render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); @@ -1879,7 +1874,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean fn item_fields( w: &mut Buffer, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, fields: &[clean::Item], ctor_kind: Option, @@ -1920,7 +1915,7 @@ fn item_fields( fn item_static( w: &mut impl fmt::Write, - cx: &mut Context<'_>, + cx: &Context<'_>, it: &clean::Item, s: &clean::Static, safety: Option, @@ -1944,7 +1939,7 @@ fn item_static( write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); } -fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) { +fn item_foreign_type(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) { wrap_item(w, |buffer| { buffer.write_str("extern {\n").unwrap(); render_attributes_in_code(buffer, it, cx); @@ -1962,7 +1957,7 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean:: .unwrap(); } -fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { +fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } @@ -2134,7 +2129,7 @@ impl Ord for ImplString { } fn render_implementor( - cx: &mut Context<'_>, + cx: &Context<'_>, implementor: &Impl, trait_: &clean::Item, w: &mut Buffer, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 76de8d872311..e99e2f04b2c5 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -1,10 +1,9 @@ use std::borrow::Cow; -use std::rc::Rc; use rinja::Template; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::CtorKind; -use rustc_hir::def_id::DefIdSet; +use rustc_hir::def_id::{DefIdMap, DefIdSet}; use rustc_middle::ty::{self, TyCtxt}; use tracing::debug; @@ -119,17 +118,18 @@ pub(crate) mod filters { pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let mut ids = IdMap::new(); let mut blocks: Vec> = docblock_toc(cx, it, &mut ids).into_iter().collect(); + let deref_id_map = cx.deref_id_map.borrow(); match it.kind { - clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks), - clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks), - clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks), - clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks), - clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks), - clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks), + clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks, &deref_id_map), + clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks, &deref_id_map), + clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks, &deref_id_map), + clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks, &deref_id_map), + clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks, &deref_id_map), + clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks, &deref_id_map), clean::ModuleItem(ref m) => { blocks.push(sidebar_module(&m.items, &mut ids, ModuleLike::from(it))) } - clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks), + clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks, &deref_id_map), _ => {} } // The sidebar is designed to display sibling functions, modules and @@ -245,6 +245,7 @@ fn sidebar_struct<'a>( it: &'a clean::Item, s: &'a clean::Struct, items: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { let fields = get_struct_fields_name(&s.fields); let field_name = match s.ctor_kind { @@ -255,7 +256,7 @@ fn sidebar_struct<'a>( if let Some(name) = field_name { items.push(LinkBlock::new(Link::new("fields", name), "structfield", fields)); } - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } fn sidebar_trait<'a>( @@ -263,6 +264,7 @@ fn sidebar_trait<'a>( it: &'a clean::Item, t: &'a clean::Trait, blocks: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { fn filter_items<'a>( items: &'a [clean::Item], @@ -313,7 +315,7 @@ fn sidebar_trait<'a>( .into_iter() .map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)), ); - sidebar_assoc_items(cx, it, blocks); + sidebar_assoc_items(cx, it, blocks, deref_id_map); if !t.is_dyn_compatible(cx.tcx()) { blocks.push(LinkBlock::forced( @@ -331,13 +333,17 @@ fn sidebar_trait<'a>( } } -fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec>) { +fn sidebar_primitive<'a>( + cx: &'a Context<'_>, + it: &'a clean::Item, + items: &mut Vec>, + deref_id_map: &'a DefIdMap, +) { if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } else { - let shared = Rc::clone(&cx.shared); let (concrete, synthetic, blanket_impl) = - super::get_filtered_impls_for_reference(&shared, it); + super::get_filtered_impls_for_reference(&cx.shared, it); sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl, items); } @@ -348,6 +354,7 @@ fn sidebar_type_alias<'a>( it: &'a clean::Item, t: &'a clean::TypeAlias, items: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { if let Some(inner_type) = &t.inner_type { items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type")); @@ -370,7 +377,7 @@ fn sidebar_type_alias<'a>( } } } - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } fn sidebar_union<'a>( @@ -378,10 +385,11 @@ fn sidebar_union<'a>( it: &'a clean::Item, u: &'a clean::Union, items: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { let fields = get_struct_fields_name(&u.fields); items.push(LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields)); - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } /// Adds trait implementations into the blocks of links @@ -389,6 +397,7 @@ fn sidebar_assoc_items<'a>( cx: &'a Context<'_>, it: &'a clean::Item, links: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { let did = it.item_id.expect_def_id(); let cache = cx.cache(); @@ -433,7 +442,15 @@ fn sidebar_assoc_items<'a>( { let mut derefs = DefIdSet::default(); derefs.insert(did); - sidebar_deref_methods(cx, &mut blocks, impl_, v, &mut derefs, &mut used_links); + sidebar_deref_methods( + cx, + &mut blocks, + impl_, + v, + &mut derefs, + &mut used_links, + deref_id_map, + ); } let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = @@ -462,6 +479,7 @@ fn sidebar_deref_methods<'a>( v: &[Impl], derefs: &mut DefIdSet, used_links: &mut FxHashSet, + deref_id_map: &'a DefIdMap, ) { let c = cx.cache(); @@ -501,7 +519,7 @@ fn sidebar_deref_methods<'a>( if !ret.is_empty() { let id = if let Some(target_def_id) = real_target.def_id(c) { Cow::Borrowed( - cx.deref_id_map + deref_id_map .get(&target_def_id) .expect("Deref section without derived id") .as_str(), @@ -531,7 +549,15 @@ fn sidebar_deref_methods<'a>( .unwrap_or(false) }) { - sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs, used_links); + sidebar_deref_methods( + cx, + out, + target_deref_impl, + target_impls, + derefs, + used_links, + deref_id_map, + ); } } } @@ -541,6 +567,7 @@ fn sidebar_enum<'a>( it: &'a clean::Item, e: &'a clean::Enum, items: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { let mut variants = e .variants() @@ -550,7 +577,7 @@ fn sidebar_enum<'a>( variants.sort_unstable(); items.push(LinkBlock::new(Link::new("variants", "Variants"), "variant", variants)); - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } pub(crate) fn sidebar_module_like( @@ -607,8 +634,9 @@ fn sidebar_foreign_type<'a>( cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec>, + deref_id_map: &'a DefIdMap, ) { - sidebar_assoc_items(cx, it, items); + sidebar_assoc_items(cx, it, items, deref_id_map); } /// Renders the trait implementations for this type diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 1fb589d829e5..ce10e5ecc244 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -43,7 +43,6 @@ use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::Impl; -use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::format::Buffer; use crate::html::layout; @@ -62,13 +61,12 @@ pub(crate) fn write_shared( tcx: TyCtxt<'_>, ) -> Result<(), Error> { // NOTE(EtomicBomb): I don't think we need sync here because no read-after-write? - Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); + cx.shared.fs.set_sync_only(true); let lock_file = cx.dst.join(".lock"); // Write shared runs within a flock; disable thread dispatching of IO temporarily. let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file); - let SerializedSearchIndex { index, desc } = - build_index(krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); + let SerializedSearchIndex { index, desc } = build_index(krate, &mut cx.shared.cache, tcx); write_search_desc(cx, krate, &desc)?; // does not need to be merged let crate_name = krate.name(cx.tcx()); @@ -128,7 +126,7 @@ pub(crate) fn write_shared( } } - Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); + cx.shared.fs.set_sync_only(false); Ok(()) } @@ -597,13 +595,11 @@ impl TypeAliasPart { krate: &Crate, crate_name_json: &OrderedJson, ) -> Result, Error> { - let cache = &Rc::clone(&cx.shared).cache; let mut path_parts = PartsAndLocations::default(); let mut type_impl_collector = TypeImplCollector { aliased_types: IndexMap::default(), visited_aliases: FxHashSet::default(), - cache, cx, }; DocVisitor::visit_crate(&mut type_impl_collector, krate); @@ -625,14 +621,14 @@ impl TypeAliasPart { // each type alias, and if it gives a different result, split the impl for &(type_alias_fqp, type_alias_item) in type_aliases { let mut buf = Buffer::html(); - cx.id_map = Default::default(); - cx.deref_id_map = Default::default(); + cx.id_map.borrow_mut().clear(); + cx.deref_id_map.borrow_mut().clear(); let target_did = impl_ .inner_impl() .trait_ .as_ref() .map(|trait_| trait_.def_id()) - .or_else(|| impl_.inner_impl().for_.def_id(cache)); + .or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache)); let provided_methods; let assoc_link = if let Some(target_did) = target_did { provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx()); @@ -720,7 +716,7 @@ impl TraitAliasPart { } fn get( - cx: &mut Context<'_>, + cx: &Context<'_>, crate_name_json: &OrderedJson, ) -> Result, Error> { let cache = &cx.shared.cache; @@ -828,8 +824,7 @@ struct TypeImplCollector<'cx, 'cache, 'item> { /// Map from DefId-of-aliased-type to its data. aliased_types: IndexMap>, visited_aliases: FxHashSet, - cache: &'cache Cache, - cx: &'cache mut Context<'cx>, + cx: &'cache Context<'cx>, } /// Data for an aliased type. @@ -868,7 +863,7 @@ struct AliasedTypeImpl<'cache, 'item> { impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { fn visit_item(&mut self, it: &'item Item) { self.visit_item_recur(it); - let cache = self.cache; + let cache = &self.cx.shared.cache; let ItemKind::TypeAliasItem(ref t) = it.kind else { return }; let Some(self_did) = it.item_id.as_def_id() else { return }; if !self.visited_aliases.insert(self_did) { diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 71b110c943e2..c37506e35883 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::ffi::OsStr; use std::ops::RangeInclusive; use std::path::{Component, Path, PathBuf}; -use std::rc::Rc; use std::{fmt, fs}; use rinja::Template; @@ -197,7 +196,7 @@ impl SourceCollector<'_, '_> { // Remove the utf-8 BOM if any let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents); - let shared = Rc::clone(&self.cx.shared); + let shared = &self.cx.shared; // Create the intermediate directories let cur = RefCell::new(PathBuf::new()); let root_path = RefCell::new(PathBuf::new()); @@ -250,12 +249,11 @@ impl SourceCollector<'_, '_> { &page, "", |buf: &mut _| { - let cx = &mut self.cx; print_src( buf, contents, file_span, - cx, + self.cx, &root_path, highlight::DecorationInfo::default(), SourceContext::Standalone { file_path }, From 5f9e71627c860058e30c0bc1f8cd4c42de5083ce Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 27 Nov 2024 14:30:01 +0100 Subject: [PATCH 268/330] Add documentation for new `FormatRenderer` trait items --- src/librustdoc/formats/renderer.rs | 26 ++++++++++++++++++++++++-- src/librustdoc/html/render/context.rs | 6 ++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index f7ba5bff51bf..8ae3cad74e32 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -17,6 +17,17 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { /// /// This is true for html, and false for json. See #80664 const RUN_ON_MODULE: bool; + /// This associated type is the type where the current module information is stored. + /// + /// For each module, we go through their items by calling for each item: + /// + /// 1. make_child_renderer + /// 2. item + /// 3. set_back_info + /// + /// However,the `item` method might update information in `self` (for example if the child is + /// a module). To prevent it to impact the other children of the current module, we need to + /// reset the information between each call to `item` by using `set_back_info`. type InfoType; /// Sets up any state required for the renderer. When this is called the cache has already been @@ -28,9 +39,20 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error>; - /// Make a new renderer to render a child of the item currently being rendered. + /// This method is called right before call [`Self::item`]. This method returns a type + /// containing information that needs to be reset after the [`Self::item`] method has been + /// called with the [`Self::set_back_info`] method. + /// + /// In short it goes like this: + /// + /// ```ignore (not valid code) + /// let reset_data = type.make_child_renderer(); + /// type.item(item)?; + /// type.set_back_info(reset_data); + /// ``` fn make_child_renderer(&mut self) -> Self::InfoType; - fn set_back_info(&mut self, _info: Self::InfoType); + /// Used to reset current module's information. + fn set_back_info(&mut self, info: Self::InfoType); /// Renders a single non-module item. This means no recursive sub-item rendering is required. fn item(&mut self, item: clean::Item) -> Result<(), Error>; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 81a9cce80d12..c2d0bc915b03 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -66,6 +66,12 @@ pub(crate) struct Context<'tcx> { pub(crate) info: ContextInfo, } +/// This struct contains the information that needs to be reset between each +/// [`FormatRenderer::render_item`] call. +/// +/// When we enter a new module, we set these values for the whole module but they might be updated +/// in each child item (especially if it's a module). So to prevent these changes to impact other +/// items rendering in the same module, we need to reset them to the module's set values. #[derive(Clone, Copy)] pub(crate) struct ContextInfo { /// A flag, which when `true`, will render pages which redirect to the From e60a7a4c24477cfadacb21926a4020b7bbf811e4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Nov 2024 14:38:41 +0100 Subject: [PATCH 269/330] Add `unreachable!` in new `FormatRenderer` methods for `JsonRenderer` implementation --- src/librustdoc/json/mod.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 9e512e87afc4..dd190be892ff 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -162,8 +162,13 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { )) } - fn make_child_renderer(&mut self) -> Self::InfoType {} - fn set_back_info(&mut self, _info: Self::InfoType) {} + fn make_child_renderer(&mut self) -> Self::InfoType { + unreachable!("RUN_ON_MODULE = false should never call make_child_renderer") + } + + fn set_back_info(&mut self, _info: Self::InfoType) { + unreachable!("RUN_ON_MODULE = false should never call set_back_info") + } /// Inserts an item into the index. This should be used rather than directly calling insert on /// the hashmap because certain items (traits and types) need to have their mappings for trait From b4921706f03cc432ced38f071f2d7d4517275d98 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 28 Nov 2024 14:57:10 +0100 Subject: [PATCH 270/330] Rename `FormatRenderer::InfoType` into `ModuleData` and rename `FormatRenderer::make_child_renderer` into `save_module_data` --- src/librustdoc/formats/renderer.rs | 12 ++++++------ src/librustdoc/html/render/context.rs | 6 +++--- src/librustdoc/json/mod.rs | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 8ae3cad74e32..582ef7d2c482 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -21,14 +21,14 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { /// /// For each module, we go through their items by calling for each item: /// - /// 1. make_child_renderer + /// 1. save_module_data /// 2. item /// 3. set_back_info /// /// However,the `item` method might update information in `self` (for example if the child is /// a module). To prevent it to impact the other children of the current module, we need to /// reset the information between each call to `item` by using `set_back_info`. - type InfoType; + type ModuleData; /// Sets up any state required for the renderer. When this is called the cache has already been /// populated. @@ -46,13 +46,13 @@ pub(crate) trait FormatRenderer<'tcx>: Sized { /// In short it goes like this: /// /// ```ignore (not valid code) - /// let reset_data = type.make_child_renderer(); + /// let reset_data = type.save_module_data(); /// type.item(item)?; /// type.set_back_info(reset_data); /// ``` - fn make_child_renderer(&mut self) -> Self::InfoType; + fn save_module_data(&mut self) -> Self::ModuleData; /// Used to reset current module's information. - fn set_back_info(&mut self, info: Self::InfoType); + fn set_back_info(&mut self, info: Self::ModuleData); /// Renders a single non-module item. This means no recursive sub-item rendering is required. fn item(&mut self, item: clean::Item) -> Result<(), Error>; @@ -89,7 +89,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>( unreachable!() }; for it in module.items { - let info = cx.make_child_renderer(); + let info = cx.save_module_data(); run_format_inner(cx, it, prof)?; cx.set_back_info(info); } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index c2d0bc915b03..b1da39b6b95f 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -454,7 +454,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } const RUN_ON_MODULE: bool = true; - type InfoType = ContextInfo; + type ModuleData = ContextInfo; fn init( krate: clean::Crate, @@ -594,14 +594,14 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { Ok((cx, krate)) } - fn make_child_renderer(&mut self) -> Self::InfoType { + fn save_module_data(&mut self) -> Self::ModuleData { self.deref_id_map.borrow_mut().clear(); self.id_map.borrow_mut().clear(); self.types_with_notable_traits.borrow_mut().clear(); self.info } - fn set_back_info(&mut self, info: Self::InfoType) { + fn set_back_info(&mut self, info: Self::ModuleData) { self.info = info; } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index dd190be892ff..9efcf6b4983b 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -137,7 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { } const RUN_ON_MODULE: bool = false; - type InfoType = (); + type ModuleData = (); fn init( krate: clean::Crate, @@ -162,11 +162,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { )) } - fn make_child_renderer(&mut self) -> Self::InfoType { - unreachable!("RUN_ON_MODULE = false should never call make_child_renderer") + fn save_module_data(&mut self) -> Self::ModuleData { + unreachable!("RUN_ON_MODULE = false should never call save_module_data") } - fn set_back_info(&mut self, _info: Self::InfoType) { + fn set_back_info(&mut self, _info: Self::ModuleData) { unreachable!("RUN_ON_MODULE = false should never call set_back_info") } From 69ed026f7ea8c5df73c99314379c40f0b79012e0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Dec 2024 11:06:12 +0100 Subject: [PATCH 271/330] Fix link to `FormatRenderer` method --- src/librustdoc/html/render/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index b1da39b6b95f..40468aef4db3 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -67,7 +67,7 @@ pub(crate) struct Context<'tcx> { } /// This struct contains the information that needs to be reset between each -/// [`FormatRenderer::render_item`] call. +/// [`FormatRenderer::item`] call. /// /// When we enter a new module, we set these values for the whole module but they might be updated /// in each child item (especially if it's a module). So to prevent these changes to impact other From 51ea7c12e70244dc89893888f3bfd6cead59d4c5 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sun, 1 Dec 2024 21:37:18 +0000 Subject: [PATCH 272/330] rustdoc-json: Add tests for `static`s --- tests/rustdoc-json/statics/statics.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/rustdoc-json/statics/statics.rs diff --git a/tests/rustdoc-json/statics/statics.rs b/tests/rustdoc-json/statics/statics.rs new file mode 100644 index 000000000000..e3ed93699256 --- /dev/null +++ b/tests/rustdoc-json/statics/statics.rs @@ -0,0 +1,10 @@ +//@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"' +//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false +//@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"' +pub static A: i32 = 5; + +//@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"' +//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true +// Expr value isn't gaurenteed, it'd be fine to change it. +//@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"' +pub static mut B: u32 = 2 + 3; From 7f011a894fca7b47a9f29e1220ed10fc6a0f80ce Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:37:36 -0400 Subject: [PATCH 273/330] Mark `slice::copy_from_slice` unstably const --- library/core/src/slice/mod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index a24417dba8cc..02edbdbed032 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -11,6 +11,7 @@ use crate::intrinsics::{exact_div, select_unpredictable, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds, RangeInclusive}; +use crate::panic::const_panic; use crate::simd::{self, Simd}; use crate::ub_checks::assert_unsafe_precondition; use crate::{fmt, hint, ptr, range, slice}; @@ -3703,8 +3704,9 @@ impl [T] { /// [`split_at_mut`]: slice::split_at_mut #[doc(alias = "memcpy")] #[stable(feature = "copy_from_slice", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_copy_from_slice", issue = "131415")] #[track_caller] - pub fn copy_from_slice(&mut self, src: &[T]) + pub const fn copy_from_slice(&mut self, src: &[T]) where T: Copy, { @@ -3713,11 +3715,13 @@ impl [T] { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] - fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { - panic!( - "source slice length ({}) does not match destination slice length ({})", - src_len, dst_len, - ); + const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! { + const_panic!( + "copy_from_slice: source slice length does not match destination slice length", + "copy_from_slice: source slice length ({src_len}) does not match destination slice length ({dst_len})", + src_len: usize, + dst_len: usize, + ) } if self.len() != src.len() { From f33dba028704d108497b8c06943b9bbc3d14c42b Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sun, 1 Dec 2024 21:39:58 +0000 Subject: [PATCH 274/330] rustdoc-json: Include safety of `static`s --- src/librustdoc/json/conversions.rs | 29 +++++++++++--------- src/rustdoc-json-types/lib.rs | 18 ++++++++++++- tests/rustdoc-json/statics/extern.rs | 39 +++++++++++++++++++++++++++ tests/rustdoc-json/statics/statics.rs | 2 ++ 4 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 tests/rustdoc-json/statics/extern.rs diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 1c8303d4c208..bb967b7f163e 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -321,8 +321,8 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum { MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)), TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)), ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)), - StaticItem(s) => ItemEnum::Static(s.into_json(renderer)), - ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)), + StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)), + ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)), ForeignTypeItem => ItemEnum::ExternType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)), // FIXME(generic_const_items): Add support for generic free consts @@ -831,17 +831,20 @@ impl FromClean> for TypeAlias { } } -impl FromClean for Static { - fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self { - let tcx = renderer.tcx; - Static { - type_: (*stat.type_).into_json(renderer), - is_mutable: stat.mutability == ast::Mutability::Mut, - expr: stat - .expr - .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) - .unwrap_or_default(), - } +fn convert_static( + stat: clean::Static, + safety: rustc_hir::Safety, + renderer: &JsonRenderer<'_>, +) -> Static { + let tcx = renderer.tcx; + Static { + type_: (*stat.type_).into_json(renderer), + is_mutable: stat.mutability == ast::Mutability::Mut, + is_unsafe: safety == rustc_hir::Safety::Unsafe, + expr: stat + .expr + .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) + .unwrap_or_default(), } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index f553a78d766e..84b33e3d8606 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap = HashMap; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 36; +pub const FORMAT_VERSION: u32 = 37; /// The root of the emitted JSON blob. /// @@ -1238,6 +1238,22 @@ pub struct Static { /// /// It's not guaranteed that it'll match the actual source code for the initial value. pub expr: String, + + /// Is the static `unsafe`? + /// + /// This is only true if it's in an `extern` block, and not explicity marked + /// as `safe`. + /// + /// ```rust + /// unsafe extern { + /// static A: i32; // unsafe + /// safe static B: i32; // safe + /// } + /// + /// static C: i32 = 0; // safe + /// static mut D: i32 = 0; // safe + /// ``` + pub is_unsafe: bool, } /// A primitive type declaration. Declarations of this kind can only come from the core library. diff --git a/tests/rustdoc-json/statics/extern.rs b/tests/rustdoc-json/statics/extern.rs new file mode 100644 index 000000000000..d38fdf1cd1cd --- /dev/null +++ b/tests/rustdoc-json/statics/extern.rs @@ -0,0 +1,39 @@ +// ignore-tidy-linelength +//@ edition: 2021 + +extern "C" { + //@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false + pub static A: i32; + //@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true + pub static mut B: i32; + + // items in unadorned `extern` blocks cannot have safety qualifiers +} + +unsafe extern "C" { + //@ is '$.index[*][?(@.name=="C")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="C")].inner.static.is_mutable' false + pub static C: i32; + //@ is '$.index[*][?(@.name=="D")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="D")].inner.static.is_mutable' true + pub static mut D: i32; + + //@ is '$.index[*][?(@.name=="E")].inner.static.is_unsafe' false + //@ is '$.index[*][?(@.name=="E")].inner.static.is_mutable' false + pub safe static E: i32; + //@ is '$.index[*][?(@.name=="F")].inner.static.is_unsafe' false + //@ is '$.index[*][?(@.name=="F")].inner.static.is_mutable' true + pub safe static mut F: i32; + + //@ is '$.index[*][?(@.name=="G")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="G")].inner.static.is_mutable' false + pub unsafe static G: i32; + //@ is '$.index[*][?(@.name=="H")].inner.static.is_unsafe' true + //@ is '$.index[*][?(@.name=="H")].inner.static.is_mutable' true + pub unsafe static mut H: i32; +} + +//@ ismany '$.index[*][?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""' +//@ ismany '$.index[*][?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' diff --git a/tests/rustdoc-json/statics/statics.rs b/tests/rustdoc-json/statics/statics.rs index e3ed93699256..a8af23cc87dc 100644 --- a/tests/rustdoc-json/statics/statics.rs +++ b/tests/rustdoc-json/statics/statics.rs @@ -1,10 +1,12 @@ //@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"' //@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false //@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"' +//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' false pub static A: i32 = 5; //@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"' //@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true // Expr value isn't gaurenteed, it'd be fine to change it. //@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"' +//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' false pub static mut B: u32 = 2 + 3; From fd1371781540c3b58bb3ee0f0ce17ad134b11926 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 21:56:38 +0100 Subject: [PATCH 275/330] rust_analyzer_settings: force use of 'nightly' toolchain --- src/bootstrap/src/core/build_steps/setup.rs | 1 + src/etc/rust_analyzer_settings.json | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 704fa46ab1ee..3a8f9e48c0da 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -572,6 +572,7 @@ Select which editor you would like to set up [default: None]: "; "828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000", "811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d", "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4", + "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d", ], EditorKind::Emacs => vec![ "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index d1b186fd316d..b104356d44cb 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -34,5 +34,8 @@ "rust-analyzer.rustc.source": "./Cargo.toml", "rust-analyzer.cargo.extraEnv": { "RUSTC_BOOTSTRAP": "1" + }, + "rust-analyzer.server.extraEnv": { + "RUSTUP_TOOLCHAIN": "nightly" } } From b5d73fc16739abd2982af2e49de1e143bf7248e3 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sun, 1 Dec 2024 23:13:57 +0000 Subject: [PATCH 276/330] rustdoc-json: Add test for `impl Trait for dyn Trait` --- tests/rustdoc-json/impls/trait-for-dyn-trait.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/rustdoc-json/impls/trait-for-dyn-trait.rs diff --git a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs new file mode 100644 index 000000000000..0fbb4df00284 --- /dev/null +++ b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs @@ -0,0 +1,15 @@ +//@ set t1 = '$.index[*][?(@.name=="T1")].id' +pub trait T1 {} + +//@ set t2 = '$.index[*][?(@.name=="T2")].id' +pub trait T2 {} + +/// Fun impl +impl T1 for dyn T2 {} + +//@ set impl = '$.index[*][?(@.docs=="Fun impl")].id' +//@ is '$.index[*][?(@.name=="T1")].inner.trait.implementations[*]' $impl +//@ is '$.index[*][?(@.name=="T2")].inner.trait.implementations' [] + +//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.trait.id' $t1 +//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2 From 2f17ea0ff53ddedfa659b1173e5bbbd57fb0231d Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 1 Dec 2024 21:47:20 -0500 Subject: [PATCH 277/330] Remove `//@ compare-output-lines-by-subset` There was only ever one test which used this flag, and it was removed in https://github.com/rust-lang/rust/pull/132244. I think this is a bad flag that should never have been added; comparing by subset makes the test failures extremely hard to debug. Any test that needs complicated output filtering like this should just use run-make instead. Note that this does not remove the underlying comparison code, because it's still used if `runner` is set. I don't quite understand what's going on there, but since we still test on other platforms and in CI that the full output is accurate, I think it will be easier to debug than a test that uses compare-by-subset unconditionally. --- src/tools/compiletest/src/directive-list.rs | 1 - src/tools/compiletest/src/header.rs | 10 ---------- src/tools/compiletest/src/runtest.rs | 11 ++++------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 952533e904c5..f3f769714641 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -17,7 +17,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-run-results", "check-stdout", "check-test-line-numbers-match", - "compare-output-lines-by-subset", "compile-flags", "doc-flags", "dont-check-compiler-stderr", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fe4c5fdd8b51..73e56cfac8f6 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -115,9 +115,6 @@ pub struct TestProps { pub dont_check_compiler_stdout: bool, // For UI tests, allows compiler to generate arbitrary output to stderr pub dont_check_compiler_stderr: bool, - // When checking the output of stdout or stderr check - // that the lines of expected output are a subset of the actual output. - pub compare_output_lines_by_subset: bool, // Don't force a --crate-type=dylib flag on the command line // // Set this for example if you have an auxiliary test file that contains @@ -240,7 +237,6 @@ mod directives { pub const KNOWN_BUG: &'static str = "known-bug"; pub const TEST_MIR_PASS: &'static str = "test-mir-pass"; pub const REMAP_SRC_BASE: &'static str = "remap-src-base"; - pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset"; pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags"; pub const FILECHECK_FLAGS: &'static str = "filecheck-flags"; pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg"; @@ -274,7 +270,6 @@ impl TestProps { check_run_results: false, dont_check_compiler_stdout: false, dont_check_compiler_stderr: false, - compare_output_lines_by_subset: false, no_prefer_dynamic: false, pretty_mode: "normal".to_string(), pretty_compare_only: false, @@ -550,11 +545,6 @@ impl TestProps { |s| s.trim().to_string(), ); config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base); - config.set_name_directive( - ln, - COMPARE_OUTPUT_LINES_BY_SUBSET, - &mut self.compare_output_lines_by_subset, - ); if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) { self.llvm_cov_flags.extend(split_flags(&flags)); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 93e5980f1f5f..7be9e2f2d577 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2541,13 +2541,10 @@ impl<'test> TestCx<'test> { return 0; } - // If `compare-output-lines-by-subset` is not explicitly enabled then - // auto-enable it when a `runner` is in use since wrapper tools might - // provide extra output on failure, for example a WebAssembly runtime - // might print the stack trace of an `unreachable` instruction by - // default. - let compare_output_by_lines = - self.props.compare_output_lines_by_subset || self.config.runner.is_some(); + // Wrapper tools set by `runner` might provide extra output on failure, + // for example a WebAssembly runtime might print the stack trace of an + // `unreachable` instruction by default. + let compare_output_by_lines = self.config.runner.is_some(); let tmp; let (expected, actual): (&str, &str) = if compare_output_by_lines { From 855c04efe7ac766b67386f1528ce4415213ae042 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Sun, 1 Dec 2024 22:07:51 -0500 Subject: [PATCH 278/330] Update mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index fdb62a9d7782..874a42656c51 100644 --- a/.mailmap +++ b/.mailmap @@ -254,6 +254,7 @@ Jack Huey Jacob Jacob Greenfield Jacob Pratt +Jacob Pratt Jake Vossen Jakob Degen Jakob Lautrup Nysom From d37ed10634131dd678697609f9060aaba8bacd41 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 29 Nov 2024 07:00:42 +1100 Subject: [PATCH 279/330] Fix crash with `-Zdump-mir-dataflow` As of #133155 `Formatter:new` uses `as_results_cursor` to create a non-mutable results reference, and then later that is accessed via `deref_mut` which results in a runtime abort. Changing to `as_results_cursor_mut` fixes it. Fixes #133641. --- compiler/rustc_mir_dataflow/src/framework/graphviz.rs | 4 ++-- compiler/rustc_mir_dataflow/src/framework/mod.rs | 4 ++-- compiler/rustc_mir_dataflow/src/framework/results.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 6e4994af8b4e..ecb1ab7f2ba7 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -47,11 +47,11 @@ where { pub(crate) fn new( body: &'mir Body<'tcx>, - results: &'mir Results<'tcx, A>, + results: &'mir mut Results<'tcx, A>, style: OutputStyle, ) -> Self { let reachable = mir::traversal::reachable_as_bitset(body); - Formatter { cursor: results.as_results_cursor(body).into(), style, reachable } + Formatter { cursor: results.as_results_cursor_mut(body).into(), style, reachable } } fn body(&self) -> &'mir Body<'tcx> { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index f1ea94e16893..b9407882ec5d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -281,10 +281,10 @@ pub trait Analysis<'tcx> { ); } - let results = Results { analysis: self, entry_sets }; + let mut results = Results { analysis: self, entry_sets }; if tcx.sess.opts.unstable_opts.dump_mir_dataflow { - let res = write_graphviz_results(tcx, body, &results, pass_name); + let res = write_graphviz_results(tcx, body, &mut results, pass_name); if let Err(e) = res { error!("Failed to write graphviz dataflow results: {}", e); } diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 8493a7aa44bb..72e9d4dba571 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -95,7 +95,7 @@ where pub(super) fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, - results: &Results<'tcx, A>, + results: &mut Results<'tcx, A>, pass_name: Option<&'static str>, ) -> std::io::Result<()> where From 9f2f6906ffe05d63488f717694bdb9e8d2fb8815 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Dec 2024 10:50:06 +1100 Subject: [PATCH 280/330] Add test for `-Zdump-mir-dataflow`. --- tests/mir-opt/dataflow.main.maybe_init.borrowck.dot | 6 ++++++ tests/mir-opt/dataflow.rs | 6 ++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/mir-opt/dataflow.main.maybe_init.borrowck.dot create mode 100644 tests/mir-opt/dataflow.rs diff --git a/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot new file mode 100644 index 000000000000..7c7d8921fb36 --- /dev/null +++ b/tests/mir-opt/dataflow.main.maybe_init.borrowck.dot @@ -0,0 +1,6 @@ +digraph graph_for_def_id_0_3 { + graph[fontname="Courier, monospace"]; + node[fontname="Courier, monospace"]; + edge[fontname="Courier, monospace"]; + bb_0[label=<
bb0
MIRSTATE
(on start){}
0_0 = const ()+_0
Treturn
(on end){_0}
>][shape="none"]; +} diff --git a/tests/mir-opt/dataflow.rs b/tests/mir-opt/dataflow.rs new file mode 100644 index 000000000000..3a28f5d47b9a --- /dev/null +++ b/tests/mir-opt/dataflow.rs @@ -0,0 +1,6 @@ +// skip-filecheck +// Test graphviz dataflow output +//@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow + +// EMIT_MIR dataflow.main.maybe_init.borrowck.dot +fn main() {} From cecef131a259320efb0a7d693ef4c594a3d93241 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Dec 2024 10:58:27 +1100 Subject: [PATCH 281/330] Simplify `ResultsHandle`. The `Borrowed` variant is no longer used. This commit removes it, along with the `as_results_cursor` method that produces it, and renames `as_results_cursor_mut` as `as_results_cursor`. --- compiler/rustc_mir_dataflow/src/framework/cursor.rs | 5 ----- .../rustc_mir_dataflow/src/framework/graphviz.rs | 2 +- .../rustc_mir_dataflow/src/framework/results.rs | 13 ++----------- compiler/rustc_mir_transform/src/coroutine.rs | 2 +- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs index 11cf8c3e8984..4a9bcdaddb31 100644 --- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs @@ -15,7 +15,6 @@ pub enum ResultsHandle<'a, 'tcx, A> where A: Analysis<'tcx>, { - Borrowed(&'a Results<'tcx, A>), BorrowedMut(&'a mut Results<'tcx, A>), Owned(Results<'tcx, A>), } @@ -28,7 +27,6 @@ where fn deref(&self) -> &Results<'tcx, A> { match self { - ResultsHandle::Borrowed(borrowed) => borrowed, ResultsHandle::BorrowedMut(borrowed) => borrowed, ResultsHandle::Owned(owned) => owned, } @@ -41,9 +39,6 @@ where { fn deref_mut(&mut self) -> &mut Results<'tcx, A> { match self { - ResultsHandle::Borrowed(_borrowed) => { - panic!("tried to deref_mut a `ResultsHandle::Borrowed") - } ResultsHandle::BorrowedMut(borrowed) => borrowed, ResultsHandle::Owned(owned) => owned, } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index ecb1ab7f2ba7..561229cf7255 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -51,7 +51,7 @@ where style: OutputStyle, ) -> Self { let reachable = mir::traversal::reachable_as_bitset(body); - Formatter { cursor: results.as_results_cursor_mut(body).into(), style, reachable } + Formatter { cursor: results.as_results_cursor(body).into(), style, reachable } } fn body(&self) -> &'mir Body<'tcx> { diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 72e9d4dba571..c4321c454e6e 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -37,18 +37,9 @@ impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, { - /// Creates a `ResultsCursor` that can inspect these `Results`. Immutably borrows the `Results`, - /// which is appropriate when the `Results` is used outside the cursor. + /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the + /// `Results` is also used outside the cursor. pub fn as_results_cursor<'mir>( - &'mir self, - body: &'mir mir::Body<'tcx>, - ) -> ResultsCursor<'mir, 'tcx, A> { - ResultsCursor::new(body, ResultsHandle::Borrowed(self)) - } - - /// Creates a `ResultsCursor` that can mutate these `Results`. Mutably borrows the `Results`, - /// which is appropriate when the `Results` is used outside the cursor. - pub fn as_results_cursor_mut<'mir>( &'mir mut self, body: &'mir mir::Body<'tcx>, ) -> ResultsCursor<'mir, 'tcx, A> { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 9b9aeccf8909..858752a3f01c 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -680,7 +680,7 @@ fn locals_live_across_suspend_points<'tcx>( let mut requires_storage_results = MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body)) .iterate_to_fixpoint(tcx, body, None); - let mut requires_storage_cursor = requires_storage_results.as_results_cursor_mut(body); + let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body); // Calculate the liveness of MIR locals ignoring borrows. let mut liveness = From 7610aa55590575671d203aa5afa8c27ab73fcf3a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 7 Nov 2024 20:02:09 +0800 Subject: [PATCH 282/330] Unify `sysroot_target_{bin,lib}dir` handling --- src/bootstrap/src/core/builder/mod.rs | 95 +++++++++++++------------ src/bootstrap/src/core/builder/tests.rs | 46 ++++++++++++ 2 files changed, 96 insertions(+), 45 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 73bc7195ac24..026c26479d35 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -765,6 +765,54 @@ impl Kind { } } +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +struct Libdir { + compiler: Compiler, + target: TargetSelection, +} + +impl Step for Libdir { + type Output = PathBuf; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.never() + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + let relative_sysroot_libdir = builder.sysroot_libdir_relative(self.compiler); + let sysroot = builder.sysroot(self.compiler).join(relative_sysroot_libdir).join("rustlib"); + + if !builder.config.dry_run() { + // Avoid deleting the `rustlib/` directory we just copied (in `impl Step for + // Sysroot`). + if !builder.download_rustc() { + let sysroot_target_libdir = sysroot.join(self.target).join("lib"); + builder.verbose(|| { + eprintln!( + "Removing sysroot {} to avoid caching bugs", + sysroot_target_libdir.display() + ) + }); + let _ = fs::remove_dir_all(&sysroot_target_libdir); + t!(fs::create_dir_all(&sysroot_target_libdir)); + } + + if self.compiler.stage == 0 { + // The stage 0 compiler for the build triple is always pre-built. Ensure that + // `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use + // it when run. + dist::maybe_install_llvm_target( + builder, + self.compiler.host, + &builder.sysroot(self.compiler), + ); + } + } + + sysroot + } +} + impl<'a> Builder<'a> { fn get_step_descriptions(kind: Kind) -> Vec { macro_rules! describe { @@ -1165,56 +1213,13 @@ impl<'a> Builder<'a> { /// Returns the bindir for a compiler's sysroot. pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { - self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin") + self.ensure(Libdir { compiler, target }).join(target).join("bin") } /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { - #[derive(Debug, Clone, Hash, PartialEq, Eq)] - struct Libdir { - compiler: Compiler, - target: TargetSelection, - } - impl Step for Libdir { - type Output = PathBuf; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.never() - } - - fn run(self, builder: &Builder<'_>) -> PathBuf { - let lib = builder.sysroot_libdir_relative(self.compiler); - let sysroot = builder - .sysroot(self.compiler) - .join(lib) - .join("rustlib") - .join(self.target) - .join("lib"); - // Avoid deleting the rustlib/ directory we just copied - // (in `impl Step for Sysroot`). - if !builder.download_rustc() { - builder.verbose(|| { - println!("Removing sysroot {} to avoid caching bugs", sysroot.display()) - }); - let _ = fs::remove_dir_all(&sysroot); - t!(fs::create_dir_all(&sysroot)); - } - - if self.compiler.stage == 0 { - // The stage 0 compiler for the build triple is always pre-built. - // Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run. - dist::maybe_install_llvm_target( - builder, - self.compiler.host, - &builder.sysroot(self.compiler), - ); - } - - sysroot - } - } - self.ensure(Libdir { compiler, target }) + self.ensure(Libdir { compiler, target }).join(target).join("lib") } pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index a1c8bff0db97..b2ffbd9c70f6 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -738,3 +738,49 @@ mod dist { ]); } } + +mod sysroot_target_dirs { + use super::{ + Build, Builder, Compiler, TEST_TRIPLE_1, TEST_TRIPLE_2, TargetSelection, configure, + }; + + #[test] + fn test_sysroot_target_libdir() { + let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); + let builder = Builder::new(&build); + let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1); + let compiler = Compiler { stage: 1, host: target_triple_1 }; + let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2); + let actual = builder.sysroot_target_libdir(compiler, target_triple_2); + + assert_eq!( + builder + .sysroot(compiler) + .join(builder.sysroot_libdir_relative(compiler)) + .join("rustlib") + .join(TEST_TRIPLE_2) + .join("lib"), + actual + ); + } + + #[test] + fn test_sysroot_target_bindir() { + let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1])); + let builder = Builder::new(&build); + let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1); + let compiler = Compiler { stage: 1, host: target_triple_1 }; + let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2); + let actual = builder.sysroot_target_bindir(compiler, target_triple_2); + + assert_eq!( + builder + .sysroot(compiler) + .join(builder.sysroot_libdir_relative(compiler)) + .join("rustlib") + .join(TEST_TRIPLE_2) + .join("bin"), + actual + ); + } +} From 267dcb28c289209462aa9695fa06e77ba532a4b1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 1 Dec 2024 15:37:39 -0800 Subject: [PATCH 283/330] Add pretty-printer parenthesis insertion test --- .../pprust-parenthesis-insertion.rs | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 tests/ui-fulldeps/pprust-parenthesis-insertion.rs diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs new file mode 100644 index 000000000000..fd6644d73c16 --- /dev/null +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -0,0 +1,242 @@ +//@ run-pass +//@ ignore-cross-compile + +// This test covers the AST pretty-printer's automatic insertion of parentheses +// into unparenthesized syntax trees according to precedence and various grammar +// restrictions and edge cases. +// +// For example if the following syntax tree represents the expression a*(b+c), +// in which the parenthesis is necessary for precedence: +// +// Binary('*', Path("a"), Paren(Binary('+', Path("b"), Path("c")))) +// +// then the pretty-printer needs to be able to print the following +// unparenthesized syntax tree with an automatically inserted parenthesization. +// +// Binary('*', Path("a"), Binary('+', Path("b"), Path("c"))) +// +// Handling this correctly is relevant in real-world code when pretty-printing +// macro-generated syntax trees, in which expressions can get interpolated into +// one another without any parenthesization being visible in the syntax tree. +// +// macro_rules! repro { +// ($rhs:expr) => { +// a * $rhs +// }; +// } +// +// let _ = repro!(b + c); + +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_ast_pretty; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate rustc_parse; +extern crate rustc_session; +extern crate rustc_span; +extern crate smallvec; + +use std::mem; +use std::process::ExitCode; + +use rustc_ast::ast::{DUMMY_NODE_ID, Expr, ExprKind, Stmt}; +use rustc_ast::mut_visit::{self, DummyAstNode as _, MutVisitor}; +use rustc_ast::node_id::NodeId; +use rustc_ast::ptr::P; +use rustc_ast_pretty::pprust; +use rustc_errors::Diag; +use rustc_parse::parser::Recovery; +use rustc_session::parse::ParseSess; +use rustc_span::{DUMMY_SP, FileName, Span}; +use smallvec::SmallVec; + +// Every parenthesis in the following expressions is re-inserted by the +// pretty-printer. +// +// FIXME: Some of them shouldn't be. +static EXPRS: &[&str] = &[ + // Straightforward binary operator precedence. + "2 * 2 + 2", + "2 + 2 * 2", + "(2 + 2) * 2", + "2 * (2 + 2)", + "2 + 2 + 2", + // Return has lower precedence than a binary operator. + "(return 2) + 2", + "2 + (return 2)", // FIXME: no parenthesis needed. + "(return) + 2", // FIXME: no parenthesis needed. + // These mean different things. + "return - 2", + "(return) - 2", + // These mean different things. + "if let _ = true && false {}", + "if let _ = (true && false) {}", + // Conditions end at the first curly brace, so struct expressions need to be + // parenthesized. Except in a match guard, where conditions end at arrow. + "if let _ = (Struct {}) {}", + "match 2 { _ if let _ = Struct {} => {} }", + // Match arms terminate eagerly, so parenthesization is needed around some + // expressions. + "match 2 { _ => 1 - 1 }", + "match 2 { _ => ({ 1 }) - 1 }", + // Grammar restriction: break value starting with a labeled loop is not + // allowed, except if the break is also labeled. + "break 'outer 'inner: loop {} + 2", + "break ('inner: loop {} + 2)", + // Grammar restriction: the value in let-else is not allowed to end in a + // curly brace. + "{ let _ = 1 + 1 else {}; }", + "{ let _ = (loop {}) else {}; }", + "{ let _ = mac!() else {}; }", + "{ let _ = (mac! {}) else {}; }", + // Parentheses are necessary to prevent an eager statement boundary. + "{ 2 - 1 }", + "{ (match 2 {}) - 1 }", + "{ (match 2 {})() - 1 }", + "{ (match 2 {})[0] - 1 }", + "{ (loop {}) - 1 }", + // Angle bracket is eagerly parsed as a path's generic argument list. + "(2 as T) < U", + "(2 as T) < V", // FIXME: no parentheses needed. + /* + // FIXME: pretty-printer produces invalid syntax. `2 + 2 as T < U` + "(2 + 2 as T) < U", + */ + /* + // FIXME: pretty-printer produces invalid syntax. `if (let _ = () && Struct {}.x) {}` + "if let _ = () && (Struct {}).x {}", + */ + /* + // FIXME: pretty-printer produces invalid syntax. `(1 < 2 == false) as usize` + "((1 < 2) == false) as usize", + */ + /* + // FIXME: pretty-printer produces invalid syntax. `for _ in 1..{ 2 } {}` + "for _ in (1..{ 2 }) {}", + */ + /* + // FIXME: pretty-printer loses the attribute. `{ let Struct { field } = s; }` + "{ let Struct { #[attr] field } = s; }", + */ + /* + // FIXME: pretty-printer turns this into a range. `0..to_string()` + "(0.).to_string()", + "0. .. 1.", + */ + /* + // FIXME: pretty-printer loses the dyn*. `i as Trait` + "i as dyn* Trait", + */ +]; + +// Flatten the content of parenthesis nodes into their parent node. For example +// this syntax tree representing the expression a*(b+c): +// +// Binary('*', Path("a"), Paren(Binary('+', Path("b"), Path("c")))) +// +// would unparenthesize to: +// +// Binary('*', Path("a"), Binary('+', Path("b"), Path("c"))) +struct Unparenthesize; + +impl MutVisitor for Unparenthesize { + fn visit_expr(&mut self, e: &mut P) { + while let ExprKind::Paren(paren) = &mut e.kind { + **e = mem::replace(&mut *paren, Expr::dummy()); + } + mut_visit::walk_expr(self, e); + } +} + +// Erase Span information that could distinguish between identical expressions +// parsed from different source strings. +struct Normalize; + +impl MutVisitor for Normalize { + const VISIT_TOKENS: bool = true; + + fn visit_id(&mut self, id: &mut NodeId) { + *id = DUMMY_NODE_ID; + } + + fn visit_span(&mut self, span: &mut Span) { + *span = DUMMY_SP; + } + + fn visit_expr(&mut self, expr: &mut P) { + if let ExprKind::Binary(binop, _left, _right) = &mut expr.kind { + self.visit_span(&mut binop.span); + } + mut_visit::walk_expr(self, expr); + } + + fn flat_map_stmt(&mut self, mut stmt: Stmt) -> SmallVec<[Stmt; 1]> { + self.visit_span(&mut stmt.span); + mut_visit::walk_flat_map_stmt(self, stmt) + } +} + +fn parse_expr(psess: &ParseSess, source_code: &str) -> Option> { + let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str( + psess, + FileName::anon_source_code(source_code), + source_code.to_owned(), + )); + + let mut expr = parser.recovery(Recovery::Forbidden).parse_expr().map_err(Diag::cancel).ok()?; + Normalize.visit_expr(&mut expr); + Some(expr) +} + +fn main() -> ExitCode { + let mut status = ExitCode::SUCCESS; + let mut fail = |description: &str, before: &str, after: &str| { + status = ExitCode::FAILURE; + eprint!( + "{description}\n BEFORE: {before}\n AFTER: {after}\n\n", + before = before.replace('\n', "\n "), + after = after.replace('\n', "\n "), + ); + }; + + rustc_span::create_default_session_globals_then(|| { + let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); + + for &source_code in EXPRS { + let expr = parse_expr(psess, source_code).unwrap(); + + // Check for FALSE POSITIVE: pretty-printer inserting parentheses where not needed. + // Pseudocode: + // assert(expr == parse(print(expr))) + let printed = &pprust::expr_to_string(&expr); + let Some(expr2) = parse_expr(psess, printed) else { + fail("Pretty-printer produced invalid syntax", source_code, printed); + continue; + }; + if format!("{expr:#?}") != format!("{expr2:#?}") { + fail("Pretty-printer inserted unnecessary parenthesis", source_code, printed); + continue; + } + + // Check for FALSE NEGATIVE: pretty-printer failing to place necessary parentheses. + // Pseudocode: + // assert(unparenthesize(expr) == unparenthesize(parse(print(unparenthesize(expr))))) + let mut expr = expr; + Unparenthesize.visit_expr(&mut expr); + let printed = &pprust::expr_to_string(&expr); + let Some(mut expr2) = parse_expr(psess, printed) else { + fail("Pretty-printer with no parens produced invalid syntax", source_code, printed); + continue; + }; + Unparenthesize.visit_expr(&mut expr2); + if format!("{expr:#?}") != format!("{expr2:#?}") { + fail("Pretty-printer lost necessary parentheses", source_code, printed); + continue; + } + } + }); + + status +} From 99e726b19490b489fb044902e3c2a487b6ff96a6 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 2 Dec 2024 08:40:00 +0300 Subject: [PATCH 284/330] add "optimized-compiler-builtins" option coverage for ci-rustc Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index cabd62dea9db..b06147055f2a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -3125,11 +3125,15 @@ fn check_incompatible_options_for_ci_rustc( }; } - err!( - current_config_toml.build.as_ref().and_then(|b| b.profiler), - ci_config_toml.build.as_ref().and_then(|b| b.profiler), - "build" - ); + let current_profiler = current_config_toml.build.as_ref().and_then(|b| b.profiler); + let profiler = ci_config_toml.build.as_ref().and_then(|b| b.profiler); + err!(current_profiler, profiler, "build"); + + let current_optimized_compiler_builtins = + current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins); + let optimized_compiler_builtins = + ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins); + err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build"); // We always build the in-tree compiler on cross targets, so we only care // about the host target here. @@ -3141,7 +3145,8 @@ fn check_incompatible_options_for_ci_rustc( "Target specific config for '{host_str}' is not present for CI-rustc" ))?; - err!(current_cfg.profiler, ci_cfg.profiler, "build"); + let profiler = &ci_cfg.profiler; + err!(current_cfg.profiler, profiler, "build"); } } From 99c232223f8330debc199f616308bc559b38c361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:48:01 +0800 Subject: [PATCH 285/330] Add `needs-target-has-atomic` directive Before this commit, the test writer has to specify platforms and architectures by hand for targets that have differing atomic width support. `#[cfg(target_has_atomic)]` is not quite the same because (1) you may have to specify additional matchers manually which has to be maintained individually, and (2) the `#[cfg]` blocks does not communicate to compiletest that a test would be ignored for a given target. This commit implements a `//@ needs-target-has-atomic` directive which admits a comma-separated list of required atomic widths that the target must satisfy in order for the test to run. ``` //@ needs-target-has-atomic: 8, 16, ptr ``` See . Co-authored-by: kei519 --- src/tools/compiletest/src/common.rs | 22 ++++++++- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header/needs.rs | 51 +++++++++++++++++++-- src/tools/compiletest/src/header/tests.rs | 37 +++++++++++++++ 4 files changed, 106 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index e6fbba943a48..36f876bcdc60 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::ffi::OsString; use std::path::{Path, PathBuf}; use std::process::Command; @@ -486,6 +486,9 @@ impl Config { } } +/// Known widths of `target_has_atomic`. +pub const KNOWN_TARGET_HAS_ATOMIC_WIDTHS: &[&str] = &["8", "16", "32", "64", "128", "ptr"]; + #[derive(Debug, Clone)] pub struct TargetCfgs { pub current: TargetCfg, @@ -611,6 +614,17 @@ impl TargetCfgs { ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort, ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind, ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"), + + ("target_has_atomic", Some(width)) + if KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width) => + { + cfg.target_has_atomic.insert(width.to_string()); + } + ("target_has_atomic", Some(other)) => { + panic!("unexpected value for `target_has_atomic` cfg: {other:?}") + } + // Nightly-only std-internal impl detail. + ("target_has_atomic", None) => {} _ => {} } } @@ -645,6 +659,12 @@ pub struct TargetCfg { pub(crate) xray: bool, #[serde(default = "default_reloc_model")] pub(crate) relocation_model: String, + + // Not present in target cfg json output, additional derived information. + #[serde(skip)] + /// Supported target atomic widths: e.g. `8` to `128` or `ptr`. This is derived from the builtin + /// `target_has_atomic` `cfg`s e.g. `target_has_atomic="8"`. + pub(crate) target_has_atomic: BTreeSet, } impl TargetCfg { diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 952533e904c5..c7e8d4b58a56 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -154,6 +154,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-thread", "needs-std-debug-assertions", "needs-symlink", + "needs-target-has-atomic", "needs-threads", "needs-unwind", "needs-wasmtime", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 77570c58db5c..e19dcd992fc2 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,4 +1,4 @@ -use crate::common::{Config, Sanitizer}; +use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; use crate::header::{IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( @@ -171,11 +171,54 @@ pub(super) fn handle_needs( }, ]; - let (name, comment) = match ln.split_once([':', ' ']) { - Some((name, comment)) => (name, Some(comment)), + let (name, rest) = match ln.split_once([':', ' ']) { + Some((name, rest)) => (name, Some(rest)), None => (ln, None), }; + // FIXME(jieyouxu): tighten up this parsing to reject using both `:` and ` ` as means to + // delineate value. + if name == "needs-target-has-atomic" { + let Some(rest) = rest else { + return IgnoreDecision::Error { + message: "expected `needs-target-has-atomic` to have a comma-separated list of atomic widths".to_string(), + }; + }; + + // Expect directive value to be a list of comma-separated atomic widths. + let specified_widths = rest + .split(',') + .map(|width| width.trim()) + .map(ToString::to_string) + .collect::>(); + + for width in &specified_widths { + if !KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width.as_str()) { + return IgnoreDecision::Error { + message: format!( + "unknown width specified in `needs-target-has-atomic`: `{width}` is not a \ + known `target_has_atomic_width`, known values are `{:?}`", + KNOWN_TARGET_HAS_ATOMIC_WIDTHS + ), + }; + } + } + + let satisfies_all_specified_widths = specified_widths + .iter() + .all(|specified| config.target_cfg().target_has_atomic.contains(specified)); + if satisfies_all_specified_widths { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!( + "skipping test as target does not support all of the required `target_has_atomic` widths `{:?}`", + specified_widths + ), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } @@ -193,7 +236,7 @@ pub(super) fn handle_needs( break; } else { return IgnoreDecision::Ignore { - reason: if let Some(comment) = comment { + reason: if let Some(comment) = rest { format!("{} ({})", need.ignore_reason, comment.trim()) } else { need.ignore_reason.into() diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 4d75c38dd320..cd7c6f8361ed 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -787,3 +787,40 @@ fn test_not_trailing_directive() { run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental"); assert!(!poisoned); } + +#[test] +fn test_needs_target_has_atomic() { + use std::collections::BTreeSet; + + // `x86_64-unknown-linux-gnu` supports `["8", "16", "32", "64", "ptr"]` but not `128`. + + let config = cfg().target("x86_64-unknown-linux-gnu").build(); + // Expectation sanity check. + assert_eq!( + config.target_cfg().target_has_atomic, + BTreeSet::from([ + "8".to_string(), + "16".to_string(), + "32".to_string(), + "64".to_string(), + "ptr".to_string() + ]), + "expected `x86_64-unknown-linux-gnu` to not have 128-bit atomic support" + ); + + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 16")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 32")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 64")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: ptr")); + + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 128")); + + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr")); + + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr,128")); + + // Check whitespace between widths is permitted. + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr")); + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr, 128")); +} From 1a976e01801d3cdec76b86c4adf626e1e2c8d446 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 2 Dec 2024 08:54:12 +0000 Subject: [PATCH 286/330] Re-add myself to rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 47b968240984..4d6806711fbc 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -996,7 +996,6 @@ warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", - "oli-obk", ] [assign.adhoc_groups] From b1ff3c8b924b911187d8fe456af03a6a197bb98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Mon, 2 Dec 2024 10:38:40 +0100 Subject: [PATCH 287/330] Fix docs for '<[T]>::as_array'; --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index bc49b7d97972..5ff888628af4 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -858,7 +858,7 @@ impl [T] { /// Gets a reference to the underlying array. /// - /// If `N` is not exactly equal to slice's the length of `self`, then this method returns `None`. + /// If `N` is not exactly equal to the length of `self`, then this method returns `None`. #[unstable(feature = "slice_as_array", issue = "133508")] #[rustc_const_unstable(feature = "slice_as_array", issue = "133508")] #[inline] From 778321d1559cfbfcf1868165b053cf73298dadfb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 2 Dec 2024 10:06:26 +0000 Subject: [PATCH 288/330] Change `AttrArgs::Eq` into a struct variant --- compiler/rustc_ast/src/ast.rs | 22 +++++++++---------- compiler/rustc_ast/src/attr/mod.rs | 12 +++++----- compiler/rustc_ast/src/mut_visit.rs | 4 ++-- compiler/rustc_ast/src/visit.rs | 4 ++-- compiler/rustc_ast_lowering/src/lib.rs | 6 ++--- compiler/rustc_ast_pretty/src/pprust/state.rs | 4 ++-- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/validate_attr.rs | 8 ++++--- compiler/rustc_resolve/src/rustdoc.rs | 2 +- .../traits/on_unimplemented.rs | 4 ++-- src/librustdoc/clean/mod.rs | 2 +- .../src/attrs/should_panic_without_expect.rs | 2 +- .../src/doc/include_in_doc_without_cfg.rs | 2 +- .../clippy_lints/src/large_include_file.rs | 2 +- .../clippy/clippy_utils/src/ast_utils.rs | 4 ++-- 16 files changed, 43 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 56b20e0ad893..2ab63f5fb79e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1733,12 +1733,12 @@ pub enum AttrArgs { /// Delimited arguments: `#[attr()/[]/{}]`. Delimited(DelimArgs), /// Arguments of a key-value attribute: `#[attr = "value"]`. - Eq( + Eq { /// Span of the `=` token. - Span, - /// The "value". - AttrArgsEq, - ), + eq_span: Span, + + value: AttrArgsEq, + }, } // The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro @@ -1755,8 +1755,8 @@ impl AttrArgs { match self { AttrArgs::Empty => None, AttrArgs::Delimited(args) => Some(args.dspan.entire()), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => Some(eq_span.to(expr.span)), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when getting span: {:?}", lit); } } @@ -1768,8 +1768,8 @@ impl AttrArgs { match self { AttrArgs::Empty => TokenStream::default(), AttrArgs::Delimited(args) => args.tokens.clone(), - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => TokenStream::from_ast(expr), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when getting inner tokens: {:?}", lit) } } @@ -1785,10 +1785,10 @@ where match self { AttrArgs::Empty => {} AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher), - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { unreachable!("hash_stable {:?}", expr); } - AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => { eq_span.hash_stable(ctx, hasher); lit.hash_stable(ctx, hasher); } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 888b13efa31a..0d79cadef34d 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -250,7 +250,7 @@ impl AttrItem { AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => { MetaItemKind::list_from_tokens(args.tokens.clone()) } - AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None, + AttrArgs::Delimited(_) | AttrArgs::Eq { .. } | AttrArgs::Empty => None, } } @@ -268,7 +268,7 @@ impl AttrItem { /// ``` fn value_str(&self) -> Option { match &self.args { - AttrArgs::Eq(_, args) => args.value_str(), + AttrArgs::Eq { value, .. } => value.value_str(), AttrArgs::Delimited(_) | AttrArgs::Empty => None, } } @@ -492,7 +492,7 @@ impl MetaItemKind { MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List) } AttrArgs::Delimited(..) => None, - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind { ExprKind::Lit(token_lit) => { // Turn failures to `None`, we'll get parse errors elsewhere. MetaItemLit::from_token_lit(token_lit, expr.span) @@ -501,7 +501,9 @@ impl MetaItemKind { } _ => None, }, - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { + Some(MetaItemKind::NameValue(lit.clone())) + } } } } @@ -702,7 +704,7 @@ pub fn mk_attr_name_value_str( tokens: None, }); let path = Path::from_ident(Ident::new(name, span)); - let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr)); + let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) }; mk_attr(g, style, unsafety, path, args, span) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0aceed45028a..55434f232fef 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -451,11 +451,11 @@ fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { match args { AttrArgs::Empty => {} AttrArgs::Delimited(args) => visit_delim_args(vis, args), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => { vis.visit_expr(expr); vis.visit_span(eq_span); } - AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when visiting mac args eq: {:?}", lit) } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 718397e8ca00..e92b7ac712a4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1273,8 +1273,8 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) - match args { AttrArgs::Empty => {} AttrArgs::Delimited(_args) => {} - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)), - AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => try_visit!(visitor.visit_expr(expr)), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when walking mac args eq: {:?}", lit) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 96546239f4c2..6b67c256fc25 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -889,7 +889,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle // nonterminals in `#[doc]` (e.g. `#[doc = $e]`). - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { + &AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(ref expr) } => { // In valid code the value always ends up as a single literal. Otherwise, a dummy // literal suffices because the error is handled elsewhere. let lit = if let ExprKind::Lit(token_lit) = expr.kind @@ -905,9 +905,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: DUMMY_SP, } }; - AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit)) + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when lowering mac args eq: {:?}", lit) } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d7c531f37608..479677b0a5ad 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -648,14 +648,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere AttrArgs::Empty => { self.print_path(&item.path, false, 0); } - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { self.print_path(&item.path, false, 0); self.space(); self.word_space("="); let token_str = self.expr_to_string(expr); self.word(token_str); } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { self.print_path(&item.path, false, 0); self.space(); self.word_space("="); diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 19c2d466f7ca..e5500c8bba1c 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -732,7 +732,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => item.to_tokens(), }; let attr_item = attr.unwrap_normal_item(); - if let AttrArgs::Eq(..) = attr_item.args { + if let AttrArgs::Eq { .. } = attr_item.args { self.cx.dcx().emit_err(UnsupportedKeyValue { span }); } let inner_tokens = attr_item.args.inner_tokens(); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ed8d152d2d3..37556c064d82 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> { AttrArgs::Delimited(args) } else if self.eat(&token::Eq) { let eq_span = self.prev_token.span; - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?)) + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(self.parse_expr_force_collect()?) } } else { AttrArgs::Empty }) diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index f3174e7dea2d..aab3f10bc667 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -43,7 +43,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { } } _ => { - if let AttrArgs::Eq(..) = attr_item.args { + if let AttrArgs::Eq { .. } = attr_item.args { // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { Ok(_) => {} @@ -70,7 +70,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?; MetaItemKind::List(nmis) } - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { if let ast::ExprKind::Lit(token_lit) = expr.kind { let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span); let res = match res { @@ -116,7 +116,9 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met return Err(err); } } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => MetaItemKind::NameValue(lit.clone()), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { + MetaItemKind::NameValue(lit.clone()) + } }, }) } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 02e255d7726d..9abf713eb250 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -220,7 +220,7 @@ pub fn attrs_to_doc_fragments<'a>( fn span_for_value(attr: &ast::Attribute) -> Span { if let ast::AttrKind::Normal(normal) = &attr.kind - && let ast::AttrArgs::Eq(_, ast::AttrArgsEq::Hir(meta)) = &normal.item.args + && let ast::AttrArgs::Eq { value: ast::AttrArgsEq::Hir(meta), .. } = &normal.item.args { meta.span.with_ctxt(attr.span.ctxt()) } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 7f42c932fcf5..2ba63b6bb49b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -639,8 +639,8 @@ impl<'tcx> OnUnimplementedDirective { let report_span = match &item.args { AttrArgs::Empty => item.path.span, AttrArgs::Delimited(args) => args.dspan.entire(), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => eq_span.to(expr.span), - AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span), + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => eq_span.to(expr.span), + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(expr) } => eq_span.to(expr.span), }; if let Some(item_def_id) = item_def_id.as_local() { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 093f216accbe..121584837207 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2649,7 +2649,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) { }); args.tokens = TokenStream::new(tokens); } - ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {} + ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {} } } diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs index fadd52728802..97cffeb098ef 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -9,7 +9,7 @@ use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args { + if let AttrArgs::Eq { value: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args { // `#[should_panic = ".."]` found, good return; } diff --git a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs index 49978d4a6555..2182689f9851 100644 --- a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -12,7 +12,7 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { if !attr.span.from_expansion() && let AttrKind::Normal(ref normal) = attr.kind && normal.item.path == sym::doc - && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index 4f22931a4ded..b38e362410ef 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile { && let AttrKind::Normal(ref normal) = attr.kind && let Some(doc) = attr.doc_str() && doc.as_str().len() as u64 > self.max_file_size - && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index c90f4a6ebfe6..620a9b56eb55 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -872,8 +872,8 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { match (l, r) { (Empty, Empty) => true, (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra), - (Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re), - (Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind, + (Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re), + (Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind, _ => false, } } From 2d61c0906a31ff1310603ee13582c05f29aa1190 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Mon, 2 Dec 2024 18:27:09 +0800 Subject: [PATCH 289/330] reduce false positives on some common cases from if-let-rescope --- compiler/rustc_lint/src/if_let_rescope.rs | 7 +++-- tests/ui/drop/lint-if-let-rescope.fixed | 24 ++++++++++++---- tests/ui/drop/lint-if-let-rescope.rs | 22 +++++++++++---- tests/ui/drop/lint-if-let-rescope.stderr | 34 +++++------------------ 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 0e874669043f..2db229ed133f 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -103,8 +103,11 @@ fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { } fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { - let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else { - return false; + let mut parents = tcx.hir().parent_iter(hir_id); + let stmt = match parents.next() { + Some((_, hir::Node::Stmt(stmt))) => stmt, + Some((_, hir::Node::Block(_) | hir::Node::Arm(_))) => return true, + _ => return false, }; let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false }; expr.hir_id == hir_id diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index fec2e3b2ae70..182190aa323b 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -14,7 +14,7 @@ impl Drop for Droppy { } } impl Droppy { - fn get(&self) -> Option { + const fn get(&self) -> Option { None } } @@ -62,11 +62,10 @@ fn main() { //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } - if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { - //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: the value is now dropped here in Edition 2024 - //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + if let () = { if let Some(_value) = Droppy.get() {} } { + // This should not lint. + // This `if let` sits is a tail expression of a block. + // In Edition 2024, the temporaries are dropped before exiting the surrounding block. } #[rustfmt::skip] @@ -94,4 +93,17 @@ fn main() { //~| HELP: the value is now dropped here in Edition 2024 //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + + // We want to keep the `if let`s below as direct descendents of match arms, + // so the formatting is suppressed. + #[rustfmt::skip] + match droppy().get() { + _ => if let Some(_value) = droppy().get() {}, + // Should not lint + // There is implicitly a block surrounding the `if let`. + // Given that it is a tail expression, the temporaries are dropped duly before + // the execution is exiting the `match`. + } + + if let Some(_value) = droppy().get() {} } diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index ee184695b97a..e1b38be0a0f5 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -14,7 +14,7 @@ impl Drop for Droppy { } } impl Droppy { - fn get(&self) -> Option { + const fn get(&self) -> Option { None } } @@ -63,10 +63,9 @@ fn main() { } if let () = { if let Some(_value) = Droppy.get() {} } { - //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: the value is now dropped here in Edition 2024 - //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + // This should not lint. + // This `if let` sits is a tail expression of a block. + // In Edition 2024, the temporaries are dropped before exiting the surrounding block. } #[rustfmt::skip] @@ -94,4 +93,17 @@ fn main() { //~| HELP: the value is now dropped here in Edition 2024 //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + + // We want to keep the `if let`s below as direct descendents of match arms, + // so the formatting is suppressed. + #[rustfmt::skip] + match droppy().get() { + _ => if let Some(_value) = droppy().get() {}, + // Should not lint + // There is implicitly a block surrounding the `if let`. + // Given that it is a tail expression, the temporaries are dropped duly before + // the execution is exiting the `match`. + } + + if let Some(_value) = droppy().get() {} } diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index ef60d141b798..cfb7070c0975 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -112,27 +112,7 @@ LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ = | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:65:22 - | -LL | if let () = { if let Some(_value) = Droppy.get() {} } { - | ^^^^^^^^^^^^^^^^^^^------^^^^^^ - | | - | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:65:55 - | -LL | if let () = { if let Some(_value) = Droppy.get() {} } { - | ^ -help: a `match` with a single arm can preserve the drop order up to Edition 2021 - | -LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { - | ~~~~~ +++++++++++++++++ ++++++++ - -error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:73:12 + --> $DIR/lint-if-let-rescope.rs:72:12 | LL | if (if let Some(_value) = droppy().get() { true } else { false }) { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -142,7 +122,7 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:73:53 + --> $DIR/lint-if-let-rescope.rs:72:53 | LL | if (if let Some(_value) = droppy().get() { true } else { false }) { | ^ @@ -152,7 +132,7 @@ LL | if (match droppy().get() { Some(_value) => { true } _ => { false }}) { | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:79:21 + --> $DIR/lint-if-let-rescope.rs:78:21 | LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -162,7 +142,7 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:79:62 + --> $DIR/lint-if-let-rescope.rs:78:62 | LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) { | ^ @@ -172,7 +152,7 @@ LL | } else if (((match droppy().get() { Some(_value) => { true } _ => { fal | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:91:15 + --> $DIR/lint-if-let-rescope.rs:90:15 | LL | while (if let Some(_value) = droppy().get() { false } else { true }) { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -182,7 +162,7 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:91:57 + --> $DIR/lint-if-let-rescope.rs:90:57 | LL | while (if let Some(_value) = droppy().get() { false } else { true }) { | ^ @@ -191,5 +171,5 @@ help: a `match` with a single arm can preserve the drop order up to Edition 2021 LL | while (match droppy().get() { Some(_value) => { false } _ => { true }}) { | ~~~~~ +++++++++++++++++ ~~~~ + -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors From c8e0724937df40f8e8323a2677b3130707aec47f Mon Sep 17 00:00:00 2001 From: Xelph Date: Mon, 2 Dec 2024 03:06:57 -0700 Subject: [PATCH 290/330] Fix typos on tests/ui/README.md --- tests/ui/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/README.md b/tests/ui/README.md index c14d0ee78c8d..aa36481ae06e 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -6,9 +6,9 @@ This folder contains `rustc`'s ## Test Directives (Headers) Typically, a UI test will have some test directives / headers which are -special comments that tell compiletest how to build and intepret a test. +special comments that tell compiletest how to build and interpret a test. -As part of an on-going effort to rewrite compiletest +As part of an ongoing effort to rewrite compiletest (see ), a major change proposal to change legacy compiletest-style headers `// ` to [`ui_test`](https://github.com/oli-obk/ui_test)-style headers @@ -30,6 +30,6 @@ but in `ui_test` style, the header would be written as compiletest is changed to accept only `//@` directives for UI tests (currently), and will reject and report an error if it encounters any -comments `// ` that may be parsed as an legacy compiletest-style +comments `// ` that may be parsed as a legacy compiletest-style test header. To fix this, you should migrate to the `ui_test`-style header `//@ `. From b863c0d28b8f59f0c986fac696acf82d3d87e788 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Dec 2024 12:03:32 +0100 Subject: [PATCH 291/330] Remove static HashSet for default IDs list --- src/librustdoc/html/markdown.rs | 116 +++++++++++++++----------------- 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index d18673c8140d..5e3d06a4ae79 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -32,12 +32,11 @@ use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::path::PathBuf; use std::str::{self, CharIndices}; -use std::sync::OnceLock; use pulldown_cmark::{ BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagMessage}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; @@ -1882,66 +1881,63 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec, usize>, + map: FxHashMap, existing_footnotes: usize, } -// The map is pre-initialized and then can be used as is to prevent cloning it for each item -// (in the sidebar rendering). -static DEFAULT_ID_MAP: OnceLock> = OnceLock::new(); - -fn init_id_map() -> FxHashSet<&'static str> { - let mut map = FxHashSet::default(); - // This is the list of IDs used in JavaScript. - map.insert("help"); - map.insert("settings"); - map.insert("not-displayed"); - map.insert("alternative-display"); - map.insert("search"); - map.insert("crate-search"); - map.insert("crate-search-div"); - // This is the list of IDs used in HTML generated in Rust (including the ones - // used in tera template files). - map.insert("themeStyle"); - map.insert("settings-menu"); - map.insert("help-button"); - map.insert("sidebar-button"); - map.insert("main-content"); - map.insert("toggle-all-docs"); - map.insert("all-types"); - map.insert("default-settings"); - map.insert("sidebar-vars"); - map.insert("copy-path"); - map.insert("rustdoc-toc"); - map.insert("rustdoc-modnav"); - // This is the list of IDs used by rustdoc sections (but still generated by - // rustdoc). - map.insert("fields"); - map.insert("variants"); - map.insert("implementors-list"); - map.insert("synthetic-implementors-list"); - map.insert("foreign-impls"); - map.insert("implementations"); - map.insert("trait-implementations"); - map.insert("synthetic-implementations"); - map.insert("blanket-implementations"); - map.insert("required-associated-types"); - map.insert("provided-associated-types"); - map.insert("provided-associated-consts"); - map.insert("required-associated-consts"); - map.insert("required-methods"); - map.insert("provided-methods"); - map.insert("dyn-compatibility"); - map.insert("implementors"); - map.insert("synthetic-implementors"); - map.insert("implementations-list"); - map.insert("trait-implementations-list"); - map.insert("synthetic-implementations-list"); - map.insert("blanket-implementations-list"); - map.insert("deref-methods"); - map.insert("layout"); - map.insert("aliased-type"); - map +fn is_default_id(id: &str) -> bool { + matches!( + id, + // This is the list of IDs used in JavaScript. + "help" + | "settings" + | "not-displayed" + | "alternative-display" + | "search" + | "crate-search" + | "crate-search-div" + // This is the list of IDs used in HTML generated in Rust (including the ones + // used in tera template files). + | "themeStyle" + | "settings-menu" + | "help-button" + | "sidebar-button" + | "main-content" + | "toggle-all-docs" + | "all-types" + | "default-settings" + | "sidebar-vars" + | "copy-path" + | "rustdoc-toc" + | "rustdoc-modnav" + // This is the list of IDs used by rustdoc sections (but still generated by + // rustdoc). + | "fields" + | "variants" + | "implementors-list" + | "synthetic-implementors-list" + | "foreign-impls" + | "implementations" + | "trait-implementations" + | "synthetic-implementations" + | "blanket-implementations" + | "required-associated-types" + | "provided-associated-types" + | "provided-associated-consts" + | "required-associated-consts" + | "required-methods" + | "provided-methods" + | "dyn-compatibility" + | "implementors" + | "synthetic-implementors" + | "implementations-list" + | "trait-implementations-list" + | "synthetic-implementations-list" + | "blanket-implementations-list" + | "deref-methods" + | "layout" + | "aliased-type" + ) } impl IdMap { @@ -1953,7 +1949,7 @@ impl IdMap { let id = match self.map.get_mut(candidate.as_ref()) { None => { let candidate = candidate.to_string(); - if DEFAULT_ID_MAP.get_or_init(init_id_map).contains(candidate.as_str()) { + if is_default_id(&candidate) { let id = format!("{}-{}", candidate, 1); self.map.insert(candidate.into(), 2); id From c0b532277b431822abb2b18aacf4adc6300e11ba Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 2 Dec 2024 10:29:45 +0000 Subject: [PATCH 292/330] Add a helper method for extracting spans from AttrArgsEq --- compiler/rustc_ast/src/ast.rs | 14 ++++++++++---- compiler/rustc_resolve/src/rustdoc.rs | 4 ++-- .../src/error_reporting/traits/on_unimplemented.rs | 5 ++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2ab63f5fb79e..03f90c8e1f49 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1750,15 +1750,21 @@ pub enum AttrArgsEq { Hir(MetaItemLit), } +impl AttrArgsEq { + pub fn span(&self) -> Span { + match self { + AttrArgsEq::Ast(p) => p.span, + AttrArgsEq::Hir(lit) => lit.span, + } + } +} + impl AttrArgs { pub fn span(&self) -> Option { match self { AttrArgs::Empty => None, AttrArgs::Delimited(args) => Some(args.dspan.entire()), - AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => Some(eq_span.to(expr.span)), - AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { - unreachable!("in literal form when getting span: {:?}", lit); - } + AttrArgs::Eq { eq_span, value } => Some(eq_span.to(value.span())), } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 9abf713eb250..65128ceb8661 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -220,9 +220,9 @@ pub fn attrs_to_doc_fragments<'a>( fn span_for_value(attr: &ast::Attribute) -> Span { if let ast::AttrKind::Normal(normal) = &attr.kind - && let ast::AttrArgs::Eq { value: ast::AttrArgsEq::Hir(meta), .. } = &normal.item.args + && let ast::AttrArgs::Eq { value, .. } = &normal.item.args { - meta.span.with_ctxt(attr.span.ctxt()) + value.span().with_ctxt(attr.span.ctxt()) } else { attr.span } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2ba63b6bb49b..f10314c1c9e0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,7 +1,7 @@ use std::iter; use std::path::PathBuf; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItemInner}; +use rustc_ast::{AttrArgs, AttrKind, Attribute, MetaItemInner}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; @@ -639,8 +639,7 @@ impl<'tcx> OnUnimplementedDirective { let report_span = match &item.args { AttrArgs::Empty => item.path.span, AttrArgs::Delimited(args) => args.dspan.entire(), - AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => eq_span.to(expr.span), - AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(expr) } => eq_span.to(expr.span), + AttrArgs::Eq { eq_span, value } => eq_span.to(value.span()), }; if let Some(item_def_id) = item_def_id.as_local() { From da182b6d95d4b8480045756a41270e43bc496c26 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 2 Dec 2024 10:56:36 +0000 Subject: [PATCH 293/330] Deduplicate some matches that always panic in one arm --- compiler/rustc_ast/src/ast.rs | 23 +++++++++++++++++++---- compiler/rustc_ast/src/mut_visit.rs | 7 ++----- compiler/rustc_ast/src/visit.rs | 5 +---- compiler/rustc_ast_lowering/src/lib.rs | 6 ++---- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 03f90c8e1f49..cd8b193850f9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1757,6 +1757,24 @@ impl AttrArgsEq { AttrArgsEq::Hir(lit) => lit.span, } } + + pub fn unwrap_ast(&self) -> &Expr { + match self { + AttrArgsEq::Ast(p) => p, + AttrArgsEq::Hir(lit) => { + unreachable!("in literal form when getting inner tokens: {lit:?}") + } + } + } + + pub fn unwrap_ast_mut(&mut self) -> &mut P { + match self { + AttrArgsEq::Ast(p) => p, + AttrArgsEq::Hir(lit) => { + unreachable!("in literal form when getting inner tokens: {lit:?}") + } + } + } } impl AttrArgs { @@ -1774,10 +1792,7 @@ impl AttrArgs { match self { AttrArgs::Empty => TokenStream::default(), AttrArgs::Delimited(args) => args.tokens.clone(), - AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => TokenStream::from_ast(expr), - AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { - unreachable!("in literal form when getting inner tokens: {:?}", lit) - } + AttrArgs::Eq { value, .. } => TokenStream::from_ast(value.unwrap_ast()), } } } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 55434f232fef..196fcc1af30f 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -451,13 +451,10 @@ fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { match args { AttrArgs::Empty => {} AttrArgs::Delimited(args) => visit_delim_args(vis, args), - AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => { - vis.visit_expr(expr); + AttrArgs::Eq { eq_span, value } => { + vis.visit_expr(value.unwrap_ast_mut()); vis.visit_span(eq_span); } - AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { - unreachable!("in literal form when visiting mac args eq: {:?}", lit) - } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e92b7ac712a4..2f6998783fa3 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1273,10 +1273,7 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) - match args { AttrArgs::Empty => {} AttrArgs::Delimited(_args) => {} - AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => try_visit!(visitor.visit_expr(expr)), - AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { - unreachable!("in literal form when walking mac args eq: {:?}", lit) - } + AttrArgs::Eq { value, .. } => try_visit!(visitor.visit_expr(value.unwrap_ast())), } V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6b67c256fc25..34ff9e9cca4d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -889,7 +889,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle // nonterminals in `#[doc]` (e.g. `#[doc = $e]`). - &AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(ref expr) } => { + &AttrArgs::Eq { eq_span, ref value } => { + let expr = value.unwrap_ast(); // In valid code the value always ends up as a single literal. Otherwise, a dummy // literal suffices because the error is handled elsewhere. let lit = if let ExprKind::Lit(token_lit) = expr.kind @@ -907,9 +908,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } } - AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { - unreachable!("in literal form when lowering mac args eq: {:?}", lit) - } } } From 70e0d5893ffd661851ae40f7b84e94ab013f8604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 2 Dec 2024 11:48:39 +0000 Subject: [PATCH 294/330] build `rustc` with 1 CGU on `aarch64-apple-darwin` --- src/ci/github-actions/jobs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 454c855c75d2..2ea37c168dd3 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -338,6 +338,7 @@ auto: --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin + --set rust.codegen-units=1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_15.4.app USE_XCODE_CLANG: 1 From 8b90e70e0634a3392b77f514c9755058b1fb85f7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 Dec 2024 13:23:16 +0100 Subject: [PATCH 295/330] mir validator: don't store mir phase --- compiler/rustc_mir_transform/src/inline.rs | 10 +-- .../rustc_mir_transform/src/pass_manager.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 79 ++++++++----------- 3 files changed, 34 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0878fa26a92c..79c38b50459c 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -220,15 +220,7 @@ impl<'tcx> Inliner<'tcx> { // Normally, this shouldn't be required, but trait normalization failure can create a // validation ICE. - if !validate_types( - self.tcx, - MirPhase::Runtime(RuntimePhase::Optimized), - self.typing_env, - &callee_body, - &caller_body, - ) - .is_empty() - { + if !validate_types(self.tcx, self.typing_env, &callee_body, &caller_body).is_empty() { return Err("failed to validate callee body"); } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 779e7f22101c..8a45ce0762d5 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -292,7 +292,7 @@ fn run_passes_inner<'tcx>( } pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { - validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); + validate::Validator { when }.run_pass(tcx, body); } fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) { diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 51e5c49cea10..936d88e9ac03 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -29,12 +29,6 @@ enum EdgeKind { pub(super) struct Validator { /// Describes at which point in the pipeline this validation is happening. pub when: String, - /// The phase for which we are upholding the dialect. If the given phase forbids a specific - /// element, this validator will now emit errors if that specific element is encountered. - /// Note that phases that change the dialect cause all *following* phases to check the - /// invariants of the new dialect. A phase that changes dialects never checks the new invariants - /// itself. - pub mir_phase: MirPhase, } impl<'tcx> crate::MirPass<'tcx> for Validator { @@ -46,11 +40,9 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) { return; } - debug_assert_eq!(self.mir_phase, body.phase); let def_id = body.source.def_id(); - let mir_phase = body.phase; let typing_env = body.typing_env(tcx); - let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) { + let can_unwind = if body.phase <= MirPhase::Runtime(RuntimePhase::Initial) { // In this case `AbortUnwindingCalls` haven't yet been executed. true } else if !tcx.def_kind(def_id).is_fn_like() { @@ -64,9 +56,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { ty::Coroutine(..) => ExternAbi::Rust, // No need to do MIR validation on error bodies ty::Error(_) => return, - _ => { - span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase) - } + _ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"), }; ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi) @@ -76,7 +66,6 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { when: &self.when, body, tcx, - mir_phase, unwind_edge_count: 0, reachable_blocks: traversal::reachable_as_bitset(body), value_cache: FxHashSet::default(), @@ -86,7 +75,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { cfg_checker.check_cleanup_control_flow(); // Also run the TypeChecker. - for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) { + for (location, msg) in validate_types(tcx, typing_env, body, body) { cfg_checker.fail(location, msg); } @@ -107,7 +96,6 @@ struct CfgChecker<'a, 'tcx> { when: &'a str, body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, - mir_phase: MirPhase, unwind_edge_count: usize, reachable_blocks: BitSet, value_cache: FxHashSet, @@ -294,7 +282,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match &statement.kind { StatementKind::AscribeUserType(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`AscribeUserType` should have been removed after drop lowering phase", @@ -302,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } StatementKind::FakeRead(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FakeRead` should have been removed after drop lowering phase", @@ -310,17 +298,17 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } StatementKind::SetDiscriminant { .. } => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); } } StatementKind::Deinit(..) => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`Deinit`is not allowed until deaggregation"); } } StatementKind::Retag(kind, _) => { - // FIXME(JakobDegen) The validator should check that `self.mir_phase < + // FIXME(JakobDegen) The validator should check that `self.body.phase < // DropsLowered`. However, this causes ICEs with generation of drop shims, which // seem to fail to set their `MirPhase` correctly. if matches!(kind, RetagKind::TwoPhase) { @@ -328,7 +316,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } StatementKind::Coverage(kind) => { - if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) + if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind { self.fail( @@ -391,7 +379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { // the return edge from the call. FIXME(tmiasko): Since this is a strictly code // generation concern, the code generation should be responsible for handling // it. - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized) + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) && self.is_critical_call_edge(target, unwind) { self.fail( @@ -440,7 +428,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { if self.body.coroutine.is_none() { self.fail(location, "`Yield` cannot appear outside coroutine bodies"); } - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`Yield` should have been replaced by coroutine lowering"); } self.check_edge(location, *resume, EdgeKind::Normal); @@ -449,7 +437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } TerminatorKind::FalseEdge { real_target, imaginary_target } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FalseEdge` should have been removed after drop elaboration", @@ -459,7 +447,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.check_edge(location, *imaginary_target, EdgeKind::Normal); } TerminatorKind::FalseUnwind { real_target, unwind } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FalseUnwind` should have been removed after drop elaboration", @@ -478,7 +466,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { if self.body.coroutine.is_none() { self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies"); } - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`CoroutineDrop` should have been replaced by coroutine lowering", @@ -532,13 +520,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { /// `optimized_mir` is available. pub(super) fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, - mir_phase: MirPhase, typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>, caller_body: &Body<'tcx>, ) -> Vec<(Location, String)> { - let mut type_checker = - TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() }; + let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() }; type_checker.visit_body(body); type_checker.failures } @@ -548,7 +534,6 @@ struct TypeChecker<'a, 'tcx> { caller_body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - mir_phase: MirPhase, failures: Vec<(Location, String)>, } @@ -577,7 +562,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // After borrowck subtyping should be fully explicit via // `Subtype` projections. - let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + let variance = if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { Variance::Invariant } else { Variance::Covariant @@ -618,7 +603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed. if self.tcx.sess.opts.unstable_opts.validate_mir - && self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) + && self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { // `Operand::Copy` is only supposed to be used with `Copy` types. if let Operand::Copy(place) = operand { @@ -642,7 +627,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ) { match elem { ProjectionElem::OpaqueCast(ty) - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) => + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) => { self.fail( location, @@ -656,7 +641,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } ProjectionElem::Deref - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) => + if self.body.phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) => { let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; @@ -856,7 +841,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // Set off any `bug!`s in the type computation code let _ = place.ty(&self.body.local_decls, self.tcx); - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) && place.projection.len() > 1 && cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo) && place.projection[1..].contains(&ProjectionElem::Deref) @@ -974,7 +959,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } AggregateKind::RawPtr(pointee_ty, mutability) => { - if !matches!(self.mir_phase, MirPhase::Runtime(_)) { + if !matches!(self.body.phase, MirPhase::Runtime(_)) { // It would probably be fine to support this in earlier phases, but at the // time of writing it's only ever introduced from intrinsic lowering, so // earlier things just `bug!` on it. @@ -1016,7 +1001,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } }, Rvalue::Ref(_, BorrowKind::Fake(_), _) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`Assign` statement with a `Fake` borrow should have been removed in runtime MIR", @@ -1130,7 +1115,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } UnOp::PtrMetadata => { - if !matches!(self.mir_phase, MirPhase::Runtime(_)) { + if !matches!(self.body.phase, MirPhase::Runtime(_)) { // It would probably be fine to support this in earlier phases, but at // the time of writing it's only ever introduced from intrinsic // lowering or other runtime-phase optimization passes, so earlier @@ -1206,7 +1191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { "CastKind::{kind:?} output must be a raw const pointer, not {:?}", ty::RawPtr(_, Mutability::Not) ); - if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { + if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { self.fail(location, format!("After borrowck, MIR disallows {kind:?}")); } } @@ -1222,7 +1207,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { "CastKind::{kind:?} output must be a raw pointer, not {:?}", ty::RawPtr(..) ); - if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { + if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) { self.fail(location, format!("After borrowck, MIR disallows {kind:?}")); } } @@ -1288,7 +1273,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - if let MirPhase::Runtime(..) = self.mir_phase { + if let MirPhase::Runtime(..) = self.body.phase { // Unlike `mem::transmute`, a MIR `Transmute` is well-formed // for any two `Sized` types, just potentially UB to run. @@ -1317,7 +1302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { location, format!( "Transmute is not supported in non-runtime phase {:?}.", - self.mir_phase + self.body.phase ), ); } @@ -1404,7 +1389,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::AscribeUserType(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`AscribeUserType` should have been removed after drop lowering phase", @@ -1412,7 +1397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::FakeRead(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( location, "`FakeRead` should have been removed after drop lowering phase", @@ -1463,7 +1448,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::SetDiscriminant { place, .. } => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); } let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind(); @@ -1477,12 +1462,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } StatementKind::Deinit(..) => { - if self.mir_phase < MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`Deinit`is not allowed until deaggregation"); } } StatementKind::Retag(kind, _) => { - // FIXME(JakobDegen) The validator should check that `self.mir_phase < + // FIXME(JakobDegen) The validator should check that `self.body.phase < // DropsLowered`. However, this causes ICEs with generation of drop shims, which // seem to fail to set their `MirPhase` correctly. if matches!(kind, RetagKind::TwoPhase) { From cfee10ce899b694e2896cd2f578bdda79746d0a6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 Dec 2024 13:43:16 +0100 Subject: [PATCH 296/330] remove outdated comment --- compiler/rustc_lint/src/internal.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 38c38b59bc58..7c8a65059d11 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -242,17 +242,10 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option { } // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait. Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => { - if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() { - if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did()) - { - // NOTE: This path is currently unreachable as `Ty<'tcx>` is - // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>` - // is not actually allowed. - // - // I(@lcnr) still kept this branch in so we don't miss this - // if we ever change it in the future. - return Some(format!("{}<{}>", name, args[0])); - } + if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() + && let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did()) + { + return Some(format!("{}<{}>", name, args[0])); } } _ => (), From e089bead327795727e1a72fd276776f12f186cea Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 Dec 2024 13:57:56 +0100 Subject: [PATCH 297/330] remove `Ty::is_copy_modulo_regions` --- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/intrinsicck.rs | 2 +- .../rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/context.rs | 4 +++ .../rustc_lint/src/drop_forget_useless.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 33 ++++++++++--------- .../src/build/expr/as_operand.rs | 2 +- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- .../src/methods/manual_inspect.rs | 4 +-- .../clippy/clippy_lints/src/question_mark.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 2 +- 15 files changed, 36 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e1f4ccca97e9..022a6d457ec5 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -103,7 +103,7 @@ fn allowed_union_or_unsafe_field<'tcx>( // Fallback case: allow `ManuallyDrop` and things that are `Copy`, // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx, typing_env) + || tcx.type_is_copy_modulo_regions(typing_env, ty) || ty.references_error() } }; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index b96469f503c8..df4da03f0f59 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { + if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { let msg = "arguments for inline assembly must be copyable"; self.tcx .dcx() diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 2a00530c4343..774d00edea03 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env()) + self.0.type_is_copy_modulo_regions(ty) } fn body_owner_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e130cfc1d736..ec0851989220 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -586,7 +586,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } } - if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) { + if cx.type_is_copy_modulo_regions(ty) { return; } if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7248b1927638..44c7888a530c 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -710,6 +710,10 @@ impl<'tcx> LateContext<'tcx> { TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } } + pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { + self.tcx.type_is_copy_modulo_regions(self.typing_env(), ty) + } + /// Gets the type-checking results for the current body, /// or `None` if outside a body. pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 8fe867386588..ce23892508b5 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) { let arg_ty = cx.typeck_results().expr_ty(arg); - let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); + let is_copy = cx.type_is_copy_modulo_regions(arg_ty); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let let_underscore_ignore_sugg = || { if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 797ac9685b1e..57054bd1a0b2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -172,6 +172,24 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Checks whether `ty: Copy` holds while ignoring region constraints. + /// + /// This impacts whether values of `ty` are *moved* or *copied* + /// when referenced. This means that we may generate MIR which + /// does copies even when the type actually doesn't satisfy the + /// full requirements for the `Copy` trait (cc #29149) -- this + /// winds up being reported as an error during NLL borrow check. + /// + /// This function should not be used if there is an `InferCtxt` available. + /// Use `InferCtxt::type_is_copy_modulo_regions` instead. + pub fn type_is_copy_modulo_regions( + self, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + ty.is_trivially_pure_clone_copy() || self.is_copy_raw(typing_env.as_query_input(ty)) + } + /// Returns the deeply last field of nested structures, or the same type if /// not a structure at all. Corresponds to the only possible unsized field, /// and its type can be used to determine unsizing strategy. @@ -1174,21 +1192,6 @@ impl<'tcx> Ty<'tcx> { .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) } - /// Checks whether values of this type `T` are *moved* or *copied* - /// when referenced -- this amounts to a check for whether `T: - /// Copy`, but note that we **don't** consider lifetimes when - /// doing this check. This means that we may generate MIR which - /// does copies even when the type actually doesn't satisfy the - /// full requirements for the `Copy` trait (cc #29149) -- this - /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions( - self, - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, - ) -> bool { - self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self)) - } - /// Checks whether values of this type `T` have a size known at /// compile time (i.e., whether `T: Sized`). Lifetimes are ignored /// for the purposes of this check, so it can be an diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 0cab853196b8..777ff9e68f02 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ty = expr.ty; if !ty.is_sized(tcx, this.typing_env()) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env())); + assert!(!tcx.type_is_copy_modulo_regions(this.typing_env(), ty)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e55cd35e2436..a13b00e19216 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -780,7 +780,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: return; }; - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env); + let is_binding_by_move = |ty: Ty<'tcx>| !cx.tcx.type_is_copy_modulo_regions(cx.typing_env, ty); let sess = cx.tcx.sess; diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 51e5c49cea10..f67d9a778253 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -624,7 +624,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { + if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 43244eb5dcb1..ee708564a804 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -35,7 +35,7 @@ impl<'tcx> InferCtxt<'tcx> { // FIXME(#132279): This should be removed as it causes us to incorrectly // handle opaques in their defining scope. if !(param_env, ty).has_infer() { - return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env)); + return self.tcx.type_is_copy_modulo_regions(self.typing_env(param_env), ty); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d85da7d355e6..1c85eb2a8613 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -202,7 +202,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.typing_env) => {} + _ if tcx.type_is_copy_modulo_regions(self.typing_env, component) => {} ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index 865a42b65c62..20e4d233525a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: _ => {}, } } - requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); + requires_copy |= !cx.type_is_copy_modulo_regions(ty); break; } }, @@ -158,7 +158,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: } if can_lint - && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())) + && (!requires_copy || cx.type_is_copy_modulo_regions(arg_ty)) // This case could be handled, but a fair bit of care would need to be taken. && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 4b96858d8f66..77abe7151f07 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) + let by_ref = !cx.type_is_copy_modulo_regions(caller_ty) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 39c9d234a1a1..260d1b801e3d 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain; /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) + cx.type_is_copy_modulo_regions(ty) } /// This checks whether a given type is known to implement Debug. From 42174f03964759f849a2f22653b264038948443a Mon Sep 17 00:00:00 2001 From: jyn Date: Mon, 2 Dec 2024 09:55:04 -0500 Subject: [PATCH 298/330] `impl Default for EarlyDiagCtxt` for small rustc_driver programs, most of their imports will currently be related to diagnostics. this change simplifiers their code so it's more clear what in the driver is modified from the default. this is especially important for external drivers which are out of tree and not updated in response to breaking changes. for these drivers, each import is a liability for future code, since it can be broken when refactors happen. here is an example driver which is simplified by these changes: ``` diff --git a/src/main.rs b/src/main.rs index f81aa3e..11e5f18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,8 @@ #![feature(rustc_private)] extern crate rustc_driver; extern crate rustc_interface; -extern crate rustc_errors; -extern crate rustc_session; use rustc_driver::Callbacks; -use rustc_errors::{emitter::HumanReadableErrorType, ColorConfig}; use rustc_interface::interface; -use rustc_session::config::ErrorOutputType; -use rustc_session::EarlyDiagCtxt; struct DisableSafetyChecks; @@ -26,11 +18,7 @@ fn main() { "https://github.com/jyn514/jyn514.github.io/issues/new", |_| (), ); - let handler = EarlyDiagCtxt::new(ErrorOutputType::HumanReadable( - HumanReadableErrorType::Default, - ColorConfig::Auto, - )); - rustc_driver::init_rustc_env_logger(&handler); + rustc_driver::init_rustc_env_logger(&Default::default()); std::process::exit(rustc_driver::catch_with_exit_code(move || { let args: Vec = std::env::args().collect(); rustc_driver::RunCompiler::new(&args, &mut DisableSafetyChecks).run() ``` --- compiler/rustc_session/src/session.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f585410adb97..120ae9946eac 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1358,6 +1358,12 @@ pub struct EarlyDiagCtxt { dcx: DiagCtxt, } +impl Default for EarlyDiagCtxt { + fn default() -> Self { + Self::new(ErrorOutputType::default()) + } +} + impl EarlyDiagCtxt { pub fn new(output: ErrorOutputType) -> Self { let emitter = mk_emitter(output); From 3a9bc76f809634b0ae9844147766818a1bdcd32b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 10:39:09 +0100 Subject: [PATCH 299/330] stabilize const_collections_with_hasher and build_hasher_default_const_new --- library/core/src/hash/mod.rs | 6 +++--- library/std/src/collections/hash/map.rs | 24 +++++++++++++++++++++++- library/std/src/collections/hash/set.rs | 24 +++++++++++++++++++++++- library/std/src/lib.rs | 1 - 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 061690e88ddf..84bbf985e8be 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -752,10 +752,10 @@ pub struct BuildHasherDefault(marker::PhantomData H>); impl BuildHasherDefault { /// Creates a new BuildHasherDefault for Hasher `H`. - #[unstable( + #[stable(feature = "build_hasher_default_const_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable( feature = "build_hasher_default_const_new", - issue = "123197", - reason = "recently added" + since = "CURRENT_RUSTC_VERSION" )] pub const fn new() -> Self { BuildHasherDefault(marker::PhantomData) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 09c0b61fb2b8..59dcdfd08cb3 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -204,6 +204,25 @@ use crate::ops::Index; /// println!("{viking:?} has {health} hp"); /// } /// ``` +/// +/// # Usage in `const` and `static` +/// +/// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed, +/// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the +/// initializer of a `const` or `static` item, you will have to use a different hasher that does not +/// involve a random seed, as demonstrated in the following example. **`HashMap` constructed this +/// way are not resistant against HashDoS!** +/// +/// ```rust +/// use std::collections::HashMap; +/// use std::hash::{BuildHasherDefault, DefaultHasher}; +/// use std::sync::Mutex; +/// +/// const EMPTY_MAP: HashMap, BuildHasherDefault> = +/// HashMap::with_hasher(BuildHasherDefault::new()); +/// static MAP: Mutex, BuildHasherDefault>> = +/// Mutex::new(HashMap::with_hasher(BuildHasherDefault::new())); +/// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")] #[stable(feature = "rust1", since = "1.0.0")] @@ -277,7 +296,10 @@ impl HashMap { /// ``` #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")] + #[rustc_const_stable( + feature = "const_collections_with_hasher", + since = "CURRENT_RUSTC_VERSION" + )] pub const fn with_hasher(hash_builder: S) -> HashMap { HashMap { base: base::HashMap::with_hasher(hash_builder) } } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 21a73259f617..2a481dbaa627 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -101,6 +101,25 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub}; /// [`HashMap`]: crate::collections::HashMap /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell +/// +/// # Usage in `const` and `static` +/// +/// Like `HashMap`, `HashSet` is randomly seeded: each `HashSet` instance uses a different seed, +/// which means that `HashSet::new` cannot be used in const context. To construct a `HashSet` in the +/// initializer of a `const` or `static` item, you will have to use a different hasher that does not +/// involve a random seed, as demonstrated in the following example. **`HashSet` constructed this +/// way are not resistant against HashDoS!** +/// +/// ```rust +/// use std::collections::HashSet; +/// use std::hash::{BuildHasherDefault, DefaultHasher}; +/// use std::sync::Mutex; +/// +/// const EMPTY_SET: HashSet> = +/// HashSet::with_hasher(BuildHasherDefault::new()); +/// static SET: Mutex>> = +/// Mutex::new(HashSet::with_hasher(BuildHasherDefault::new())); +/// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "HashSet")] #[stable(feature = "rust1", since = "1.0.0")] pub struct HashSet { @@ -369,7 +388,10 @@ impl HashSet { /// ``` #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")] + #[rustc_const_stable( + feature = "const_collections_with_hasher", + since = "CURRENT_RUSTC_VERSION" + )] pub const fn with_hasher(hasher: S) -> HashSet { HashSet { base: base::HashSet::with_hasher(hasher) } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 143878170f08..585946c1d50e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -320,7 +320,6 @@ // Library features (core): // tidy-alphabetical-start #![feature(array_chunks)] -#![feature(build_hasher_default_const_new)] #![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] From a6f2f00de89e1dd9cb903db93dac754398c1267f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 4 Nov 2024 18:59:57 +0000 Subject: [PATCH 300/330] Move tests back to using AsyncFn --- .../error_reporting/traits/fulfillment_errors.rs | 2 +- .../async-closures/async-fn-mut-for-async-fn.rs | 2 +- .../async-closures/async-fn-once-for-async-fn.rs | 2 +- .../async-closures/auxiliary/foreign.rs | 2 +- .../async-closures/body-check-on-non-fnmut.rs | 2 +- .../async-closures/box-deref-in-debuginfo.rs | 2 +- tests/ui/async-await/async-closures/brand.rs | 2 +- tests/ui/async-await/async-closures/captures.rs | 6 +++--- .../async-await/async-closures/clone-closure.rs | 2 +- .../constrained-but-no-upvars-yet.rs | 4 ++-- .../async-closures/debuginfo-by-move-body.rs | 2 +- tests/ui/async-await/async-closures/drop.rs | 2 +- .../fn-exception-target-features.rs | 2 +- .../fn-exception-target-features.stderr | 4 ++-- .../async-await/async-closures/fn-exception.rs | 2 +- .../async-closures/fn-exception.stderr | 8 ++++---- .../force-move-due-to-inferred-kind.rs | 2 +- tests/ui/async-await/async-closures/foreign.rs | 2 +- .../async-closures/implements-fnmut.rs | 2 +- .../ui/async-await/async-closures/inline-body.rs | 2 +- tests/ui/async-await/async-closures/mangle.rs | 4 ++-- .../async-await/async-closures/moro-example.rs | 2 +- .../async-closures/move-is-async-fn.rs | 2 +- .../async-closures/mut-ref-reborrow.rs | 2 +- .../async-closures/no-borrow-from-env.rs | 2 +- .../non-copy-arg-does-not-force-inner-move.rs | 2 +- .../async-closures/overlapping-projs.rs | 2 +- .../async-closures/precise-captures.rs | 6 +++--- tests/ui/async-await/async-closures/refd.rs | 8 ++++---- .../async-closures/signature-deduction.rs | 2 +- .../without-precise-captures-we-are-powerless.rs | 2 +- .../async-await/async-closures/wrong-fn-kind.rs | 4 ++-- .../async-closures/wrong-fn-kind.stderr | 16 ++++++++-------- .../async-fn/higher-ranked-async-fn.rs | 2 +- tests/ui/async-await/async-fn/impl-trait.rs | 6 +++--- tests/ui/async-await/async-fn/project.rs | 4 +++- 36 files changed, 61 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 9b969dd3e43a..90b182536290 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -794,7 +794,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { closure_def_id, found_kind, expected_kind, - "async ", + "Async", ); self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs index 5ed65425f34e..8309cfbd58f1 100644 --- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs @@ -10,7 +10,7 @@ fn main() { block_on::block_on(async { let x = async || {}; - async fn needs_async_fn_mut(mut x: impl async FnMut()) { + async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) { x().await; } needs_async_fn_mut(x).await; diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs index be4364653159..e7644e3dfe02 100644 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs @@ -8,7 +8,7 @@ extern crate block_on; fn main() { block_on::block_on(async { - async fn needs_async_fn_once(x: impl async FnOnce()) { + async fn needs_async_fn_once(x: impl AsyncFnOnce()) { x().await; } diff --git a/tests/ui/async-await/async-closures/auxiliary/foreign.rs b/tests/ui/async-await/async-closures/auxiliary/foreign.rs index 2c935f5e1fa8..33548a1b30dd 100644 --- a/tests/ui/async-await/async-closures/auxiliary/foreign.rs +++ b/tests/ui/async-await/async-closures/auxiliary/foreign.rs @@ -2,6 +2,6 @@ #![feature(async_closure)] -pub fn closure() -> impl async Fn() { +pub fn closure() -> impl AsyncFn() { async || { /* Don't really need to do anything here. */ } } diff --git a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs index 4382a689e756..a72ff8e5dce6 100644 --- a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs +++ b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs @@ -11,7 +11,7 @@ extern crate block_on; async fn empty() {} -pub async fn call_once(f: F) { +pub async fn call_once(f: F) { f().await; } diff --git a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs index 8b2de578b249..5ec1c5ee50ea 100644 --- a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs +++ b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs @@ -16,7 +16,7 @@ impl Trait for (i32,) { } } -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs index 5168f3696d7d..db1f5d271c6c 100644 --- a/tests/ui/async-await/async-closures/brand.rs +++ b/tests/ui/async-await/async-closures/brand.rs @@ -13,7 +13,7 @@ struct S; struct B<'b>(PhantomData<&'b mut &'b mut ()>); impl S { - async fn q)>(self, f: F) { + async fn q)>(self, f: F) { f(B(PhantomData)).await; } } diff --git a/tests/ui/async-await/async-closures/captures.rs b/tests/ui/async-await/async-closures/captures.rs index 0a9d0529bf54..2bd4b6859979 100644 --- a/tests/ui/async-await/async-closures/captures.rs +++ b/tests/ui/async-await/async-closures/captures.rs @@ -13,11 +13,11 @@ fn main() { block_on::block_on(async_main()); } -async fn call(f: &impl async Fn() -> T) -> T { +async fn call(f: &impl AsyncFn() -> T) -> T { f().await } -async fn call_once(f: impl async FnOnce() -> T) -> T { +async fn call_once(f: impl AsyncFnOnce() -> T) -> T { f().await } @@ -80,7 +80,7 @@ async fn async_main() { call_once(c).await; } - fn force_fnonce(f: impl async FnOnce() -> T) -> impl async FnOnce() -> T { + fn force_fnonce(f: impl AsyncFnOnce() -> T) -> impl AsyncFnOnce() -> T { f } diff --git a/tests/ui/async-await/async-closures/clone-closure.rs b/tests/ui/async-await/async-closures/clone-closure.rs index 807897e3e031..a9e1d6bccc77 100644 --- a/tests/ui/async-await/async-closures/clone-closure.rs +++ b/tests/ui/async-await/async-closures/clone-closure.rs @@ -7,7 +7,7 @@ extern crate block_on; -async fn for_each(f: impl async FnOnce(&str) + Clone) { +async fn for_each(f: impl AsyncFnOnce(&str) + Clone) { f.clone()("world").await; f.clone()("world2").await; } diff --git a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs index 3b222d00baea..1acbf0311b3a 100644 --- a/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs +++ b/tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs @@ -6,7 +6,7 @@ #![feature(async_closure)] -fn constrain(t: T) -> T { +fn constrain(t: T) -> T { t } @@ -14,7 +14,7 @@ fn call_once(f: impl FnOnce() -> T) -> T { f() } -async fn async_call_once(f: impl async FnOnce() -> T) -> T { +async fn async_call_once(f: impl AsyncFnOnce() -> T) -> T { f().await } diff --git a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs index 6f339f0c8ef1..f71cc1ef537a 100644 --- a/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs +++ b/tests/ui/async-await/async-closures/debuginfo-by-move-body.rs @@ -7,7 +7,7 @@ extern crate block_on; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs index 2884a20f244e..9c99550e3b7b 100644 --- a/tests/ui/async-await/async-closures/drop.rs +++ b/tests/ui/async-await/async-closures/drop.rs @@ -16,7 +16,7 @@ impl Drop for DropMe { } } -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { println!("before call"); let fut = Box::pin(f()); println!("after call"); diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.rs b/tests/ui/async-await/async-closures/fn-exception-target-features.rs index de62fc8bf7e3..eb554650b7c9 100644 --- a/tests/ui/async-await/async-closures/fn-exception-target-features.rs +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.rs @@ -10,7 +10,7 @@ use std::future::Future; #[target_feature(enable = "sse2")] fn target_feature() -> Pin + 'static>> { todo!() } -fn test(f: impl async Fn()) {} +fn test(f: impl AsyncFn()) {} fn main() { test(target_feature); //~ ERROR the trait bound diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr index e965c40fb5b8..db5895108bb0 100644 --- a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr @@ -9,8 +9,8 @@ LL | test(target_feature); note: required by a bound in `test` --> $DIR/fn-exception-target-features.rs:13:17 | -LL | fn test(f: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `test` +LL | fn test(f: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `test` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-closures/fn-exception.rs b/tests/ui/async-await/async-closures/fn-exception.rs index 0e06ebf48a4b..36cb955cd5cc 100644 --- a/tests/ui/async-await/async-closures/fn-exception.rs +++ b/tests/ui/async-await/async-closures/fn-exception.rs @@ -13,7 +13,7 @@ unsafe extern "C" { pub safe fn abi() -> Pin + 'static>>; } -fn test(f: impl async Fn()) {} +fn test(f: impl AsyncFn()) {} fn main() { test(unsafety); //~ ERROR the trait bound diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr index 20132e428332..b3118664c15e 100644 --- a/tests/ui/async-await/async-closures/fn-exception.stderr +++ b/tests/ui/async-await/async-closures/fn-exception.stderr @@ -9,8 +9,8 @@ LL | test(unsafety); note: required by a bound in `test` --> $DIR/fn-exception.rs:16:17 | -LL | fn test(f: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `test` +LL | fn test(f: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `test` error[E0277]: the trait bound `extern "C" fn() -> Pin + 'static)>> {abi}: AsyncFn()` is not satisfied --> $DIR/fn-exception.rs:20:10 @@ -23,8 +23,8 @@ LL | test(abi); note: required by a bound in `test` --> $DIR/fn-exception.rs:16:17 | -LL | fn test(f: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `test` +LL | fn test(f: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `test` error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs index 7ce210a33c3e..c20e3664d8b0 100644 --- a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs +++ b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs @@ -6,7 +6,7 @@ extern crate block_on; -fn force_fnonce(t: T) -> T { t } +fn force_fnonce(t: T) -> T { t } fn main() { block_on::block_on(async { diff --git a/tests/ui/async-await/async-closures/foreign.rs b/tests/ui/async-await/async-closures/foreign.rs index ab6fe06a3f4b..a244eef41029 100644 --- a/tests/ui/async-await/async-closures/foreign.rs +++ b/tests/ui/async-await/async-closures/foreign.rs @@ -12,7 +12,7 @@ extern crate foreign; struct NoCopy; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/implements-fnmut.rs b/tests/ui/async-await/async-closures/implements-fnmut.rs index 8e780ce9889a..f49d1423c404 100644 --- a/tests/ui/async-await/async-closures/implements-fnmut.rs +++ b/tests/ui/async-await/async-closures/implements-fnmut.rs @@ -1,7 +1,7 @@ //@ build-pass //@ edition: 2021 -// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!) +// Demonstrates that an async closure may implement `FnMut` (not just `AsyncFnMut`!) // if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env, // since it's fine to reborrow it with its original lifetime. See the doc comment on // `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we diff --git a/tests/ui/async-await/async-closures/inline-body.rs b/tests/ui/async-await/async-closures/inline-body.rs index a842d98d1de4..1bd2da6e8995 100644 --- a/tests/ui/async-await/async-closures/inline-body.rs +++ b/tests/ui/async-await/async-closures/inline-body.rs @@ -24,7 +24,7 @@ pub fn block_on(fut: impl Future) -> T { } } -async fn call_once(f: impl async FnOnce() -> T) -> T { +async fn call_once(f: impl AsyncFnOnce() -> T) -> T { f().await } diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs index a428905e40b7..3032ca3c02bb 100644 --- a/tests/ui/async-await/async-closures/mangle.rs +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -13,11 +13,11 @@ use std::future::Future; use std::pin::pin; use std::task::*; -async fn call_mut(f: &mut impl async FnMut()) { +async fn call_mut(f: &mut impl AsyncFnMut()) { f().await; } -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/moro-example.rs b/tests/ui/async-await/async-closures/moro-example.rs index 5a8f42c7ca5a..c331b8e5b5e9 100644 --- a/tests/ui/async-await/async-closures/moro-example.rs +++ b/tests/ui/async-await/async-closures/moro-example.rs @@ -22,7 +22,7 @@ impl<'scope, 'env: 'scope> Scope<'scope, 'env> { fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()> where - for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>), + for<'scope> B: AsyncFnOnce(&'scope Scope<'scope, 'env>), { todo!() } diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs index 79e2298f6092..d0e2bc24b52e 100644 --- a/tests/ui/async-await/async-closures/move-is-async-fn.rs +++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs @@ -19,7 +19,7 @@ fn main() { is_static(&c); // Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures. - fn call_once(f: F) -> F::CallOnceFuture { f() } + fn call_once(f: F) -> F::CallOnceFuture { f() } is_static(&call_once(c)); }); } diff --git a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs index 9f2cbd7ce1c3..c37048398e97 100644 --- a/tests/ui/async-await/async-closures/mut-ref-reborrow.rs +++ b/tests/ui/async-await/async-closures/mut-ref-reborrow.rs @@ -9,7 +9,7 @@ extern crate block_on; -async fn call_once(f: impl async FnOnce()) { f().await; } +async fn call_once(f: impl AsyncFnOnce()) { f().await; } pub async fn async_closure(x: &mut i32) { let c = async move || { diff --git a/tests/ui/async-await/async-closures/no-borrow-from-env.rs b/tests/ui/async-await/async-closures/no-borrow-from-env.rs index 3f9d26b97130..36b10c06dcaf 100644 --- a/tests/ui/async-await/async-closures/no-borrow-from-env.rs +++ b/tests/ui/async-await/async-closures/no-borrow-from-env.rs @@ -5,7 +5,7 @@ fn outlives<'a>(_: impl Sized + 'a) {} -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs index cd9d98d07992..cfb50dd5574d 100644 --- a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs +++ b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs @@ -6,7 +6,7 @@ extern crate block_on; -fn wrapper(f: impl Fn(String)) -> impl async Fn(String) { +fn wrapper(f: impl Fn(String)) -> impl AsyncFn(String) { async move |s| f(s) } diff --git a/tests/ui/async-await/async-closures/overlapping-projs.rs b/tests/ui/async-await/async-closures/overlapping-projs.rs index 6dd00b16103f..f778534cfe26 100644 --- a/tests/ui/async-await/async-closures/overlapping-projs.rs +++ b/tests/ui/async-await/async-closures/overlapping-projs.rs @@ -7,7 +7,7 @@ extern crate block_on; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/precise-captures.rs b/tests/ui/async-await/async-closures/precise-captures.rs index c4c67df544fb..7dcbf2595f0d 100644 --- a/tests/ui/async-await/async-closures/precise-captures.rs +++ b/tests/ui/async-await/async-closures/precise-captures.rs @@ -5,7 +5,7 @@ //@ revisions: call call_once force_once // call - Call the closure regularly. -// call_once - Call the closure w/ `async FnOnce`, so exercising the by_move shim. +// call_once - Call the closure w/ `AsyncFnOnce`, so exercising the by_move shim. // force_once - Force the closure mode to `FnOnce`, so exercising what was fixed // in . @@ -20,7 +20,7 @@ macro_rules! call { } #[cfg(call_once)] -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await } @@ -35,7 +35,7 @@ macro_rules! guidance { } #[cfg(force_once)] -fn infer_fnonce(c: impl async FnOnce()) -> impl async FnOnce() { c } +fn infer_fnonce(c: impl AsyncFnOnce()) -> impl AsyncFnOnce() { c } #[cfg(force_once)] macro_rules! guidance { diff --git a/tests/ui/async-await/async-closures/refd.rs b/tests/ui/async-await/async-closures/refd.rs index 0b8d3d7aff55..8c16ecb15313 100644 --- a/tests/ui/async-await/async-closures/refd.rs +++ b/tests/ui/async-await/async-closures/refd.rs @@ -10,15 +10,15 @@ struct NoCopy; fn main() { block_on::block_on(async { - async fn call_once(x: impl async Fn()) { x().await } + async fn call_once(x: impl AsyncFn()) { x().await } - // check that `&{async-closure}` implements `async Fn`. + // check that `&{async-closure}` implements `AsyncFn`. call_once(&async || {}).await; - // check that `&{closure}` implements `async Fn`. + // check that `&{closure}` implements `AsyncFn`. call_once(&|| async {}).await; - // check that `&fndef` implements `async Fn`. + // check that `&fndef` implements `AsyncFn`. async fn foo() {} call_once(&foo).await; }); diff --git a/tests/ui/async-await/async-closures/signature-deduction.rs b/tests/ui/async-await/async-closures/signature-deduction.rs index 856f3963ee6a..4e9a6747f1f3 100644 --- a/tests/ui/async-await/async-closures/signature-deduction.rs +++ b/tests/ui/async-await/async-closures/signature-deduction.rs @@ -3,7 +3,7 @@ #![feature(async_closure)] -async fn foo(x: impl async Fn(&str) -> &str) {} +async fn foo(x: impl AsyncFn(&str) -> &str) {} fn main() { foo(async |x| x); diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs index be3f032b8ff8..19f366cc903c 100644 --- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs +++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs @@ -8,7 +8,7 @@ fn outlives<'a>(_: impl Sized + 'a) {} -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs index 3d6f856874f2..a566b8aa6639 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -2,7 +2,7 @@ #![feature(async_closure)] -fn needs_async_fn(_: impl async Fn()) {} +fn needs_async_fn(_: impl AsyncFn()) {} fn a() { let mut x = 1; @@ -15,7 +15,7 @@ fn a() { fn b() { let x = String::new(); needs_async_fn(move || async move { - //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` + //~^ ERROR expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce` println!("{x}"); }); } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index 4b626c1bed6c..d03b10ca2cc1 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -1,29 +1,29 @@ -error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce` +error[E0525]: expected a closure that implements the `AsyncFn` trait, but this closure only implements `AsyncFnOnce` --> $DIR/wrong-fn-kind.rs:17:20 | LL | needs_async_fn(move || async move { | -------------- -^^^^^^ | | | - | _____|______________this closure implements `async FnOnce`, not `async Fn` + | _____|______________this closure implements `AsyncFnOnce`, not `AsyncFn` | | | | | required by a bound introduced by this call LL | | LL | | println!("{x}"); - | | - closure is `async FnOnce` because it moves the variable `x` out of its environment + | | - closure is `AsyncFnOnce` because it moves the variable `x` out of its environment LL | | }); - | |_____- the requirement to implement `async Fn` derives from here + | |_____- the requirement to implement `AsyncFn` derives from here | note: required by a bound in `needs_async_fn` --> $DIR/wrong-fn-kind.rs:5:27 | -LL | fn needs_async_fn(_: impl async Fn()) {} - | ^^^^^^^^^^ required by this bound in `needs_async_fn` +LL | fn needs_async_fn(_: impl AsyncFn()) {} + | ^^^^^^^^^ required by this bound in `needs_async_fn` error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/wrong-fn-kind.rs:9:20 | -LL | fn needs_async_fn(_: impl async Fn()) {} - | --------------- change this to accept `FnMut` instead of `Fn` +LL | fn needs_async_fn(_: impl AsyncFn()) {} + | -------------- change this to accept `FnMut` instead of `Fn` ... LL | needs_async_fn(async || { | -------------- ^^^^^^^^ diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs index f8da517213ae..5d6759210288 100644 --- a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs +++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs @@ -15,7 +15,7 @@ async fn f(arg: &i32) {} async fn func(f: F) where - F: for<'a> async Fn(&'a i32), + F: for<'a> AsyncFn(&'a i32), { let x: i32 = 0; f(&x).await; diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs index 686addcb1a91..11faf9ac9830 100644 --- a/tests/ui/async-await/async-fn/impl-trait.rs +++ b/tests/ui/async-await/async-fn/impl-trait.rs @@ -3,13 +3,13 @@ #![feature(async_closure, type_alias_impl_trait)] -type Tait = impl async Fn(); +type Tait = impl AsyncFn(); fn tait() -> Tait { || async {} } -fn foo(x: impl async Fn()) -> impl async Fn() { x } +fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x } -fn param() {} +fn param() {} fn main() {} diff --git a/tests/ui/async-await/async-fn/project.rs b/tests/ui/async-await/async-fn/project.rs index 5cbdc378dda2..b6068a916aea 100644 --- a/tests/ui/async-await/async-fn/project.rs +++ b/tests/ui/async-await/async-fn/project.rs @@ -6,7 +6,9 @@ #![feature(async_closure, unboxed_closures, async_fn_traits)] -fn project>(_: F) -> Option { None } +use std::ops::AsyncFn; + +fn project>(_: F) -> Option { None } fn main() { let x: Option = project(|| async { 1i32 }); From 59e3e8934e3e50ddb9b9a9ffaa523cbab2260598 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 4 Nov 2024 19:29:02 +0000 Subject: [PATCH 301/330] Gate async fn trait bound modifier on async_trait_bounds --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 ++++ compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_parse/src/parser/ty.rs | 4 ++-- compiler/rustc_span/src/symbol.rs | 1 + .../miri/tests/pass/async-closure-captures.rs | 2 +- .../miri/tests/pass/async-closure-drop.rs | 2 +- tests/codegen/async-closure-debug.rs | 2 +- tests/coverage/async_closure.cov-map | 8 +++---- tests/coverage/async_closure.coverage | 2 +- tests/coverage/async_closure.rs | 2 +- tests/crashes/124020.rs | 4 ++-- tests/ui/async-await/async-fn/dyn-pos.rs | 2 +- tests/ui/async-await/async-fn/dyn-pos.stderr | 4 ++-- tests/ui/async-await/async-fn/edition-2015.rs | 4 ++-- .../async-await/async-fn/edition-2015.stderr | 12 +++++----- ...sync-trait-bound-theoretical-regression.rs | 4 ++-- ...-trait-bound-theoretical-regression.stderr | 12 +++++----- tests/ui/async-await/async-fn/not-a-trait.rs | 2 +- tests/ui/async-await/async-fn/sugar.rs | 2 +- .../async-fn/trait-bounds-in-macro.rs | 2 +- .../async-fn/trait-bounds-in-macro.stderr | 6 ++--- tests/ui/async-await/async-fn/wrong-trait.rs | 2 +- .../feature-gate-async-trait-bounds.rs | 7 ++++++ .../feature-gate-async-trait-bounds.stderr | 24 +++++++++++++++++++ .../precise-capturing/bound-modifiers.rs | 2 +- .../precise-capturing/bound-modifiers.stderr | 6 ++--- tests/ui/parser/bad-recover-kw-after-impl.rs | 2 +- .../parser/bad-recover-kw-after-impl.stderr | 6 ++--- 28 files changed, 86 insertions(+), 47 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-async-trait-bounds.rs create mode 100644 tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 8cdc7133cc07..0c925cd8fa21 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "async closures are unstable", "to use an async block, remove the `||`: `async {`" ); + gate_all!( + async_trait_bounds, + "`async` trait bounds are unstable", + "use the desugared name of the async trait, such as `AsyncFn`" + ); gate_all!(async_for_loop, "`for await` loops are experimental"); gate_all!( closure_lifetime_binder, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index ec908762da72..cb6bc03f9e22 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -394,6 +394,8 @@ declare_features! ( (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. (unstable, async_for_loop, "1.77.0", Some(118898)), + /// Allows `async` trait bound modifier. + (unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg()]`. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 505586e74f11..1340558d9688 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -940,7 +940,7 @@ impl<'a> Parser<'a> { let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Async) { - self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else if self.may_recover() && self.token.uninterpolated_span().is_rust_2015() @@ -951,7 +951,7 @@ impl<'a> Parser<'a> { span: self.prev_token.span, help: HelpUseLatestEdition::new(), }); - self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else { BoundAsyncness::Normal diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e94c0a5ea6e7..b2ca86bf486f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -468,6 +468,7 @@ symbols! { async_for_loop, async_iterator, async_iterator_poll_next, + async_trait_bounds, atomic, atomic_mod, atomics, diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs index cac26bfe1462..423ef7a5cf7e 100644 --- a/src/tools/miri/tests/pass/async-closure-captures.rs +++ b/src/tools/miri/tests/pass/async-closure-captures.rs @@ -1,6 +1,6 @@ // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync -#![feature(async_closure, noop_waker)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs index 9b2fc2948bf4..264da5a95183 100644 --- a/src/tools/miri/tests/pass/async-closure-drop.rs +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -1,4 +1,4 @@ -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs index 9cb1e623295b..644df169a368 100644 --- a/tests/codegen/async-closure-debug.rs +++ b/tests/codegen/async-closure-debug.rs @@ -9,7 +9,7 @@ #![feature(async_closure)] -fn async_closure_test(upvar: &str) -> impl async Fn() + '_ { +fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ { async move || { let hello = String::from("hello"); println!("{hello}, {upvar}"); diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 4d00f0d9b337..9ff29af8e8ec 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -1,19 +1,19 @@ Function name: async_closure::call_once:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44) +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43) Highest counter ID seen: c0 Function name: async_closure::call_once::::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14) +- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index fd6edf7c29e3..75da1a01fc1d 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -4,7 +4,7 @@ LL| |//@ aux-build: executor.rs LL| |extern crate executor; LL| | - LL| 1|async fn call_once(f: impl async FnOnce()) { + LL| 1|async fn call_once(f: impl AsyncFnOnce()) { LL| 1| f().await; LL| 1|} LL| | diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async_closure.rs index c076d03eef43..cbac592d9577 100644 --- a/tests/coverage/async_closure.rs +++ b/tests/coverage/async_closure.rs @@ -4,7 +4,7 @@ //@ aux-build: executor.rs extern crate executor; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/crashes/124020.rs b/tests/crashes/124020.rs index f461f32f59d1..1b875497465c 100644 --- a/tests/crashes/124020.rs +++ b/tests/crashes/124020.rs @@ -1,7 +1,7 @@ //@ known-bug: #124020 //@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; @@ -19,7 +19,7 @@ pub fn block_on(fut: impl Future) -> T { } } -async fn call_once(f: impl async FnOnce(DropMe)) { +async fn call_once(f: impl AsyncFnOnce(DropMe)) { f(DropMe("world")).await; } diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs index a16b7c26f0d5..129ea2829362 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.rs +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -2,7 +2,7 @@ #![feature(async_closure)] -fn foo(x: &dyn async Fn()) {} +fn foo(x: &dyn AsyncFn()) {} //~^ ERROR the trait `AsyncFnMut` cannot be made into an object fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr index a9abfc5e5c46..aaa8eb2634d0 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.stderr +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `AsyncFnMut` cannot be made into an object --> $DIR/dyn-pos.rs:5:16 | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object +LL | fn foo(x: &dyn AsyncFn()) {} + | ^^^^^^^^^ `AsyncFnMut` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs index e38179758f6b..7fc62a8dd93d 100644 --- a/tests/ui/async-await/async-fn/edition-2015.rs +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -1,8 +1,8 @@ fn foo(x: impl async Fn()) -> impl async Fn() { x } //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later -//~| ERROR async closures are unstable -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable +//~| ERROR `async` trait bounds are unstable //~| ERROR use of unstable library feature `async_closure` //~| ERROR use of unstable library feature `async_closure` diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr index 9fbceafd75d7..96fb4c9e9791 100644 --- a/tests/ui/async-await/async-fn/edition-2015.stderr +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -16,27 +16,27 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = help: pass `--edition 2024` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/edition-2015.rs:1:16 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/edition-2015.rs:1:36 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: use of unstable library feature `async_closure` --> $DIR/edition-2015.rs:1:42 diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs index abc429772fdc..ea67831b68e6 100644 --- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs +++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs @@ -13,9 +13,9 @@ macro_rules! demo { } demo! { impl async Trait } -//~^ ERROR async closures are unstable +//~^ ERROR `async` trait bounds are unstable demo! { dyn async Trait } -//~^ ERROR async closures are unstable +//~^ ERROR `async` trait bounds are unstable fn main() {} diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr index 13b8e72b49dc..a463944d1133 100644 --- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr +++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr @@ -20,27 +20,27 @@ LL | demo! { dyn async Trait } | = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14 | LL | demo! { impl async Trait } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13 | LL | demo! { dyn async Trait } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs index 0d22cbd2c073..5cf23f2456a8 100644 --- a/tests/ui/async-await/async-fn/not-a-trait.rs +++ b/tests/ui/async-await/async-fn/not-a-trait.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(async_closure)] +#![feature(async_trait_bounds)] struct S; diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs index 29b6abc814a4..0225b666ac58 100644 --- a/tests/ui/async-await/async-fn/sugar.rs +++ b/tests/ui/async-await/async-fn/sugar.rs @@ -1,7 +1,7 @@ //@ edition: 2021 //@ check-pass -#![feature(async_closure)] +#![feature(async_closure, async_trait_bounds)] async fn foo() {} diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs index 329a1528e8b4..654883966f40 100644 --- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs +++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs @@ -6,7 +6,7 @@ macro_rules! x { x! { async fn foo() -> impl async Fn() { } - //~^ ERROR async closures are unstable + //~^ ERROR `async` trait bounds are unstable } fn main() {} diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr index f68c09737dbc..259e13cd1fe2 100644 --- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr +++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr @@ -1,13 +1,13 @@ -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/trait-bounds-in-macro.rs:8:28 | LL | async fn foo() -> impl async Fn() { } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs index e6fb0b46712d..38d6bb1d01a9 100644 --- a/tests/ui/async-await/async-fn/wrong-trait.rs +++ b/tests/ui/async-await/async-fn/wrong-trait.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(async_closure)] +#![feature(async_trait_bounds)] trait Foo {} diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs new file mode 100644 index 000000000000..db5d7aa06d22 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs @@ -0,0 +1,7 @@ +//@ edition: 2021 + +fn test(_: impl async Fn()) {} +//~^ ERROR `async` trait bounds are unstable +//~| ERROR use of unstable library feature `async_closure` + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr new file mode 100644 index 000000000000..abc7e37c45f2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr @@ -0,0 +1,24 @@ +error[E0658]: `async` trait bounds are unstable + --> $DIR/feature-gate-async-trait-bounds.rs:3:17 + | +LL | fn test(_: impl async Fn()) {} + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: use the desugared name of the async trait, such as `AsyncFn` + +error[E0658]: use of unstable library feature `async_closure` + --> $DIR/feature-gate-async-trait-bounds.rs:3:23 + | +LL | fn test(_: impl async Fn()) {} + | ^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` 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 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs index 46121308fa07..cac5ae177d2f 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs @@ -7,7 +7,7 @@ fn polarity() -> impl Sized + ?use<> {} fn asyncness() -> impl Sized + async use<> {} //~^ ERROR expected identifier, found keyword `use` //~| ERROR cannot find trait `r#use` in this scope -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable fn constness() -> impl Sized + const use<> {} //~^ ERROR expected identifier, found keyword `use` diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr index 16e7470debf0..d4b5b47b41b5 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -46,16 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope LL | fn binder() -> impl Sized + for<'a> use<> {} | ^^^ not found in this scope -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/bound-modifiers.rs:7:32 | LL | fn asyncness() -> impl Sized + async use<> {} | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: const trait impls are experimental --> $DIR/bound-modifiers.rs:12:32 diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs index 15c0b377c8ae..964d32c55bc1 100644 --- a/tests/ui/parser/bad-recover-kw-after-impl.rs +++ b/tests/ui/parser/bad-recover-kw-after-impl.rs @@ -12,6 +12,6 @@ macro_rules! impl_primitive { impl_primitive!(impl async); //~^ ERROR expected identifier, found `` -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable fn main() {} diff --git a/tests/ui/parser/bad-recover-kw-after-impl.stderr b/tests/ui/parser/bad-recover-kw-after-impl.stderr index f617cf654988..7a8979db165a 100644 --- a/tests/ui/parser/bad-recover-kw-after-impl.stderr +++ b/tests/ui/parser/bad-recover-kw-after-impl.stderr @@ -7,16 +7,16 @@ LL | ($ty:ty) => { LL | impl_primitive!(impl async); | ^^^^^ expected identifier -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/bad-recover-kw-after-impl.rs:13:22 | LL | impl_primitive!(impl async); | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 2 previous errors From 43bed16b8bc4f410934d6cf983a8f3c84d66ac91 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 1 Dec 2024 18:19:20 +0100 Subject: [PATCH 302/330] Reduce conflicts for check-cfg `target_feature` cfg values --- tests/ui/check-cfg/target_feature.rs | 18 ++ tests/ui/check-cfg/target_feature.stderr | 297 ++++++++++++++++++++ tests/ui/check-cfg/well-known-values.rs | 4 +- tests/ui/check-cfg/well-known-values.stderr | 11 +- 4 files changed, 318 insertions(+), 12 deletions(-) create mode 100644 tests/ui/check-cfg/target_feature.rs create mode 100644 tests/ui/check-cfg/target_feature.stderr diff --git a/tests/ui/check-cfg/target_feature.rs b/tests/ui/check-cfg/target_feature.rs new file mode 100644 index 000000000000..6028dae66c4d --- /dev/null +++ b/tests/ui/check-cfg/target_feature.rs @@ -0,0 +1,18 @@ +// This test prints all the possible values for the `target_feature` cfg +// as a way to assert the expected values and reflect on any changes made +// to the `target_feature` cfg in the compiler. +// +// The output of this test does not reflect the actual output seen by +// users which will see a truncated list of possible values (at worst). +// +// In case of test output differences, just `--bless` the test. +// +//@ check-pass +//@ no-auto-check-cfg +//@ compile-flags: --check-cfg=cfg() -Zcheck-cfg-all-expected +//@ normalize-stderr-test: "`, `" -> "`\n`" + +fn main() { + cfg!(target_feature = "_UNEXPECTED_VALUE"); + //~^ WARNING unexpected `cfg` condition value +} diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr new file mode 100644 index 000000000000..2674a97a551e --- /dev/null +++ b/tests/ui/check-cfg/target_feature.stderr @@ -0,0 +1,297 @@ +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/target_feature.rs:16:10 + | +LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_feature` are: `10e60` +`2e3` +`3e3r1` +`3e3r2` +`3e3r3` +`3e7` +`7e10` +`a` +`aclass` +`adx` +`aes` +`altivec` +`alu32` +`amx-bf16` +`amx-complex` +`amx-fp16` +`amx-int8` +`amx-tile` +`atomics` +`avx` +`avx2` +`avx512bf16` +`avx512bitalg` +`avx512bw` +`avx512cd` +`avx512dq` +`avx512f` +`avx512fp16` +`avx512ifma` +`avx512vbmi` +`avx512vbmi2` +`avx512vl` +`avx512vnni` +`avx512vp2intersect` +`avx512vpopcntdq` +`avxifma` +`avxneconvert` +`avxvnni` +`avxvnniint16` +`avxvnniint8` +`backchain` +`bf16` +`bmi1` +`bmi2` +`bti` +`bulk-memory` +`c` +`cache` +`cmpxchg16b` +`crc` +`crt-static` +`cssc` +`d` +`d32` +`dit` +`doloop` +`dotprod` +`dpb` +`dpb2` +`dsp` +`dsp1e2` +`dspe60` +`e` +`e1` +`e2` +`ecv` +`edsp` +`elrw` +`ermsb` +`exception-handling` +`extended-const` +`f` +`f16c` +`f32mm` +`f64mm` +`faminmax` +`fcma` +`fdivdu` +`fhm` +`flagm` +`flagm2` +`float1e2` +`float1e3` +`float3e4` +`float7e60` +`floate1` +`fma` +`fp-armv8` +`fp16` +`fp64` +`fp8` +`fp8dot2` +`fp8dot4` +`fp8fma` +`fpuv2_df` +`fpuv2_sf` +`fpuv3_df` +`fpuv3_hf` +`fpuv3_hi` +`fpuv3_sf` +`frecipe` +`frintts` +`fxsr` +`gfni` +`hard-float` +`hard-float-abi` +`hard-tp` +`hbc` +`high-registers` +`hvx` +`hvx-length128b` +`hwdiv` +`i8mm` +`jsconv` +`lahfsahf` +`lasx` +`lbt` +`leoncasa` +`lor` +`lse` +`lse128` +`lse2` +`lsx` +`lut` +`lvz` +`lzcnt` +`m` +`mclass` +`mops` +`movbe` +`mp` +`mp1e2` +`msa` +`mte` +`multivalue` +`mutable-globals` +`neon` +`nontrapping-fptoint` +`nvic` +`paca` +`pacg` +`pan` +`partword-atomics` +`pauth-lr` +`pclmulqdq` +`pmuv3` +`popcnt` +`power10-vector` +`power8-altivec` +`power8-vector` +`power9-altivec` +`power9-vector` +`prfchw` +`quadword-atomics` +`rand` +`ras` +`rclass` +`rcpc` +`rcpc2` +`rcpc3` +`rdm` +`rdrand` +`rdseed` +`reference-types` +`relax` +`relaxed-simd` +`reserve-x18` +`rtm` +`sb` +`sha` +`sha2` +`sha3` +`sha512` +`sign-ext` +`simd128` +`sm3` +`sm4` +`sme` +`sme-b16b16` +`sme-f16f16` +`sme-f64f64` +`sme-f8f16` +`sme-f8f32` +`sme-fa64` +`sme-i16i64` +`sme-lutv2` +`sme2` +`sme2p1` +`spe` +`ssbs` +`sse` +`sse2` +`sse3` +`sse4.1` +`sse4.2` +`sse4a` +`ssse3` +`ssve-fp8dot2` +`ssve-fp8dot4` +`ssve-fp8fma` +`sve` +`sve-b16b16` +`sve2` +`sve2-aes` +`sve2-bitperm` +`sve2-sha3` +`sve2-sm4` +`sve2p1` +`tail-call` +`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` +`v8.8a` +`v8.9a` +`v8plus` +`v9` +`v9.1a` +`v9.2a` +`v9.3a` +`v9.4a` +`v9.5a` +`v9a` +`vaes` +`vdsp2e60f` +`vdspv1` +`vdspv2` +`vector` +`vfp2` +`vfp3` +`vfp4` +`vh` +`virt` +`virtualization` +`vpclmulqdq` +`vsx` +`wfxt` +`wide-arithmetic` +`xop` +`xsave` +`xsavec` +`xsaveopt` +`xsaves` +`zaamo` +`zabha` +`zalrsc` +`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 + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 1fda4b2089ec..40b7b2db8365 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -60,8 +60,8 @@ //~^ WARN unexpected `cfg` condition value target_family = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value - target_feature = "_UNEXPECTED_VALUE", - //~^ WARN unexpected `cfg` condition value + // target_feature = "_UNEXPECTED_VALUE", + // ^ tested in target_feature.rs target_has_atomic = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 4d375d80e771..7c03d0570db5 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -168,15 +168,6 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: expected values for `target_family` are: `unix`, `wasm`, and `windows` = note: see for more information about checking conditional configuration -warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:63:5 - | -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`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `reserve-x18`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tail-call`, `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`, `v8.8a`, `v8.9a`, `v8plus`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `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` --> $DIR/well-known-values.rs:65:5 | @@ -297,5 +288,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration -warning: 30 warnings emitted +warning: 29 warnings emitted From 72297d42723510f90c208f3971d1e408e27361bc Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 2 Dec 2024 18:26:00 +0100 Subject: [PATCH 303/330] Fix `f16::midpoint` const feature gate --- library/core/src/num/f16.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 5e1098c877f5..c82f0d7cd4ad 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -803,7 +803,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f128", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] pub const fn midpoint(self, other: f16) -> f16 { const LO: f16 = f16::MIN_POSITIVE * 2.; const HI: f16 = f16::MAX / 2.; From eadea7764ee49e11165ed041e529cbe79707a31c Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 30 Nov 2024 20:32:00 +0000 Subject: [PATCH 304/330] Use c"lit" for CStrings without unwrap --- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- .../src/error_codes/E0060.md | 13 +++----- library/alloc/src/ffi/c_str.rs | 32 +++++++++---------- library/alloc/src/ffi/c_str/tests.rs | 2 +- library/alloc/src/rc/tests.rs | 4 +-- library/alloc/src/sync/tests.rs | 4 +-- .../sys/pal/unix/process/process_common.rs | 2 +- .../tests/pass-dep/libc/libc-fs-symlink.rs | 3 +- .../pass-dep/libc/libc-fs-with-isolation.rs | 4 +-- .../miri/tests/pass-dep/libc/libc-mem.rs | 10 +++--- .../crates/profile/src/memory_usage.rs | 4 +-- tests/run-make/libtest-thread-limit/rmake.rs | 2 +- tests/ui/process/env-funky-keys.rs | 4 +-- 14 files changed, 38 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 48beb9be2b2a..f6d2ec24da6f 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -148,7 +148,7 @@ fn prepare_lto( // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to // __llvm_profile_runtime, therefore we won't know until link time if this symbol // should have default visibility. - symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap()); + symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned()); Ok((symbols_below_threshold, upstream_modules)) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 2744795d9981..bde6668929c5 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -509,7 +509,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option { } fn get_instr_profile_output_path(config: &ModuleConfig) -> Option { - config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap()) + config.instrument_coverage.then(|| c"default_%m_%p.profraw".to_owned()) } pub(crate) unsafe fn llvm_optimize( diff --git a/compiler/rustc_error_codes/src/error_codes/E0060.md b/compiler/rustc_error_codes/src/error_codes/E0060.md index 54b10c886ccc..a6831c881e3a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0060.md +++ b/compiler/rustc_error_codes/src/error_codes/E0060.md @@ -15,7 +15,7 @@ unsafe { printf(); } // error! Using this declaration, it must be called with at least one argument, so simply calling `printf()` is invalid. But the following uses are allowed: -``` +```rust,edition2021 # use std::os::raw::{c_char, c_int}; # #[cfg_attr(all(windows, target_env = "msvc"), # link(name = "legacy_stdio_definitions", @@ -23,16 +23,11 @@ simply calling `printf()` is invalid. But the following uses are allowed: # extern "C" { fn printf(_: *const c_char, ...) -> c_int; } # fn main() { unsafe { - use std::ffi::CString; + printf(c"test\n".as_ptr()); - let fmt = CString::new("test\n").unwrap(); - printf(fmt.as_ptr()); + printf(c"number = %d\n".as_ptr(), 3); - let fmt = CString::new("number = %d\n").unwrap(); - printf(fmt.as_ptr(), 3); - - let fmt = CString::new("%d, %d\n").unwrap(); - printf(fmt.as_ptr(), 10, 5); + printf(c"%d, %d\n".as_ptr(), 10, 5); } # } ``` diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index c739832bc784..9c074383a5ec 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -384,7 +384,7 @@ impl CString { /// fn some_extern_function(s: *mut c_char); /// } /// - /// let c_string = CString::new("Hello!").expect("CString::new failed"); + /// let c_string = CString::from(c"Hello!"); /// let raw = c_string.into_raw(); /// unsafe { /// some_extern_function(raw); @@ -429,7 +429,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// /// let ptr = c_string.into_raw(); /// @@ -487,7 +487,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.into_bytes(); /// assert_eq!(bytes, vec![b'f', b'o', b'o']); /// ``` @@ -508,7 +508,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.into_bytes_with_nul(); /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); /// ``` @@ -530,7 +530,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.as_bytes(); /// assert_eq!(bytes, &[b'f', b'o', b'o']); /// ``` @@ -550,7 +550,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.as_bytes_with_nul(); /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); /// ``` @@ -568,7 +568,7 @@ impl CString { /// ``` /// use std::ffi::{CString, CStr}; /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let cstr = c_string.as_c_str(); /// assert_eq!(cstr, /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); @@ -586,12 +586,9 @@ impl CString { /// # Examples /// /// ``` - /// use std::ffi::{CString, CStr}; - /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); + /// let c_string = c"foo".to_owned(); /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(&*boxed, - /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); + /// assert_eq!(boxed.to_bytes_with_nul(), b"foo\0"); /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_c_str", since = "1.20.0")] @@ -658,7 +655,7 @@ impl CString { /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) /// .expect("CString::from_vec_with_nul failed"), - /// CString::new(b"abc".to_vec()).expect("CString::new failed") + /// c"abc".to_owned() /// ); /// ``` /// @@ -1168,11 +1165,12 @@ impl CStr { /// # Examples /// /// ``` - /// use std::ffi::CString; + /// use std::ffi::{CStr, CString}; /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); - /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed")); + /// let boxed: Box = Box::from(c"foo"); + /// let c_string: CString = c"foo".to_owned(); + /// + /// assert_eq!(boxed.into_c_string(), c_string); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "`self` will be dropped if the result is not used"] diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs index 8b7172b3f20a..d6b797347c2e 100644 --- a/library/alloc/src/ffi/c_str/tests.rs +++ b/library/alloc/src/ffi/c_str/tests.rs @@ -159,7 +159,7 @@ fn boxed_default() { #[test] fn test_c_str_clone_into() { - let mut c_string = CString::new("lorem").unwrap(); + let mut c_string = c"lorem".to_owned(); let c_ptr = c_string.as_ptr(); let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap(); c_str.clone_into(&mut c_string); diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 333e1bde31c1..2210a7c24c06 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -349,9 +349,9 @@ fn test_unsized() { #[test] fn test_maybe_thin_unsized() { // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::{CStr, CString}; + use std::ffi::CStr; - let x: Rc = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + let x: Rc = Rc::from(c"swordfish"); assert_eq!(format!("{x:?}"), "\"swordfish\""); let y: Weak = Rc::downgrade(&x); drop(x); diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index 3f66c8899234..de5816fda974 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -412,9 +412,9 @@ fn test_unsized() { #[test] fn test_maybe_thin_unsized() { // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::{CStr, CString}; + use std::ffi::CStr; - let x: Arc = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + let x: Arc = Arc::from(c"swordfish"); assert_eq!(format!("{x:?}"), "\"swordfish\""); let y: Weak = Arc::downgrade(&x); drop(x); diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index 13290fed762a..342818ac9118 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -393,7 +393,7 @@ impl Command { fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString { CString::new(s.as_bytes()).unwrap_or_else(|_e| { *saw_nul = true; - CString::new("").unwrap() + c"".to_owned() }) } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index a35c92636ce6..4b49e105562f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -47,9 +47,8 @@ fn test_readlink() { assert_eq!(res, small_buf.len() as isize); // Test that we report a proper error for a missing path. - let bad_path = CString::new("MIRI_MISSING_FILE_NAME").unwrap(); let res = unsafe { - libc::readlink(bad_path.as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) + libc::readlink(c"MIRI_MISSING_FILE_NAME".as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) }; assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs index ab3fd6733ffe..cffcf4a867fe 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs @@ -2,7 +2,6 @@ //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" -use std::ffi::CString; use std::fs; use std::io::{Error, ErrorKind}; @@ -13,10 +12,9 @@ fn main() { } // test `readlink` - let symlink_c_str = CString::new("foo.txt").unwrap(); let mut buf = vec![0; "foo_link.txt".len() + 1]; unsafe { - assert_eq!(libc::readlink(symlink_c_str.as_ptr(), buf.as_mut_ptr(), buf.len()), -1); + assert_eq!(libc::readlink(c"foo.txt".as_ptr(), buf.as_mut_ptr(), buf.len()), -1); assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EACCES)); } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index 10be78798a60..727533a9de61 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -55,12 +55,12 @@ fn test_memcpy() { } fn test_strcpy() { - use std::ffi::{CStr, CString}; + use std::ffi::CStr; // case: src_size equals dest_size unsafe { - let src = CString::new("rust").unwrap(); - let size = src.as_bytes_with_nul().len(); + let src = c"rust"; + let size = src.to_bytes_with_nul().len(); let dest = libc::malloc(size); libc::strcpy(dest as *mut libc::c_char, src.as_ptr()); assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref()); @@ -69,8 +69,8 @@ fn test_strcpy() { // case: src_size is less than dest_size unsafe { - let src = CString::new("rust").unwrap(); - let size = src.as_bytes_with_nul().len(); + let src = c"rust"; + let size = src.to_bytes_with_nul().len(); let dest = libc::malloc(size + 1); libc::strcpy(dest as *mut libc::c_char, src.as_ptr()); assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref()); diff --git a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs index 660afff3dcaa..006748ddb08e 100644 --- a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs +++ b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs @@ -62,15 +62,13 @@ fn memusage_linux() -> MemoryUsage { // mallinfo2 is very recent, so its presence needs to be detected at runtime. // Both are abysmally slow. - use std::ffi::CStr; use std::sync::atomic::{AtomicUsize, Ordering}; static MALLINFO2: AtomicUsize = AtomicUsize::new(1); let mut mallinfo2 = MALLINFO2.load(Ordering::Relaxed); if mallinfo2 == 1 { - let cstr = CStr::from_bytes_with_nul(b"mallinfo2\0").unwrap(); - mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, cstr.as_ptr()) } as usize; + mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"mallinfo2".as_ptr()) } as usize; // NB: races don't matter here, since they'll always store the same value MALLINFO2.store(mallinfo2, Ordering::Relaxed); } diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs index 5decd802b347..fe14d2c046cc 100644 --- a/tests/run-make/libtest-thread-limit/rmake.rs +++ b/tests/run-make/libtest-thread-limit/rmake.rs @@ -38,7 +38,7 @@ fn main() { // If the process ID is 0, this is the child process responsible for running the test // program. if pid == 0 { - let test = CString::new("test").unwrap(); + let test = c"test"; // The argv array should be terminated with a NULL pointer. let argv = [test.as_ptr(), std::ptr::null()]; // rlim_cur is soft limit, rlim_max is hard limit. diff --git a/tests/ui/process/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs index 314ccaea0152..a4a71c94020c 100644 --- a/tests/ui/process/env-funky-keys.rs +++ b/tests/ui/process/env-funky-keys.rs @@ -1,4 +1,5 @@ //@ run-pass +//@ edition: 2021 // Ignore this test on Android, because it segfaults there. //@ ignore-android @@ -32,10 +33,9 @@ fn main() { .unwrap() .as_os_str() .as_bytes()).unwrap(); - let new_env_var = CString::new("FOOBAR").unwrap(); let filename: *const c_char = current_exe.as_ptr(); let argv: &[*const c_char] = &[filename, filename, ptr::null()]; - let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()]; + let envp: &[*const c_char] = &[c"FOOBAR".as_ptr(), ptr::null()]; unsafe { execve(filename, &argv[0], &envp[0]); } From c5fedc2267838ab9db5a98f946873685ae69097f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 14 Oct 2024 18:32:54 -0400 Subject: [PATCH 305/330] Stabilize `const_maybe_uninit_write` Mark the following API const stable: impl MaybeUninit { pub const fn write(&mut self, val: T) -> &mut T; } This depends on `const_mut_refs` and `const_maybe_uninit_assume_init`, both of which have recently been stabilized. Tracking issue: --- library/core/src/mem/maybe_uninit.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 3c1a098374ef..9b3d69020985 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -485,9 +485,9 @@ impl MaybeUninit { /// } /// } /// ``` - #[stable(feature = "maybe_uninit_write", since = "1.55.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_write", issue = "63567")] #[inline(always)] + #[stable(feature = "maybe_uninit_write", since = "1.55.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_write", since = "CURRENT_RUSTC_VERSION")] pub const fn write(&mut self, val: T) -> &mut T { *self = MaybeUninit::new(val); // SAFETY: We just initialized this value. From 2b88e4c7162573e97820d75bee4d3728076d34a8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Dec 2024 18:03:29 +0100 Subject: [PATCH 306/330] stabilize const_{size,align}_of_val --- library/core/src/alloc/layout.rs | 2 +- library/core/src/intrinsics/mod.rs | 2 ++ library/core/src/mem/mod.rs | 6 ++---- library/core/tests/lib.rs | 1 - .../ui/consts/const-size_of_val-align_of_val-extern-type.rs | 1 - .../const-size_of_val-align_of_val-extern-type.stderr | 4 ++-- tests/ui/consts/const-size_of_val-align_of_val.rs | 3 +-- 7 files changed, 8 insertions(+), 11 deletions(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 60936da2e0b0..d884fa69efbb 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -179,6 +179,7 @@ impl Layout { /// or other unsized type like a slice). #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[rustc_const_stable_indirect] #[must_use] #[inline] pub const fn for_value(t: &T) -> Self { @@ -215,7 +216,6 @@ impl Layout { /// [trait object]: ../../book/ch17-02-trait-objects.html /// [extern type]: ../../unstable-book/language-features/extern-types.html #[unstable(feature = "layout_for_ptr", issue = "69835")] - #[rustc_const_unstable(feature = "layout_for_ptr", issue = "69835")] #[must_use] pub const unsafe fn for_value_raw(t: *const T) -> Self { // SAFETY: we pass along the prerequisites of these functions to the caller diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 46873fdc0479..ea41cecfec24 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -4099,6 +4099,7 @@ pub const fn variant_count() -> usize { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] pub const unsafe fn size_of_val(_ptr: *const T) -> usize { unreachable!() } @@ -4114,6 +4115,7 @@ pub const unsafe fn size_of_val(_ptr: *const T) -> usize { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize { unreachable!() } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 4cf52042a57f..78ad6880709f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -333,7 +333,7 @@ pub const fn size_of() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")] +#[rustc_const_stable(feature = "const_size_of_val", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] pub const fn size_of_val(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer @@ -390,7 +390,6 @@ pub const fn size_of_val(val: &T) -> usize { #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] -#[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")] pub const unsafe fn size_of_val_raw(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer unsafe { intrinsics::size_of_val(val) } @@ -485,7 +484,7 @@ pub const fn align_of() -> usize { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")] +#[rustc_const_stable(feature = "const_align_of_val", since = "CURRENT_RUSTC_VERSION")] #[allow(deprecated)] pub const fn align_of_val(val: &T) -> usize { // SAFETY: val is a reference, so it's a valid raw pointer @@ -534,7 +533,6 @@ pub const fn align_of_val(val: &T) -> usize { #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] -#[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")] pub const unsafe fn align_of_val_raw(val: *const T) -> usize { // SAFETY: the caller must provide a valid raw pointer unsafe { intrinsics::min_align_of_val(val) } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index ec4b42b966b3..e0b1c21e1ecb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -13,7 +13,6 @@ #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(clone_to_uninit)] -#![feature(const_align_of_val_raw)] #![feature(const_black_box)] #![feature(const_eval_select)] #![feature(const_nonnull_new)] diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs index 4df3a793b4c3..598904d3c445 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -1,6 +1,5 @@ #![feature(extern_types)] #![feature(core_intrinsics)] -#![feature(const_size_of_val, const_align_of_val)] use std::intrinsics::{min_align_of_val, size_of_val}; diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index ad2de0f4d312..4c0252123a4d 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -1,11 +1,11 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31 + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout error[E0080]: evaluation of constant value failed - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32 + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:32 | LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout diff --git a/tests/ui/consts/const-size_of_val-align_of_val.rs b/tests/ui/consts/const-size_of_val-align_of_val.rs index ee9dfca0170b..d4b5a9035179 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val.rs @@ -1,7 +1,6 @@ //@ run-pass -#![feature(const_size_of_val, const_align_of_val)] -#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)] +#![feature(layout_for_ptr)] use std::{mem, ptr}; From 277e049d918226981f86be50d10dde25282b022f Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 28 Nov 2024 22:04:03 -0800 Subject: [PATCH 307/330] Move `Const::{from_anon_const,try_from_lit}` to hir_ty_lowering These operations are much more about lowering the HIR than about `Const`s themselves. They fit better in hir_ty_lowering with `lower_const_arg` (formerly `Const::from_const_arg`) and the rest. To accomplish this, `const_evaluatable_predicates_of` had to be changed to not use `from_anon_const` anymore. Instead of visiting the HIR and lowering anon consts on the fly, it now visits the `rustc_middle::ty` data structures instead and directly looks for `UnevaluatedConst`s. This approach was proposed in: https://github.com/rust-lang/rust/pull/131081#discussion_r1821189257 --- .../rustc_hir_analysis/src/check/wfcheck.rs | 21 ++-- .../rustc_hir_analysis/src/collect/dump.rs | 11 ++- .../src/collect/predicates_of.rs | 96 +++++++++++-------- .../src/hir_ty_lowering/mod.rs | 88 ++++++++++++++++- compiler/rustc_middle/src/ty/consts.rs | 84 +--------------- tests/crashes/121429.rs | 13 +-- tests/ui/attributes/dump_def_parents.rs | 5 +- tests/ui/attributes/dump_def_parents.stderr | 79 ++++++++++++--- .../issues/cg-in-dyn-issue-128176.rs} | 6 +- .../const-generics/issues/issue-83765.stderr | 8 +- 10 files changed, 244 insertions(+), 167 deletions(-) rename tests/{crashes/128176.rs => ui/const-generics/issues/cg-in-dyn-issue-128176.rs} (71%) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8fa797db2466..ed3ae1e12b92 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -13,6 +13,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_macros::LintDiagnostic; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::query::Providers; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -1170,19 +1171,13 @@ fn check_type_defn<'tcx>( // Explicit `enum` discriminant values must const-evaluate successfully. if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr { - let cause = traits::ObligationCause::new( - tcx.def_span(discr_def_id), - wfcx.body_def_id, - ObligationCauseCode::Misc, - ); - wfcx.register_obligation(Obligation::new( - tcx, - cause, - wfcx.param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable( - ty::Const::from_anon_const(tcx, discr_def_id.expect_local()), - ))), - )); + match tcx.const_eval_poly(discr_def_id) { + Ok(_) => {} + Err(ErrorHandled::Reported(..)) => {} + Err(ErrorHandled::TooGeneric(sp)) => { + span_bug!(sp, "enum variant discr was too generic to eval") + } + } } } diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 8648a7d1e322..f1022d957531 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -1,6 +1,6 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::intravisit; -use rustc_middle::hir::nested_filter::OnlyBodies; +use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::sym; @@ -42,7 +42,8 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { } pub(crate) fn def_parents(tcx: TyCtxt<'_>) { - for did in tcx.hir().body_owners() { + for iid in tcx.hir().items() { + let did = iid.owner_id.def_id; if tcx.has_attr(did, sym::rustc_dump_def_parents) { struct AnonConstFinder<'tcx> { tcx: TyCtxt<'tcx>, @@ -50,7 +51,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { } impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> { - type NestedFilter = OnlyBodies; + type NestedFilter = nested_filter::All; fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() @@ -62,11 +63,11 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) { } } - // Look for any anon consts inside of this body owner as there is no way to apply + // Look for any anon consts inside of this item as there is no way to apply // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible // to see what its def parent is. let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] }; - intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value); + intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid)); for did in [did].into_iter().chain(anon_ct_finder.anon_consts) { let span = tcx.def_span(did); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index bfee5d33598a..ca2597e79fd1 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,12 +1,13 @@ use std::assert_matches::assert_matches; -use hir::{HirId, Node}; +use hir::Node; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{ + self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, +}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span}; @@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } if tcx.features().generic_const_exprs() { - predicates.extend(const_evaluatable_predicates_of(tcx, def_id)); + predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates)); } let mut predicates: Vec<_> = predicates.into_iter().collect(); @@ -369,32 +370,48 @@ fn compute_bidirectional_outlives_predicates<'tcx>( } } -fn const_evaluatable_predicates_of( - tcx: TyCtxt<'_>, +#[instrument(level = "debug", skip(tcx, predicates), ret)] +fn const_evaluatable_predicates_of<'tcx>( + tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> FxIndexSet<(ty::Clause<'_>, Span)> { + predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>, +) -> FxIndexSet<(ty::Clause<'tcx>, Span)> { struct ConstCollector<'tcx> { tcx: TyCtxt<'tcx>, preds: FxIndexSet<(ty::Clause<'tcx>, Span)>, } - impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { - fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { - let ct = ty::Const::from_anon_const(self.tcx, c.def_id); - if let ty::ConstKind::Unevaluated(_) = ct.kind() { - let span = self.tcx.def_span(c.def_id); - self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span)); - } - } + fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool { + let hir_id = tcx.local_def_id_to_hir_id(def); + let (_, parent_node) = tcx + .hir() + .parent_iter(hir_id) + .skip_while(|(_, n)| matches!(n, Node::ConstArg(..))) + .next() + .unwrap(); + matches!( + parent_node, + Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. }) + ) + } - fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) { - // Do not look into const param defaults, - // these get checked when they are actually instantiated. - // - // We do not want the following to error: - // - // struct Foo; - // struct Bar(Foo); + impl<'tcx> TypeVisitor> for ConstCollector<'tcx> { + fn visit_const(&mut self, c: ty::Const<'tcx>) { + if let ty::ConstKind::Unevaluated(uv) = c.kind() { + if is_const_param_default(self.tcx, uv.def.expect_local()) { + // Do not look into const param defaults, + // these get checked when they are actually instantiated. + // + // We do not want the following to error: + // + // struct Foo; + // struct Bar(Foo); + return; + } + + let span = self.tcx.def_span(uv.def); + self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span)); + } } } @@ -402,29 +419,32 @@ fn const_evaluatable_predicates_of( let node = tcx.hir_node(hir_id); let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; + + for (clause, _sp) in predicates { + clause.visit_with(&mut collector); + } + if let hir::Node::Item(item) = node - && let hir::ItemKind::Impl(impl_) = item.kind + && let hir::ItemKind::Impl(_) = item.kind { - if let Some(of_trait) = &impl_.of_trait { - debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); - collector.visit_trait_ref(of_trait); + if let Some(of_trait) = tcx.impl_trait_ref(def_id) { + debug!("visit impl trait_ref"); + of_trait.instantiate_identity().visit_with(&mut collector); } - debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); - collector.visit_ty(impl_.self_ty); + debug!("visit self_ty"); + let self_ty = tcx.type_of(def_id); + self_ty.instantiate_identity().visit_with(&mut collector); } - if let Some(generics) = node.generics() { - debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id); - collector.visit_generics(generics); + if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) { + debug!("visit fn sig"); + let fn_sig = tcx.fn_sig(def_id); + let fn_sig = fn_sig.instantiate_identity(); + debug!(?fn_sig); + fn_sig.visit_with(&mut collector); } - if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) { - debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id); - collector.visit_fn_decl(fn_sig.decl); - } - debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds); - collector.preds } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7b8e95f3434e..cb4209116ac6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2089,7 +2089,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qpath.span(), format!("Const::lower_const_arg: invalid qpath {qpath:?}"), ), - hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id), + hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id), hir::ConstArgKind::Infer(span) => self.ct_infer(None, span), } } @@ -2177,6 +2177,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + /// Literals and const generic parameters are eagerly converted to a constant, everything else + /// becomes `Unevaluated`. + #[instrument(skip(self), level = "debug")] + fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> { + let tcx = self.tcx(); + + let body_id = match tcx.hir_node_by_def_id(def) { + hir::Node::AnonConst(ac) => ac.body, + node => span_bug!( + tcx.def_span(def.to_def_id()), + "from_anon_const can only process anonymous constants, not {node:?}" + ), + }; + + let expr = &tcx.hir().body(body_id).value; + debug!(?expr); + + let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); + + match self.try_lower_anon_const_lit(ty, expr) { + Some(v) => v, + None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { + def: def.to_def_id(), + args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()), + }), + } + } + + #[instrument(skip(self), level = "debug")] + fn try_lower_anon_const_lit( + &self, + ty: Ty<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + ) -> Option> { + let tcx = self.tcx(); + + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, + }; + + if let hir::ExprKind::Path(hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + )) = expr.kind + { + span_bug!( + expr.span, + "try_lower_anon_const_lit: received const param which shouldn't be possible" + ); + }; + + let lit_input = match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), + _ => None, + }, + _ => None, + }; + + if let Some(lit_input) = lit_input { + // If an error occurred, ignore that it's a literal and leave reporting the error up to + // mir. + match tcx.at(expr.span).lit_to_const(lit_input) { + Ok(c) => return Some(c), + Err(_) if lit_input.ty.has_aliases() => { + // allow the `ty` to be an alias type, though we cannot handle it here + return None; + } + Err(e) => { + tcx.dcx().span_delayed_bug( + expr.span, + format!("try_lower_anon_const_lit: couldn't lit_to_const {e:?}"), + ); + } + } + } + + None + } + fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index d27205e26abb..310552764224 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,15 +2,11 @@ use std::borrow::Cow; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LocalDefId; -use rustc_hir::{self as hir}; use rustc_macros::HashStable; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; -use tracing::{debug, instrument}; -use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt}; +use crate::mir::interpret::Scalar; +use crate::ty::{self, Ty, TyCtxt}; mod int; mod kind; @@ -181,82 +177,6 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { } impl<'tcx> Const<'tcx> { - // FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg - /// Literals and const generic parameters are eagerly converted to a constant, everything else - /// becomes `Unevaluated`. - #[instrument(skip(tcx), level = "debug")] - pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self { - let body_id = match tcx.hir_node_by_def_id(def) { - hir::Node::AnonConst(ac) => ac.body, - node => span_bug!( - tcx.def_span(def.to_def_id()), - "from_anon_const can only process anonymous constants, not {node:?}" - ), - }; - - let expr = &tcx.hir().body(body_id).value; - debug!(?expr); - - let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - - match Self::try_from_lit(tcx, ty, expr) { - Some(v) => v, - None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { - def: def.to_def_id(), - args: GenericArgs::identity_for_item(tcx, def.to_def_id()), - }), - } - } - - #[instrument(skip(tcx), level = "debug")] - fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option { - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - - if let hir::ExprKind::Path(hir::QPath::Resolved( - _, - &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, - )) = expr.kind - { - span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible"); - }; - - let lit_input = match expr.kind { - hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { - hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), - _ => None, - }, - _ => None, - }; - - if let Some(lit_input) = lit_input { - // If an error occurred, ignore that it's a literal and leave reporting the error up to - // mir. - match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return Some(c), - Err(_) if lit_input.ty.has_aliases() => { - // allow the `ty` to be an alias type, though we cannot handle it here - return None; - } - Err(e) => { - tcx.dcx().span_delayed_bug( - expr.span, - format!("Const::try_from_lit: couldn't lit_to_const {e:?}"), - ); - } - } - } - - None - } - /// Creates a constant with the given integer value and interns it. #[inline] pub fn from_bits( diff --git a/tests/crashes/121429.rs b/tests/crashes/121429.rs index 09bd343e0ba9..e407754db5cf 100644 --- a/tests/crashes/121429.rs +++ b/tests/crashes/121429.rs @@ -1,13 +1,10 @@ //@ known-bug: #121429 + #![feature(generic_const_exprs)] - -pub trait True {} - -impl PartialEq> for FixedI8 where - If<{}>: True -{ -} -#![feature(generic_const_exprs)] + +struct FixedI8; +const FRAC_LHS: usize = 0; +const FRAC_RHS: usize = 1; pub trait True {} diff --git a/tests/ui/attributes/dump_def_parents.rs b/tests/ui/attributes/dump_def_parents.rs index de0c88bb6c39..04a725f6c144 100644 --- a/tests/ui/attributes/dump_def_parents.rs +++ b/tests/ui/attributes/dump_def_parents.rs @@ -3,16 +3,17 @@ fn bar() { fn foo() { + #[rustc_dump_def_parents] fn baz() { - #[rustc_dump_def_parents] + //~^ ERROR: rustc_dump_def_parents: DefId || { - //~^ ERROR: rustc_dump_def_parents: DefId qux::< { //~^ ERROR: rustc_dump_def_parents: DefId fn inhibits_dump() { qux::< { + //~^ ERROR: rustc_dump_def_parents: DefId "hi"; 1 }, diff --git a/tests/ui/attributes/dump_def_parents.stderr b/tests/ui/attributes/dump_def_parents.stderr index b2cc32d09b07..a928e8e33a4f 100644 --- a/tests/ui/attributes/dump_def_parents.stderr +++ b/tests/ui/attributes/dump_def_parents.stderr @@ -1,14 +1,9 @@ error: rustc_dump_def_parents: DefId(..) - --> $DIR/dump_def_parents.rs:8:13 - | -LL | || { - | ^^ - | -note: DefId(..) - --> $DIR/dump_def_parents.rs:6:9 + --> $DIR/dump_def_parents.rs:7:9 | LL | fn baz() { | ^^^^^^^^ + | note: DefId(..) --> $DIR/dump_def_parents.rs:5:5 | @@ -44,12 +39,12 @@ LL | | }, | |_____________________^ | note: DefId(..) - --> $DIR/dump_def_parents.rs:8:13 + --> $DIR/dump_def_parents.rs:9:13 | LL | || { | ^^ note: DefId(..) - --> $DIR/dump_def_parents.rs:6:9 + --> $DIR/dump_def_parents.rs:7:9 | LL | fn baz() { | ^^^^^^^^ @@ -76,7 +71,65 @@ LL | | fn main() {} | |____________^ error: rustc_dump_def_parents: DefId(..) - --> $DIR/dump_def_parents.rs:22:31 + --> $DIR/dump_def_parents.rs:15:33 + | +LL | / ... { +LL | | ... +LL | | ... "hi"; +LL | | ... 1 +LL | | ... }, + | |_______________________^ + | +note: DefId(..) + --> $DIR/dump_def_parents.rs:13:25 + | +LL | fn inhibits_dump() { + | ^^^^^^^^^^^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:11:21 + | +LL | / { +LL | | +LL | | fn inhibits_dump() { +LL | | qux::< +... | +LL | | 1 +LL | | }, + | |_____________________^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:9:13 + | +LL | || { + | ^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:7:9 + | +LL | fn baz() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:5:5 + | +LL | fn foo() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:4:1 + | +LL | fn bar() { + | ^^^^^^^^ +note: DefId(..) + --> $DIR/dump_def_parents.rs:2:1 + | +LL | / #![feature(rustc_attrs)] +LL | | +LL | | fn bar() { +LL | | fn foo() { +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: rustc_dump_def_parents: DefId(..) + --> $DIR/dump_def_parents.rs:23:31 | LL | qux::<{ 1 + 1 }>(); | ^^^^^^^^^ @@ -93,12 +146,12 @@ LL | | 1 LL | | }, | |_____________________^ note: DefId(..) - --> $DIR/dump_def_parents.rs:8:13 + --> $DIR/dump_def_parents.rs:9:13 | LL | || { | ^^ note: DefId(..) - --> $DIR/dump_def_parents.rs:6:9 + --> $DIR/dump_def_parents.rs:7:9 | LL | fn baz() { | ^^^^^^^^ @@ -124,5 +177,5 @@ LL | | LL | | fn main() {} | |____________^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/crashes/128176.rs b/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs similarity index 71% rename from tests/crashes/128176.rs rename to tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs index 970ad9ff2cd5..d163238c6d53 100644 --- a/tests/crashes/128176.rs +++ b/tests/ui/const-generics/issues/cg-in-dyn-issue-128176.rs @@ -1,7 +1,11 @@ -//@ known-bug: rust-lang/rust#128176 +//@ check-pass + +// Regression test for #128176. #![feature(generic_const_exprs)] #![feature(dyn_compatible_for_dispatch)] +#![allow(incomplete_features)] + trait X { type Y; } diff --git a/tests/ui/const-generics/issues/issue-83765.stderr b/tests/ui/const-generics/issues/issue-83765.stderr index cce627499125..6b62012c14fc 100644 --- a/tests/ui/const-generics/issues/issue-83765.stderr +++ b/tests/ui/const-generics/issues/issue-83765.stderr @@ -10,11 +10,11 @@ note: ...which requires computing candidate for `::DIM, DIM> as TensorDimension>::DIM`, completing the cycle -note: cycle used when computing candidate for ` as TensorDimension>` - --> $DIR/issue-83765.rs:4:1 +note: cycle used when checking assoc item `::size` is compatible with trait definition + --> $DIR/issue-83765.rs:51:5 | -LL | trait TensorDimension { - | ^^^^^^^^^^^^^^^^^^^^^ +LL | fn size(&self) -> [usize; DIM] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0391]: cycle detected when resolving instance `::DIM, DIM> as TensorDimension>::DIM` From dcf332bd9ddd6c81c54ce6422243df9a96cef44f Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 29 Nov 2024 12:14:07 -0800 Subject: [PATCH 308/330] Fix broken intra-doc link --- compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9d60759ae487..0404e38a2930 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -703,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// It might actually be possible that we can already support early-bound generic params /// in such types if we just lifted some more checks in other places, too, for example -/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should +/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should /// probably gate this behind another feature flag. /// /// [^1]: . From e91fc1bc0c05da68d218a01d550c6d12297f5703 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Nov 2024 20:22:08 +0000 Subject: [PATCH 309/330] Reimplement specialization for const traits --- .../src/traits/specialize/mod.rs | 130 +++++++++++++++--- ...t-bound-non-const-specialized-bound.stderr | 26 +++- .../const-traits/specializing-constness.rs | 3 +- .../specializing-constness.stderr | 8 +- 4 files changed, 142 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a9cd705465e3..91a0599a3be8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -15,6 +15,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_infer::traits::Obligation; use rustc_middle::bug; use rustc_middle::query::LocalCrate; use rustc_middle::ty::print::PrintTraitRefExt as _; @@ -230,15 +231,18 @@ pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool /// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies /// to. #[instrument(skip(tcx), level = "debug")] -pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool { +pub(super) fn specializes( + tcx: TyCtxt<'_>, + (specializing_impl_def_id, parent_impl_def_id): (DefId, DefId), +) -> bool { // We check that the specializing impl comes from a crate that has specialization enabled, // or if the specializing impl is marked with `allow_internal_unstable`. // // We don't really care if the specialized impl (the parent) is in a crate that has // specialization enabled, since it's not being specialized, and it's already been checked // for coherence. - if !tcx.specialization_enabled_in(impl1_def_id.krate) { - let span = tcx.def_span(impl1_def_id); + if !tcx.specialization_enabled_in(specializing_impl_def_id.krate) { + let span = tcx.def_span(specializing_impl_def_id); if !span.allows_unstable(sym::specialization) && !span.allows_unstable(sym::min_specialization) { @@ -246,7 +250,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, } } - let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap(); + let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id).unwrap(); // We determine whether there's a subset relationship by: // @@ -261,27 +265,117 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // See RFC 1210 for more details and justification. // Currently we do not allow e.g., a negative impl to specialize a positive one - if impl1_trait_header.polarity != tcx.impl_polarity(impl2_def_id) { + if specializing_impl_trait_header.polarity != tcx.impl_polarity(parent_impl_def_id) { return false; } - // create a parameter environment corresponding to an identity instantiation of impl1, - // i.e. the most generic instantiation of impl1. - let param_env = tcx.param_env(impl1_def_id); + // create a parameter environment corresponding to an identity instantiation of the specializing impl, + // i.e. the most generic instantiation of the specializing impl. + let param_env = tcx.param_env(specializing_impl_def_id); - // Create an infcx, taking the predicates of impl1 as assumptions: + // Create an infcx, taking the predicates of the specializing impl as assumptions: let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - // Attempt to prove that impl2 applies, given all of the above. - fulfill_implication( - &infcx, + let specializing_impl_trait_ref = + specializing_impl_trait_header.trait_ref.instantiate_identity(); + let cause = &ObligationCause::dummy(); + debug!( + "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)", + param_env, specializing_impl_trait_ref, parent_impl_def_id + ); + + // Attempt to prove that the parent impl applies, given all of the above. + + let ocx = ObligationCtxt::new(&infcx); + let specializing_impl_trait_ref = ocx.normalize(cause, param_env, specializing_impl_trait_ref); + + if !ocx.select_all_or_error().is_empty() { + infcx.dcx().span_delayed_bug( + infcx.tcx.def_span(specializing_impl_def_id), + format!("failed to fully normalize {specializing_impl_trait_ref}"), + ); + return false; + } + + let parent_args = infcx.fresh_args_for_item(DUMMY_SP, parent_impl_def_id); + let parent_impl_trait_ref = ocx.normalize( + cause, param_env, - impl1_trait_header.trait_ref.instantiate_identity(), - impl1_def_id, - impl2_def_id, - &ObligationCause::dummy(), - ) - .is_ok() + infcx + .tcx + .impl_trait_ref(parent_impl_def_id) + .expect("expected source impl to be a trait impl") + .instantiate(infcx.tcx, parent_args), + ); + + // do the impls unify? If not, no specialization. + let Ok(()) = ocx.eq(cause, param_env, specializing_impl_trait_ref, parent_impl_trait_ref) + else { + return false; + }; + + // Now check that the source trait ref satisfies all the where clauses of the target impl. + // This is not just for correctness; we also need this to constrain any params that may + // only be referenced via projection predicates. + let predicates = ocx.normalize( + cause, + param_env, + infcx.tcx.predicates_of(parent_impl_def_id).instantiate(infcx.tcx, parent_args), + ); + let obligations = predicates_for_generics(|_, _| cause.clone(), param_env, predicates); + ocx.register_obligations(obligations); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + // no dice! + debug!( + "fulfill_implication: for impls on {:?} and {:?}, \ + could not fulfill: {:?} given {:?}", + specializing_impl_trait_ref, + parent_impl_trait_ref, + errors, + param_env.caller_bounds() + ); + return false; + } + + // If the parent impl is const, then the specializing impl must be const. + if tcx.is_conditionally_const(parent_impl_def_id) { + let const_conditions = ocx.normalize( + cause, + param_env, + infcx.tcx.const_conditions(parent_impl_def_id).instantiate(infcx.tcx, parent_args), + ); + ocx.register_obligations(const_conditions.into_iter().map(|(trait_ref, _)| { + Obligation::new( + infcx.tcx, + cause.clone(), + param_env, + trait_ref.to_host_effect_clause(infcx.tcx, ty::BoundConstness::Maybe), + ) + })); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + // no dice! + debug!( + "fulfill_implication: for impls on {:?} and {:?}, \ + could not fulfill: {:?} given {:?}", + specializing_impl_trait_ref, + parent_impl_trait_ref, + errors, + param_env.caller_bounds() + ); + return false; + } + } + + debug!( + "fulfill_implication: an impl for {:?} specializes {:?}", + specializing_impl_trait_ref, parent_impl_trait_ref + ); + + true } /// Query provider for `specialization_graph_of`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr index bffc60c65fce..9166b8ca5d22 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -1,11 +1,31 @@ -error: cannot specialize on const impl with non-const impl +error[E0119]: conflicting implementations of trait `Bar` --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1 | +LL | / impl const Bar for T +LL | | where +LL | | T: ~const Foo, + | |__________________- first implementation here +... LL | / impl Bar for T LL | | where LL | | T: Foo, //FIXME ~ ERROR missing `~const` qualifier LL | | T: Specialize, - | |__________________^ + | |__________________^ conflicting implementation -error: aborting due to 1 previous error +error[E0119]: conflicting implementations of trait `Baz` + --> $DIR/const-default-bound-non-const-specialized-bound.rs:48:1 + | +LL | / impl const Baz for T +LL | | where +LL | | T: ~const Foo, + | |__________________- first implementation here +... +LL | / impl const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz` +LL | | where +LL | | T: Foo, +LL | | T: Specialize, + | |__________________^ conflicting implementation +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs index 632121924a63..94b6da7124d2 100644 --- a/tests/ui/traits/const-traits/specializing-constness.rs +++ b/tests/ui/traits/const-traits/specializing-constness.rs @@ -21,8 +21,7 @@ impl const A for T { } impl A for T { -//~^ ERROR: cannot specialize -//FIXME(const_trait_impl) ~| ERROR: missing `~const` qualifier + //~^ ERROR conflicting implementations of trait `A` fn a() -> u32 { 3 } diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr index 21e21c2cb71a..2ca70b53e4e2 100644 --- a/tests/ui/traits/const-traits/specializing-constness.stderr +++ b/tests/ui/traits/const-traits/specializing-constness.stderr @@ -1,8 +1,12 @@ -error: cannot specialize on const impl with non-const impl +error[E0119]: conflicting implementations of trait `A` --> $DIR/specializing-constness.rs:23:1 | +LL | impl const A for T { + | ---------------------------------- first implementation here +... LL | impl A for T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0119`. From 9bda88bb58c1c6fa175166a7d5272f483eac38c8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 01:00:11 +0000 Subject: [PATCH 310/330] Fix const specialization --- compiler/rustc_hir_analysis/messages.ftl | 2 - compiler/rustc_hir_analysis/src/errors.rs | 7 ---- .../src/impl_wf_check/min_specialization.rs | 26 ------------- .../src/traits/specialize/mod.rs | 22 ++++++++--- ...verlap-const-with-nonconst.min_spec.stderr | 14 +++++++ .../overlap-const-with-nonconst.rs | 38 +++++++++++++++++++ .../overlap-const-with-nonconst.spec.stderr | 24 ++++++++++++ ...non-const-specialized-impl.min_spec.stderr | 12 ++++++ ...default-impl-non-const-specialized-impl.rs | 8 +++- ...mpl-non-const-specialized-impl.spec.stderr | 22 +++++++++++ ...ult-impl-non-const-specialized-impl.stderr | 8 ---- 11 files changed, 133 insertions(+), 50 deletions(-) create mode 100644 tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr create mode 100644 tests/ui/traits/const-traits/overlap-const-with-nonconst.rs create mode 100644 tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr create mode 100644 tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr create mode 100644 tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr delete mode 100644 tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index cb658111392c..070d63b48b7b 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -113,8 +113,6 @@ hir_analysis_const_param_ty_impl_on_unsized = the trait `ConstParamTy` may not be implemented for this type .label = type is not `Sized` -hir_analysis_const_specialize = cannot specialize on const impl with non-const impl - hir_analysis_copy_impl_on_non_adt = the trait `Copy` cannot be implemented for this type .label = type is not a structure or enumeration diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 51115b11e86b..4142dcff226b 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1079,13 +1079,6 @@ pub(crate) struct EmptySpecialization { pub base_impl_span: Span, } -#[derive(Diagnostic)] -#[diag(hir_analysis_const_specialize)] -pub(crate) struct ConstSpecialize { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_static_specialize)] pub(crate) struct StaticSpecialize { diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 246643d80747..ee55e1bc21a6 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -66,7 +66,6 @@ //! on traits with methods can. use rustc_data_structures::fx::FxHashSet; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::outlives::env::OutlivesEnvironment; @@ -134,7 +133,6 @@ fn check_always_applicable( unconstrained_parent_impl_args(tcx, impl2_def_id, impl2_args) }; - res = res.and(check_constness(tcx, impl1_def_id, impl2_node, span)); res = res.and(check_static_lifetimes(tcx, &parent_args, span)); res = res.and(check_duplicate_params(tcx, impl1_args, parent_args, span)); res = res.and(check_predicates(tcx, impl1_def_id, impl1_args, impl2_node, impl2_args, span)); @@ -157,30 +155,6 @@ fn check_has_items( Ok(()) } -/// Check that the specializing impl `impl1` is at least as const as the base -/// impl `impl2` -fn check_constness( - tcx: TyCtxt<'_>, - impl1_def_id: LocalDefId, - impl2_node: Node, - span: Span, -) -> Result<(), ErrorGuaranteed> { - if impl2_node.is_from_trait() { - // This isn't a specialization - return Ok(()); - } - - let impl1_constness = tcx.constness(impl1_def_id.to_def_id()); - let impl2_constness = tcx.constness(impl2_node.def_id()); - - if let hir::Constness::Const = impl2_constness { - if let hir::Constness::NotConst = impl1_constness { - return Err(tcx.dcx().emit_err(errors::ConstSpecialize { span })); - } - } - Ok(()) -} - /// Given a specializing impl `impl1`, and the base impl `impl2`, returns two /// generic parameters `(S1, S2)` that equate their trait references. /// The returned types are expressed in terms of the generics of `impl1`. diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 91a0599a3be8..1430cfae51f7 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -225,11 +225,17 @@ pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool tcx.features().specialization() || tcx.features().min_specialization() } -/// Is `impl1` a specialization of `impl2`? +/// Is `specializing_impl_def_id` a specialization of `parent_impl_def_id`? /// -/// Specialization is determined by the sets of types to which the impls apply; -/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies -/// to. +/// For every type that could apply to `specializing_impl_def_id`, we prove that +/// the `parent_impl_def_id` also applies (i.e. it has a valid impl header and +/// its where-clauses hold). +/// +/// For the purposes of const traits, we also check that the specializing +/// impl is not more restrictive than the parent impl. That is, if the +/// `parent_impl_def_id` is a const impl (conditionally based off of some `~const` +/// bounds), then `specializing_impl_def_id` must also be const for the same +/// set of types. #[instrument(skip(tcx), level = "debug")] pub(super) fn specializes( tcx: TyCtxt<'_>, @@ -339,8 +345,14 @@ pub(super) fn specializes( return false; } - // If the parent impl is const, then the specializing impl must be const. + // If the parent impl is const, then the specializing impl must be const, + // and it must not be *more restrictive* than the parent impl (that is, + // it cannot be const in fewer cases than the parent impl). if tcx.is_conditionally_const(parent_impl_def_id) { + if !tcx.is_conditionally_const(specializing_impl_def_id) { + return false; + } + let const_conditions = ocx.normalize( cause, param_env, diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr new file mode 100644 index 000000000000..bd822970ad1e --- /dev/null +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `(_,)` + --> $DIR/overlap-const-with-nonconst.rs:23:1 + | +LL | / impl const Foo for T +LL | | where +LL | | T: ~const Bar, + | |__________________- first implementation here +... +LL | impl Foo for (T,) { + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs new file mode 100644 index 000000000000..eb66d03faa63 --- /dev/null +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs @@ -0,0 +1,38 @@ +//@ revisions: spec min_spec + +#![feature(const_trait_impl)] +#![cfg_attr(spec, feature(specialization))] +//[spec]~^ WARN the feature `specialization` is incomplete +#![cfg_attr(min_spec, feature(min_specialization))] + +#[const_trait] +trait Bar {} +impl const Bar for T {} + +#[const_trait] +trait Foo { + fn method(&self); +} +impl const Foo for T +where + T: ~const Bar, +{ + default fn method(&self) {} +} +// specializing impl: +impl Foo for (T,) { +//~^ ERROR conflicting implementations + fn method(&self) { + println!("hi"); + } +} + +const fn dispatch(t: T) { + t.method(); +} + +fn main() { + const { + dispatch(((),)); + } +} diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr new file mode 100644 index 000000000000..cbdcb45f6beb --- /dev/null +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr @@ -0,0 +1,24 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/overlap-const-with-nonconst.rs:4:27 + | +LL | #![cfg_attr(spec, feature(specialization))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `(_,)` + --> $DIR/overlap-const-with-nonconst.rs:23:1 + | +LL | / impl const Foo for T +LL | | where +LL | | T: ~const Bar, + | |__________________- first implementation here +... +LL | impl Foo for (T,) { + | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr new file mode 100644 index 000000000000..38fc5ddfbef5 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` + --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1 + | +LL | impl const Value for T { + | ------------------------- first implementation here +... +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs index a3bb9b3f93ed..acf0a967a884 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs @@ -1,7 +1,10 @@ // Tests that specializing trait impls must be at least as const as the default impl. +//@ revisions: spec min_spec #![feature(const_trait_impl)] -#![feature(min_specialization)] +#![cfg_attr(spec, feature(specialization))] +//[spec]~^ WARN the feature `specialization` is incomplete +#![cfg_attr(min_spec, feature(min_specialization))] #[const_trait] trait Value { @@ -16,7 +19,8 @@ impl const Value for T { struct FortyTwo; -impl Value for FortyTwo { //~ ERROR cannot specialize on const impl with non-const impl +impl Value for FortyTwo { + //~^ ERROR conflicting implementations fn value() -> u32 { println!("You can't do that (constly)"); 42 diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr new file mode 100644 index 000000000000..b59c42f51893 --- /dev/null +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr @@ -0,0 +1,22 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-default-impl-non-const-specialized-impl.rs:5:27 + | +LL | #![cfg_attr(spec, feature(specialization))] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` + --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1 + | +LL | impl const Value for T { + | ------------------------- first implementation here +... +LL | impl Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr deleted file mode 100644 index e356621ba47e..000000000000 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: cannot specialize on const impl with non-const impl - --> $DIR/const-default-impl-non-const-specialized-impl.rs:19:1 - | -LL | impl Value for FortyTwo { - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - From abfa5c1dca4c549f0e196a872579434ff23a24bb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 27 Nov 2024 02:37:59 +0000 Subject: [PATCH 311/330] Deeply normalize when computing implied outlives bounds --- .../src/traits/normalize.rs | 2 +- .../query/type_op/implied_outlives_bounds.rs | 7 +-- .../normalize-in-implied_outlives_bounds.rs | 46 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index e99c5eacbd8e..2891df3ed2dd 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -66,7 +66,7 @@ impl<'tcx> At<'_, 'tcx> { let value = self .normalize(value) .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); - let errors = fulfill_cx.select_where_possible(self.infcx); + let errors = fulfill_cx.select_all_or_error(self.infcx); let value = self.infcx.resolve_vars_if_possible(value); if errors.is_empty() { Ok(value) } else { Err(errors) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index c6e41e57f0ce..224a72714727 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -59,12 +59,13 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Result>, NoSolution> { - let normalize_op = |ty| { - let ty = ocx.normalize(&ObligationCause::dummy(), param_env, ty); + let normalize_op = |ty| -> Result<_, NoSolution> { + let ty = ocx + .deeply_normalize(&ObligationCause::dummy(), param_env, ty) + .map_err(|_| NoSolution)?; if !ocx.select_all_or_error().is_empty() { return Err(NoSolution); } - let ty = ocx.infcx.resolve_vars_if_possible(ty); let ty = OpportunisticRegionResolver::new(&ocx.infcx).fold_ty(ty); Ok(ty) }; diff --git a/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs new file mode 100644 index 000000000000..1dca19d28e9a --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-in-implied_outlives_bounds.rs @@ -0,0 +1,46 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Minimized example from `rustc_type_ir` that demonstrates a missing deep normalization +// in the new solver when computing the implies outlives bounds of an impl. + +use std::marker::PhantomData; +use std::ops::Deref; + +pub struct SearchGraph::Cx> { + d: PhantomData, + x: PhantomData, +} + +pub trait Delegate { + type Cx; +} + +struct SearchGraphDelegate { + _marker: PhantomData, +} + +impl Delegate for SearchGraphDelegate +where + D: SolverDelegate, +{ + type Cx = D::Interner; +} + +pub trait SolverDelegate { + type Interner; +} + +struct EvalCtxt<'a, D, I> +where + D: SolverDelegate, +{ + search_graph: &'a SearchGraph>, +} + +impl<'a, D, I> EvalCtxt<'a, D, ::Interner> +where + D: SolverDelegate +{} + +fn main() {} From 398fd901d5f8afa982eeb0f9318d9d0e4e791f44 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 27 Nov 2024 21:27:37 +0000 Subject: [PATCH 312/330] Assert that obligations are empty before deeply normalizing --- .../src/obligation_forest/mod.rs | 4 ++++ compiler/rustc_hir_analysis/src/check/wfcheck.rs | 3 +-- compiler/rustc_infer/src/traits/engine.rs | 2 ++ compiler/rustc_trait_selection/src/solve/fulfill.rs | 4 ++++ .../rustc_trait_selection/src/traits/fulfill.rs | 4 ++++ .../rustc_trait_selection/src/traits/normalize.rs | 9 +++++++++ .../traits/query/type_op/implied_outlives_bounds.rs | 3 +++ .../ui/higher-ranked/structually-relate-aliases.rs | 1 - .../higher-ranked/structually-relate-aliases.stderr | 13 +------------ .../in-trait/alias-bounds-when-not-wf.stderr | 4 ++-- .../traits/next-solver/issue-118950-root-region.rs | 2 +- .../next-solver/issue-118950-root-region.stderr | 13 ++++++------- 12 files changed, 37 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 34a2464972a6..78d69a66edc8 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -415,6 +415,10 @@ impl ObligationForest { .collect() } + pub fn has_pending_obligations(&self) -> bool { + self.nodes.iter().any(|node| node.state.get() == NodeState::Pending) + } + fn insert_into_error_cache(&mut self, index: usize) { let node = &self.nodes[index]; self.error_cache diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8fa797db2466..680454039329 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -116,13 +116,12 @@ where } f(&mut wfcx)?; - let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; - let errors = wfcx.select_all_or_error(); if !errors.is_empty() { return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } + let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?; debug!(?assumed_wf_types); let infcx_compat = infcx.fork(); diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index ba1516655b0b..51282b900ed1 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -84,6 +84,8 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { self.collect_remaining_errors(infcx) } + fn has_pending_obligations(&self) -> bool; + fn pending_obligations(&self) -> PredicateObligations<'tcx>; /// Among all pending obligations, collect those are stalled on a inference variable which has diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 0f90c45d0320..2b2623a050ec 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -199,6 +199,10 @@ where errors } + fn has_pending_obligations(&self) -> bool { + !self.obligations.pending.is_empty() || !self.obligations.overflowed.is_empty() + } + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.obligations.clone_pending() } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 03e483f555d8..7529ee128f5e 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -213,6 +213,10 @@ where } } + fn has_pending_obligations(&self) -> bool { + self.predicates.has_pending_obligations() + } + fn pending_obligations(&self) -> PredicateObligations<'tcx> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 2891df3ed2dd..ad62b456ad46 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -7,6 +7,7 @@ use rustc_infer::traits::{ FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, }; use rustc_macros::extension; +use rustc_middle::span_bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, @@ -63,6 +64,14 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) } else { + if fulfill_cx.has_pending_obligations() { + let pending_obligations = fulfill_cx.pending_obligations(); + span_bug!( + pending_obligations[0].cause.span, + "deeply_normalize should not be called with pending obligations: \ + {pending_obligations:#?}" + ); + } let value = self .normalize(value) .into_value_registering_obligations(self.infcx, &mut *fulfill_cx); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 224a72714727..fe47e837dfb5 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -60,6 +60,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( ty: Ty<'tcx>, ) -> Result>, NoSolution> { let normalize_op = |ty| -> Result<_, NoSolution> { + // We must normalize the type so we can compute the right outlives components. + // for example, if we have some constrained param type like `T: Trait`, + // and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`. let ty = ocx .deeply_normalize(&ObligationCause::dummy(), param_env, ty) .map_err(|_| NoSolution)?; diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 73c2cd23d86e..1ed3767643a0 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -12,6 +12,5 @@ impl Overlap for T {} impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} //~^ ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied -//~| ERROR the trait bound `for<'a> T: ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index e9d91e45e217..cf3e4cc85b91 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -10,17 +10,6 @@ help: consider restricting type parameter `T` LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} | ++++++++++++++++++++ -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:17 - | -LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 79581066a3a3..1cfc2a6d9449 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -8,10 +8,10 @@ LL | #![feature(lazy_type_alias)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `usize: Foo` is not satisfied - --> $DIR/alias-bounds-when-not-wf.rs:16:13 + --> $DIR/alias-bounds-when-not-wf.rs:16:15 | LL | fn hello(_: W>) {} - | ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize` + | ^^^^^^^^ the trait `Foo` is not implemented for `usize` | help: this trait has no implementations, consider adding one --> $DIR/alias-bounds-when-not-wf.rs:6:1 diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index e1bd234a275a..8fe53d6773b9 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -18,6 +18,6 @@ impl Overlap for T {} impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} //~^ ERROR cannot find type `Missing` in this scope -//~| ERROR the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied +//~| ERROR the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not satisfied fn main() {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index f6545c6ebf9d..09162970d33d 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -26,17 +26,16 @@ LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. } -error[E0277]: the trait bound `for<'a> *const T: ToUnit<'a>` is not satisfied - --> $DIR/issue-118950-root-region.rs:19:17 +error[E0277]: the trait bound `T: Overlap fn(Assoc<'a, T>)>` is not satisfied + --> $DIR/issue-118950-root-region.rs:19:47 | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `*const T` + | ^ the trait `Overlap fn(Assoc<'a, T>)>` is not implemented for `T` | -help: this trait has no implementations, consider adding one - --> $DIR/issue-118950-root-region.rs:8:1 +help: consider further restricting type parameter `T` | -LL | trait ToUnit<'a> { - | ^^^^^^^^^^^^^^^^ +LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap, T: Overlap fn(Assoc<'a, T>)> {} + | ++++++++++++++++++++++++++++++++++++++ error: aborting due to 3 previous errors; 1 warning emitted From 0609b999681f9c807554bffe838288bda7efa3f1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 28 Nov 2024 00:58:05 +0000 Subject: [PATCH 313/330] Structurally resolve in probe_adt --- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 6 +++++- tests/crashes/132320.rs | 15 --------------- .../typeck/structurally-resolve-in-probe_adt.rs | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 16 deletions(-) delete mode 100644 tests/crashes/132320.rs create mode 100644 tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 3940d138deb0..aacdcf027b6e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -307,7 +307,11 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) if !ty.has_escaping_bound_vars() => { - self.normalize(span, ty).ty_adt_def() + if self.next_trait_solver() { + self.try_structurally_resolve_type(span, ty).ty_adt_def() + } else { + self.normalize(span, ty).ty_adt_def() + } } _ => None, } diff --git a/tests/crashes/132320.rs b/tests/crashes/132320.rs deleted file mode 100644 index 79181c3a2c52..000000000000 --- a/tests/crashes/132320.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #132320 -//@ compile-flags: -Znext-solver=globally - -trait Foo { - type Item; - fn foo(&mut self); -} - -impl Foo for () { - type Item = Option<()>; - - fn foo(&mut self) { - let _ = Self::Item::None; - } -} diff --git a/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs new file mode 100644 index 000000000000..23915808279a --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-probe_adt.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +type Foo = as Mirror>::Assoc; + +fn main() { + let x = Foo::::None; +} From ebb9a382a4205b343f616cca8bac113abe34aa3a Mon Sep 17 00:00:00 2001 From: The 8472 Date: Tue, 3 Dec 2024 00:53:55 +0100 Subject: [PATCH 314/330] document -Zrandomize-layout in the unstable book --- .../src/compiler-flags/randomize-layout.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/randomize-layout.md diff --git a/src/doc/unstable-book/src/compiler-flags/randomize-layout.md b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md new file mode 100644 index 000000000000..84c6712bc23a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/randomize-layout.md @@ -0,0 +1,23 @@ +# `randomize-layout` + +The tracking issue for this feature is: [#106764](https://github.com/rust-lang/rust/issues/106764). + +------------------------ + +The `-Zrandomize-layout` flag changes the layout algorithm for `repr(Rust)` types defined in the current crate from its normal +optimization goals to pseudorandomly rearranging fields within the degrees of freedom provided by the largely unspecified +default representation. This also affects type sizes and padding. +Downstream intantiations of generic types defined in a crate with randomization enabled will also be randomized. + +It can be used to find unsafe code that accidentally relies on unspecified behavior. + +Randomization is not guaranteed to use a different permutation for each compilation session. +`-Zlayout-seed=` can be used to supply additional entropy. + +Randomization only approximates the intended freedom of repr(Rust). Sometimes two distinct types may still consistently +result in the same layout due to limitations of the current implementation. Randomization may become +more aggressive over time as our coverage of the available degrees of freedoms improves. +Corollary: Randomization is not a safety oracle. Two struct layouts being observably the same under different layout seeds +on the current compiler version does not guarantee that future compiler versions won't give them distinct layouts. + +Randomization may also become less aggressive in the future if additional guarantees get added to the default layout. From 2807ba77a0b8c22d1326a6bfef87b28942fe9ab7 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 3 Dec 2024 00:00:48 +0000 Subject: [PATCH 315/330] Use correct `hir_id` for array const arg infers --- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 ++++++++---- .../generic_arg_infer/array-repeat-expr-lib.rs | 12 ++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7ffe4db6e45e..3a04a66cd144 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2013,7 +2013,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer() { let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); - self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind }) + self.arena + .alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) } else { feature_err( &self.tcx.sess, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 068a5d31a8e1..a34ea18f7169 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1389,10 +1389,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // `ConstArgKind::Path`. We never actually access this `DefId` // anywhere so we don't need to encode it for other crates. if def_kind == DefKind::AnonConst - && matches!( - tcx.hir_node_by_def_id(local_id), - hir::Node::ConstArg(hir::ConstArg { kind: hir::ConstArgKind::Path(..), .. }) - ) + && match tcx.hir_node_by_def_id(local_id) { + hir::Node::ConstArg(hir::ConstArg { kind, .. }) => match kind { + // Skip encoding defs for these as they should not have had a `DefId` created + hir::ConstArgKind::Path(..) | hir::ConstArgKind::Infer(..) => true, + hir::ConstArgKind::Anon(..) => false, + }, + _ => false, + } { continue; } diff --git a/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs new file mode 100644 index 000000000000..c1f725db126a --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/array-repeat-expr-lib.rs @@ -0,0 +1,12 @@ +//@ check-pass + +#![feature(generic_arg_infer)] +#![crate_type = "lib"] + +// Test that encoding the hallucinated `DefId` for the `_` const argument doesn't +// ICE (see #133468). This requires this to be a library crate. + +pub fn foo() { + let s: [u8; 10]; + s = [0; _]; +} From e9fbb6f27177d9e7579af064c18184114ed9cec9 Mon Sep 17 00:00:00 2001 From: Matt Weber <30441572+mweber15@users.noreply.github.com> Date: Mon, 2 Dec 2024 21:59:34 -0500 Subject: [PATCH 316/330] Fix tests when using MinGW --- tests/codegen/issues/issue-98678-async.rs | 2 +- tests/codegen/issues/issue-98678-closure-coroutine.rs | 2 +- tests/codegen/issues/issue-98678-enum.rs | 2 +- tests/codegen/issues/issue-98678-struct-union.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/codegen/issues/issue-98678-async.rs b/tests/codegen/issues/issue-98678-async.rs index df413537f015..75f5d82eee55 100644 --- a/tests/codegen/issues/issue-98678-async.rs +++ b/tests/codegen/issues/issue-98678-async.rs @@ -6,7 +6,7 @@ // ignore-tidy-linelength -// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-async.rs{{".*}}) +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-async.rs{{".*}}) // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-async.rs{{".*}}) // NONMSVC-DAG: !DISubprogram(name: "foo",{{.*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], diff --git a/tests/codegen/issues/issue-98678-closure-coroutine.rs b/tests/codegen/issues/issue-98678-closure-coroutine.rs index 0ae94700c5d5..0730e56bf315 100644 --- a/tests/codegen/issues/issue-98678-closure-coroutine.rs +++ b/tests/codegen/issues/issue-98678-closure-coroutine.rs @@ -6,7 +6,7 @@ // ignore-tidy-linelength -// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-closure-coroutine.rs{{".*}}) +// NONMSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-closure-coroutine.rs{{".*}}) // MSVC-DAG: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-closure-coroutine.rs{{".*}}) pub fn foo() { diff --git a/tests/codegen/issues/issue-98678-enum.rs b/tests/codegen/issues/issue-98678-enum.rs index aec18c2132ca..62c6cded8664 100644 --- a/tests/codegen/issues/issue-98678-enum.rs +++ b/tests/codegen/issues/issue-98678-enum.rs @@ -4,7 +4,7 @@ // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-enum.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-enum.rs{{".*}}) // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-enum.rs{{".*}}) // NONMSVC: !DICompositeType({{.*"}}SingleCase{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 2]], diff --git a/tests/codegen/issues/issue-98678-struct-union.rs b/tests/codegen/issues/issue-98678-struct-union.rs index 4c0189dd0464..bf2d6e731aa4 100644 --- a/tests/codegen/issues/issue-98678-struct-union.rs +++ b/tests/codegen/issues/issue-98678-struct-union.rs @@ -5,7 +5,7 @@ // ignore-tidy-linelength -// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}/issue-98678-struct-union.rs{{".*}}) +// NONMSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*[/\\]}}issue-98678-struct-union.rs{{".*}}) // MSVC: ![[#FILE:]] = !DIFile({{.*}}filename:{{.*}}\\issue-98678-struct-union.rs{{".*}}) // CHECK: !DICompositeType({{.*"}}MyType{{".*}}file: ![[#FILE]]{{.*}}line: [[# @LINE + 1]], From 3b2ff90529ec6c24d87a7a163ed6acf70acfe4b3 Mon Sep 17 00:00:00 2001 From: Xelph Date: Mon, 2 Dec 2024 20:55:45 -0700 Subject: [PATCH 317/330] Add ui test for const evaluation fail when type is too big. --- tests/ui/consts/const-eval-fail-too-big.rs | 12 ++++++++++++ tests/ui/consts/const-eval-fail-too-big.stderr | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/ui/consts/const-eval-fail-too-big.rs create mode 100644 tests/ui/consts/const-eval-fail-too-big.stderr diff --git a/tests/ui/consts/const-eval-fail-too-big.rs b/tests/ui/consts/const-eval-fail-too-big.rs new file mode 100644 index 000000000000..4b5dbc1d7a4e --- /dev/null +++ b/tests/ui/consts/const-eval-fail-too-big.rs @@ -0,0 +1,12 @@ +//Error output test for #78834: Type is too big for the target architecture +struct B< + A: Sized = [(); { + let x = [0u8; !0usize]; + //~^ ERROR evaluation of constant value failed + 1 + }], +> { + a: A, +} + +fn main() {} diff --git a/tests/ui/consts/const-eval-fail-too-big.stderr b/tests/ui/consts/const-eval-fail-too-big.stderr new file mode 100644 index 000000000000..ae6664832336 --- /dev/null +++ b/tests/ui/consts/const-eval-fail-too-big.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-fail-too-big.rs:4:28 + | +LL | let x = [0u8; !0usize]; + | ^^^^^^^^^^^^^^ values of the type `[u8; usize::MAX]` are too big for the target architecture + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. From 7ac7b4c285d3130af463ce27584e2a4c08abf500 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 11:31:12 +0100 Subject: [PATCH 318/330] ./x miri: fix sysroot build --- library/std/src/collections/hash/map.rs | 4 ++-- library/std/src/collections/hash/set.rs | 4 ++-- src/bootstrap/src/core/build_steps/test.rs | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 59dcdfd08cb3..109bc3946346 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -210,8 +210,8 @@ use crate::ops::Index; /// As explained above, `HashMap` is randomly seeded: each `HashMap` instance uses a different seed, /// which means that `HashMap::new` cannot be used in const context. To construct a `HashMap` in the /// initializer of a `const` or `static` item, you will have to use a different hasher that does not -/// involve a random seed, as demonstrated in the following example. **`HashMap` constructed this -/// way are not resistant against HashDoS!** +/// involve a random seed, as demonstrated in the following example. **A `HashMap` constructed this +/// way is not resistant against HashDoS!** /// /// ```rust /// use std::collections::HashMap; diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 2a481dbaa627..4c81aaff4588 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -107,8 +107,8 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub}; /// Like `HashMap`, `HashSet` is randomly seeded: each `HashSet` instance uses a different seed, /// which means that `HashSet::new` cannot be used in const context. To construct a `HashSet` in the /// initializer of a `const` or `static` item, you will have to use a different hasher that does not -/// involve a random seed, as demonstrated in the following example. **`HashSet` constructed this -/// way are not resistant against HashDoS!** +/// involve a random seed, as demonstrated in the following example. **A `HashSet` constructed this +/// way is not resistant against HashDoS!** /// /// ```rust /// use std::collections::HashSet; diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 4fa91c1a5714..161157acffe0 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2756,6 +2756,10 @@ impl Step for Crate { // `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that // instead. But crucially we only do that for the library, not the test builds. cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1"); + // std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder + // does not set this directly, but relies on the rustc wrapper to set it, and we are not using + // the wrapper -- hence we have to set it ourselves. + cargo.rustflag("-Zforce-unstable-if-unmarked"); cargo } else { // Also prepare a sysroot for the target. From a030ffbe354be8072fe2749d89c66365c192b0fe Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 1 Dec 2024 19:07:13 -0800 Subject: [PATCH 319/330] Add `core::arch::breakpoint` and test Approved in [ACP 491](https://github.com/rust-lang/libs-team/issues/491). Remove the `unsafe` on `core::intrinsics::breakpoint()`, since it's a safe intrinsic to call and has no prerequisites. (Thanks to @zachs18 for figuring out the `bootstrap`/`not(bootstrap)` logic.) --- .../src/error_codes/E0622.md | 9 ++++--- .../rustc_hir_analysis/src/check/intrinsic.rs | 1 + library/core/src/arch.rs | 27 +++++++++++++++++++ library/core/src/intrinsics/mod.rs | 12 +++++++++ tests/assembly/breakpoint.rs | 14 ++++++++++ tests/ui/error-codes/E0622.rs | 4 +-- tests/ui/error-codes/E0622.stderr | 4 +-- 7 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 tests/assembly/breakpoint.rs diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md index 5d71ee9949d8..4cb605b636d2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0622.md +++ b/compiler/rustc_error_codes/src/error_codes/E0622.md @@ -7,10 +7,11 @@ Erroneous code example: #![allow(internal_features)] extern "rust-intrinsic" { - pub static breakpoint: fn(); // error: intrinsic must be a function + pub static atomic_singlethreadfence_seqcst: fn(); + // error: intrinsic must be a function } -fn main() { unsafe { breakpoint(); } } +fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } ``` An intrinsic is a function available for use in a given programming language @@ -22,8 +23,8 @@ error, just declare a function. Example: #![allow(internal_features)] extern "rust-intrinsic" { - pub fn breakpoint(); // ok! + pub fn atomic_singlethreadfence_seqcst(); // ok! } -fn main() { unsafe { breakpoint(); } } +fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } ``` diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 3e33120901f6..31a9b34ee0c7 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -87,6 +87,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid + | sym::breakpoint | sym::size_of | sym::min_align_of | sym::needs_drop diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 57f456c98b3c..95d88c7f6799 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -42,3 +42,30 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } + +/// Compiles to a target-specific software breakpoint instruction or equivalent. +/// +/// This will typically abort the program. It may result in a core dump, and/or the system logging +/// debug information. Additional target-specific capabilities may be possible depending on +/// debuggers or other tooling; in particular, a debugger may be able to resume execution. +/// +/// If possible, this will produce an instruction sequence that allows a debugger to resume *after* +/// the breakpoint, rather than resuming *at* the breakpoint; however, the exact behavior is +/// target-specific and debugger-specific, and not guaranteed. +/// +/// If the target platform does not have any kind of debug breakpoint instruction, this may compile +/// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of +/// target-specific abort that may or may not support convenient resumption. +/// +/// The precise behavior and the precise instruction generated are not guaranteed, except that in +/// normal execution with no debug tooling involved this will not continue executing. +/// +/// - On x86 targets, this produces an `int3` instruction. +/// - On aarch64 targets, this produces a `brk #0xf000` instruction. +// When stabilizing this, update the comment on `core::intrinsics::breakpoint`. +#[unstable(feature = "breakpoint", issue = "133724")] +#[inline(always)] +#[cfg(not(bootstrap))] +pub fn breakpoint() { + core::intrinsics::breakpoint(); +} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 46873fdc0479..4c8fd922f195 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1381,6 +1381,18 @@ pub unsafe fn prefetch_write_instruction(_data: *const T, _locality: i32) { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] +#[cfg(not(bootstrap))] +pub fn breakpoint() { + unreachable!() +} + +/// Executes a breakpoint trap, for inspection by a debugger. +/// +/// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +#[cfg(bootstrap)] pub unsafe fn breakpoint() { unreachable!() } diff --git a/tests/assembly/breakpoint.rs b/tests/assembly/breakpoint.rs new file mode 100644 index 000000000000..e0cc2d1eebb7 --- /dev/null +++ b/tests/assembly/breakpoint.rs @@ -0,0 +1,14 @@ +//@ revisions: aarch64 x86_64 +//@ assembly-output: emit-asm +//@[aarch64] only-aarch64 +//@[x86_64] only-x86_64 + +#![feature(breakpoint)] +#![crate_type = "lib"] + +// CHECK-LABEL: use_bp +// aarch64: brk #0xf000 +// x86_64: int3 +pub fn use_bp() { + core::arch::breakpoint(); +} diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs index ae7378a707e5..08c6d1712960 100644 --- a/tests/ui/error-codes/E0622.rs +++ b/tests/ui/error-codes/E0622.rs @@ -1,6 +1,6 @@ #![feature(intrinsics)] extern "rust-intrinsic" { - pub static breakpoint : unsafe extern "rust-intrinsic" fn(); + pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); //~^ ERROR intrinsic must be a function [E0622] } -fn main() { unsafe { breakpoint(); } } +fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr index c59776b211fd..739ec984fc60 100644 --- a/tests/ui/error-codes/E0622.stderr +++ b/tests/ui/error-codes/E0622.stderr @@ -1,8 +1,8 @@ error[E0622]: intrinsic must be a function --> $DIR/E0622.rs:3:5 | -LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function +LL | pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function error: aborting due to 1 previous error From cea0582dbdd231c46884ca917de3e32b75b6287a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 2 Dec 2024 21:15:38 -0800 Subject: [PATCH 320/330] miri: Adapt for `breakpoint` becoming safe --- src/tools/miri/tests/fail/breakpoint.rs | 4 +--- src/tools/miri/tests/fail/breakpoint.stderr | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs index 2dd87ea60839..42943d58191e 100644 --- a/src/tools/miri/tests/fail/breakpoint.rs +++ b/src/tools/miri/tests/fail/breakpoint.rs @@ -1,7 +1,5 @@ #![feature(core_intrinsics)] fn main() { - unsafe { - core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap - }; + core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap } diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr index ca98e81f1f4e..f203cb0c15f1 100644 --- a/src/tools/miri/tests/fail/breakpoint.stderr +++ b/src/tools/miri/tests/fail/breakpoint.stderr @@ -1,8 +1,8 @@ error: abnormal termination: trace/breakpoint trap --> tests/fail/breakpoint.rs:LL:CC | -LL | core::intrinsics::breakpoint() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap +LL | core::intrinsics::breakpoint(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap | = note: BACKTRACE: = note: inside `main` at tests/fail/breakpoint.rs:LL:CC From a69fe84ec841c20d229711d6861c5d889851e7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 2 Dec 2024 16:16:41 +0000 Subject: [PATCH 321/330] switch jemalloc-sys back to tikv-jemalloc-sys, and update to 0.6.0 --- Cargo.lock | 24 ++++++++++++------------ compiler/rustc/Cargo.toml | 6 +++--- compiler/rustc/src/main.rs | 2 ++ src/librustdoc/lib.rs | 2 +- src/tools/miri/Cargo.toml | 4 ++-- src/tools/miri/src/bin/miri.rs | 2 ++ src/tools/tidy/src/deps.rs | 2 +- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ccf05cc5b84..a96e06858583 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1877,16 +1877,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "jobserver" version = "0.1.32" @@ -2287,7 +2277,6 @@ dependencies = [ "ctrlc", "directories", "getrandom", - "jemalloc-sys", "libc", "libffi", "libloading", @@ -2297,6 +2286,7 @@ dependencies = [ "rustc_version", "smallvec", "tempfile", + "tikv-jemalloc-sys", "ui_test", "windows-sys 0.52.0", ] @@ -3151,12 +3141,12 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys", "rustc_codegen_ssa", "rustc_driver", "rustc_driver_impl", "rustc_smir", "stable_mir", + "tikv-jemalloc-sys", ] [[package]] @@ -5260,6 +5250,16 @@ dependencies = [ name = "tier-check" version = "0.1.0" +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "time" version = "0.3.36" diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index f85c30ac7ec5..d24b630516a7 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -20,14 +20,14 @@ rustc_smir = { path = "../rustc_smir" } stable_mir = { path = "../stable_mir" } # tidy-alphabetical-end -[dependencies.jemalloc-sys] -version = "0.5.0" +[dependencies.tikv-jemalloc-sys] +version = "0.6.0" optional = true features = ['unprefixed_malloc_on_supported_platforms'] [features] # tidy-alphabetical-start -jemalloc = ['dep:jemalloc-sys'] +jemalloc = ['dep:tikv-jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index ccf88d8ff4bc..a55a63a7bf17 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -43,6 +43,8 @@ fn main() { { use std::os::raw::{c_int, c_void}; + use tikv_jemalloc_sys as jemalloc_sys; + #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; #[used] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 436d36d899e5..8bc543f7e72a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -68,7 +68,7 @@ extern crate test; // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs // about jemalloc. #[cfg(feature = "jemalloc")] -extern crate jemalloc_sys; +extern crate tikv_jemalloc_sys as jemalloc_sys; use std::env::{self, VarError}; use std::io::{self, IsTerminal}; diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index cb02914fd93b..473b4fba928b 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -31,8 +31,8 @@ directories = "5" # Copied from `compiler/rustc/Cargo.toml`. # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't # easily use that since we support of-tree builds. -[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.jemalloc-sys] -version = "0.5.0" +[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.tikv-jemalloc-sys] +version = "0.6.0" features = ['unprefixed_malloc_on_supported_platforms'] [target.'cfg(unix)'.dependencies] diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index c61c62c73dad..1e0e31f01abd 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -316,6 +316,8 @@ fn jemalloc_magic() { // See there for further comments. use std::os::raw::{c_int, c_void}; + use tikv_jemalloc_sys as jemalloc_sys; + #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; #[used] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e065f01ebba8..afa0b9a67607 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -307,7 +307,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "intl_pluralrules", "itertools", "itoa", - "jemalloc-sys", "jobserver", "lazy_static", "leb128", @@ -392,6 +391,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "thiserror-impl", "thorin-dwp", "thread_local", + "tikv-jemalloc-sys", "time", "time-core", "time-macros", From 8b7d3d396761f7fe4d609f9983bd196ef127e8c9 Mon Sep 17 00:00:00 2001 From: Tobias Decking Date: Tue, 3 Dec 2024 12:40:00 +0100 Subject: [PATCH 322/330] Update the definition of `borrowing_sub` This ensures that it matches the one in `carrying_add`. --- library/core/src/num/uint_macros.rs | 2 +- ...bigint-add.rs => x86_64-bigint-helpers.rs} | 25 +++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) rename tests/assembly/{x86_64-bigint-add.rs => x86_64-bigint-helpers.rs} (52%) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c853db181cee..c79b2f7ad8ed 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2445,7 +2445,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_sub(rhs); let (c, d) = a.overflowing_sub(borrow as $SelfT); - (c, b || d) + (c, b | d) } /// Calculates `self` - `rhs` with a signed `rhs` diff --git a/tests/assembly/x86_64-bigint-add.rs b/tests/assembly/x86_64-bigint-helpers.rs similarity index 52% rename from tests/assembly/x86_64-bigint-add.rs rename to tests/assembly/x86_64-bigint-helpers.rs index 4bcb9732c640..198e55435390 100644 --- a/tests/assembly/x86_64-bigint-add.rs +++ b/tests/assembly/x86_64-bigint-helpers.rs @@ -6,8 +6,8 @@ #![no_std] #![feature(bigint_helper_methods)] -// This checks that the `carrying_add` implementation successfully chains, to catch -// issues like +// This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain, +// to catch issues like // This forces the ABI to avoid the windows-vs-linux ABI differences. @@ -31,3 +31,24 @@ pub unsafe extern "sysv64" fn bigint_chain_carrying_add( } carry } + +// CHECK-LABEL: bigint_chain_borrowing_sub: +#[no_mangle] +pub unsafe extern "sysv64" fn bigint_chain_borrowing_sub( + dest: *mut u64, + src1: *const u64, + src2: *const u64, + n: usize, + mut carry: bool, +) -> bool { + // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] + // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] + // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] + // CHECK: sbb [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + for i in 0..n { + (*dest.add(i), carry) = u64::borrowing_sub(*src1.add(i), *src2.add(i), carry); + } + carry +} From f91fd0cb87a69ffc5bac28cef494871c12db3918 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 3 Dec 2024 16:34:42 +0000 Subject: [PATCH 323/330] Remove generic_associated_types_extended feature gate --- compiler/rustc_feature/src/removed.rs | 7 +++ compiler/rustc_feature/src/unstable.rs | 2 - .../src/traits/dyn_compatibility.rs | 5 +- .../src/traits/project.rs | 26 +-------- .../src/traits/select/confirmation.rs | 2 +- tests/crashes/131538.rs | 13 ----- ...-gate-generic_associated_types_extended.rs | 4 -- ...e-generic_associated_types_extended.stderr | 12 ---- .../extended/lending_iterator.rs | 9 +-- ...or.base.stderr => lending_iterator.stderr} | 4 +- .../extended/lending_iterator_2.rs | 8 +-- ....base.stderr => lending_iterator_2.stderr} | 2 +- .../gat-in-trait-path.rs | 12 ++-- .../gat-in-trait-path.stderr | 58 +++++++++++++++++++ .../issue-67510-pass.rs | 9 +-- .../issue-67510-pass.stderr | 18 ++++++ .../generic-associated-types/issue-76535.rs | 9 +-- .../issue-76535.stderr | 55 ++++++++++++++++++ .../generic-associated-types/issue-78671.rs | 7 +-- .../issue-78671.stderr | 35 +++++++++++ .../generic-associated-types/issue-79422.rs | 10 +--- .../issue-79422.stderr | 57 ++++++++++++++++++ .../generic-associated-types/trait-objects.rs | 12 +--- .../trait-objects.stderr | 48 +++++++++++++++ 24 files changed, 300 insertions(+), 124 deletions(-) delete mode 100644 tests/crashes/131538.rs delete mode 100644 tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs delete mode 100644 tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr rename tests/ui/generic-associated-types/extended/{lending_iterator.base.stderr => lending_iterator.stderr} (90%) rename tests/ui/generic-associated-types/extended/{lending_iterator_2.base.stderr => lending_iterator_2.stderr} (93%) create mode 100644 tests/ui/generic-associated-types/gat-in-trait-path.stderr create mode 100644 tests/ui/generic-associated-types/issue-67510-pass.stderr create mode 100644 tests/ui/generic-associated-types/issue-76535.stderr create mode 100644 tests/ui/generic-associated-types/issue-78671.stderr create mode 100644 tests/ui/generic-associated-types/issue-79422.stderr create mode 100644 tests/ui/generic-associated-types/trait-objects.stderr diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 69a14bd9f120..8b4f441dafe2 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -119,6 +119,13 @@ declare_features! ( (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), /// Allows defining generators. (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")), + /// An extension to the `generic_associated_types` feature, allowing incomplete features. + (removed, generic_associated_types_extended, "CURRENT_RUSTC_VERSION", Some(95451), + Some( + "feature needs overhaul and reimplementation pending \ + better implied higher-ranked implied bounds support" + ) + ), /// Allows `impl Trait` in bindings (`let`, `const`, `static`). (removed, impl_trait_in_bindings, "1.55.0", Some(63065), Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index ec908762da72..1f205dacd176 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -497,8 +497,6 @@ declare_features! ( (unstable, gen_blocks, "1.75.0", Some(117078)), /// Infer generic args for both consts and types. (unstable, generic_arg_infer, "1.55.0", Some(85077)), - /// An extension to the `generic_associated_types` feature, allowing incomplete features. - (incomplete, generic_associated_types_extended, "1.61.0", Some(95451)), /// Allows non-trivial generic constants which have to have wfness manually propagated to callers (incomplete, generic_const_exprs, "1.56.0", Some(76560)), /// Allows generic parameters and where-clauses on free & associated const items. diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e0a9ddf1876e..43481ee910af 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -329,10 +329,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( .collect(), // Associated types can only be dyn-compatible if they have `Self: Sized` bounds. ty::AssocKind::Type => { - if !tcx.features().generic_associated_types_extended() - && !tcx.generics_of(item.def_id).is_own_empty() - && !item.is_impl_trait_in_trait() - { + if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() { vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)] } else { // We will permit associated types if they are explicitly mentioned in the trait object. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 01f6cccb375a..49c34550f8e0 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -14,7 +14,7 @@ use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::sym; @@ -179,35 +179,11 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>( ) -> ProjectAndUnifyResult<'tcx> { let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { - let old_universe = infcx.universe(); let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); - let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); match project_and_unify_term(selcx, &placeholder_obligation) { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), - ProjectAndUnifyResult::Holds(obligations) - if old_universe != new_universe - && selcx.tcx().features().generic_associated_types_extended() => - { - // If the `generic_associated_types_extended` feature is active, then we ignore any - // obligations references lifetimes from any universe greater than or equal to the - // universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`, - // which isn't quite what we want. Ideally, we want either an implied - // `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we - // instantiate concrete regions. There is design work to be done here; until then, - // however, this allows experimenting potential GAT features without running into - // well-formedness issues. - let new_obligations = obligations - .into_iter() - .filter(|obligation| { - let mut visitor = MaxUniverse::new(); - obligation.predicate.visit_with(&mut visitor); - visitor.max_universe() < new_universe - }) - .collect(); - Ok(ProjectAndUnifyResult::Holds(new_obligations)) - } other => Ok(other), } }); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 712856e6a8f2..19b4125e75cd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -626,7 +626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for assoc_type in assoc_types { let defs: &ty::Generics = tcx.generics_of(assoc_type); - if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended() { + if !defs.own_params.is_empty() { tcx.dcx().span_delayed_bug( obligation.cause.span, "GATs in trait object shouldn't have been considered", diff --git a/tests/crashes/131538.rs b/tests/crashes/131538.rs deleted file mode 100644 index f971d8b7791e..000000000000 --- a/tests/crashes/131538.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #131538 -#![feature(generic_associated_types_extended)] -#![feature(trivial_bounds)] - -trait HealthCheck { - async fn check(); -} - -fn do_health_check_par() -where - HealthCheck: HealthCheck, -{ -} diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs deleted file mode 100644 index 7842d44ac4f0..000000000000 --- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This feature doesn't *currently* fire on any specific code; it's just a -// behavior change. Future changes might. -#[rustc_error] //~ the -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr b/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr deleted file mode 100644 index a5ab1b0d6313..000000000000 --- a/tests/ui/feature-gates/feature-gate-generic_associated_types_extended.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable - --> $DIR/feature-gate-generic_associated_types_extended.rs:3:1 - | -LL | #[rustc_error] - | ^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` 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/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs index 7cd32413001e..8d815f6dc780 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -1,9 +1,4 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] +//@ known-bug: #133805 pub trait FromLendingIterator: Sized { fn from_iter LendingIterator = A>>(iter: T) -> Self; @@ -11,7 +6,6 @@ pub trait FromLendingIterator: Sized { impl FromLendingIterator for Vec { fn from_iter LendingIterator = A>>(mut iter: I) -> Self { - //[base]~^ impl has stricter let mut v = vec![]; while let Some(item) = iter.next() { v.push(item); @@ -32,7 +26,6 @@ pub trait LendingIterator { Self: for<'q> LendingIterator = A>, { >::from_iter(self) - //[base]~^ ERROR: does not live long enough } } diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.stderr similarity index 90% rename from tests/ui/generic-associated-types/extended/lending_iterator.base.stderr rename to tests/ui/generic-associated-types/extended/lending_iterator.stderr index b19280b45c24..84f5ed07bda5 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator.stderr @@ -1,5 +1,5 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/lending_iterator.rs:13:45 + --> $DIR/lending_iterator.rs:8:45 | LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; | ------------------------------------------------------------------------ definition of `from_iter` from trait @@ -8,7 +8,7 @@ LL | fn from_iter LendingIterator = A>>(mut iter: I) -> | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` error: `Self` does not live long enough - --> $DIR/lending_iterator.rs:34:9 + --> $DIR/lending_iterator.rs:28:9 | LL | >::from_iter(self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs index f4b0dae0a91c..0545d4d12bba 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator_2.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.rs @@ -1,9 +1,4 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] +//@ known-bug: #133805 pub trait FromLendingIterator: Sized { fn from_iter LendingIterator = A>>(iter: T) -> Self; @@ -11,7 +6,6 @@ pub trait FromLendingIterator: Sized { impl FromLendingIterator for Vec { fn from_iter LendingIterator = A>>(mut iter: I) -> Self { - //[base]~^ impl has stricter let mut v = vec![]; while let Some(item) = iter.next() { v.push(item); diff --git a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator_2.stderr similarity index 93% rename from tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr rename to tests/ui/generic-associated-types/extended/lending_iterator_2.stderr index 717d867057e7..47c32a28aea5 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator_2.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator_2.stderr @@ -1,5 +1,5 @@ error[E0276]: impl has stricter requirements than trait - --> $DIR/lending_iterator_2.rs:13:45 + --> $DIR/lending_iterator_2.rs:8:45 | LL | fn from_iter LendingIterator = A>>(iter: T) -> Self; | ------------------------------------------------------------------------ definition of `from_iter` from trait diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs index 7eb0aabb3333..cd759a73cf27 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.rs +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -1,10 +1,6 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass +//@ check-fail #![feature(associated_type_defaults)] -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] trait Foo { type A<'a> where Self: 'a; @@ -24,12 +20,12 @@ impl Foo for Fooer { } fn f(_arg : Box Foo = &'a ()>>) {} -//[base]~^ the trait `Foo` cannot be made into an object +//~^ the trait `Foo` cannot be made into an object fn main() { let foo = Fooer(5); f(Box::new(foo)); - //[base]~^ the trait `Foo` cannot be made into an object - //[base]~| the trait `Foo` cannot be made into an object + //~^ the trait `Foo` cannot be made into an object + //~| the trait `Foo` cannot be made into an object } diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr new file mode 100644 index 000000000000..b2176fa6de3b --- /dev/null +++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr @@ -0,0 +1,58 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:22:17 + | +LL | fn f(_arg : Box Foo = &'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: + Fooy + Fooer + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:28:5 + | +LL | f(Box::new(foo)); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: + Fooy + Fooer + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/gat-in-trait-path.rs:28:5 + | +LL | f(Box::new(foo)); + | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/gat-in-trait-path.rs:6:10 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | type A<'a> where Self: 'a; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: + Fooy + Fooer + = note: required for the cast from `Box>` to `Box<(dyn Foo = &'a ()> + 'static)>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-67510-pass.rs b/tests/ui/generic-associated-types/issue-67510-pass.rs index 1596f401bbcb..a48d9c37cd4f 100644 --- a/tests/ui/generic-associated-types/issue-67510-pass.rs +++ b/tests/ui/generic-associated-types/issue-67510-pass.rs @@ -1,15 +1,10 @@ -//@ revisions: base extended -//@[base] check-fail -//@[extended] check-pass - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] +//@ check-fail trait X { type Y<'a>; } fn _func1<'a>(_x: Box=&'a ()>>) {} -//[base]~^ ERROR the trait `X` cannot be made into an object +//~^ ERROR the trait `X` cannot be made into an object fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510-pass.stderr b/tests/ui/generic-associated-types/issue-67510-pass.stderr new file mode 100644 index 000000000000..5560cb0f64df --- /dev/null +++ b/tests/ui/generic-associated-types/issue-67510-pass.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-67510-pass.rs:7:23 + | +LL | fn _func1<'a>(_x: Box=&'a ()>>) {} + | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-67510-pass.rs:4:10 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | type Y<'a>; + | ^ ...because it contains the generic associated type `Y` + = help: consider moving `Y` to another trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-76535.rs b/tests/ui/generic-associated-types/issue-76535.rs index cf26b65c85f2..9e18c82c7f1c 100644 --- a/tests/ui/generic-associated-types/issue-76535.rs +++ b/tests/ui/generic-associated-types/issue-76535.rs @@ -1,8 +1,3 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - pub trait SubTrait {} pub trait SuperTrait { @@ -38,6 +33,6 @@ impl SuperTrait for SuperStruct { fn main() { let sub: Box> = Box::new(SuperStruct::new(0)); //~^ ERROR missing generics for associated type - //[base]~^^ ERROR the trait - //[base]~| ERROR the trait + //~^^ ERROR the trait + //~| ERROR the trait } diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr new file mode 100644 index 000000000000..613ded6f1ef1 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-76535.stderr @@ -0,0 +1,55 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:34:33 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:4:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); + | ++++ + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:34:14 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-76535.rs:4:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead + = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type + +error[E0038]: the trait `SuperTrait` cannot be made into an object + --> $DIR/issue-76535.rs:34:57 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-76535.rs:4:10 + | +LL | pub trait SuperTrait { + | ---------- this trait cannot be made into an object... +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ ...because it contains the generic associated type `SubType` + = help: consider moving `SubType` to another trait + = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead + = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type + = note: required for the cast from `Box` to `Box = SubStruct<'_>>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-78671.rs b/tests/ui/generic-associated-types/issue-78671.rs index ce4c040644a2..0871def17313 100644 --- a/tests/ui/generic-associated-types/issue-78671.rs +++ b/tests/ui/generic-associated-types/issue-78671.rs @@ -1,15 +1,10 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - trait CollectionFamily { type Member; } fn floatify() { Box::new(Family) as &dyn CollectionFamily //~^ ERROR: missing generics for associated type - //[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object + //~| ERROR: the trait `CollectionFamily` cannot be made into an object } struct Family; diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr new file mode 100644 index 000000000000..fbd76c73895a --- /dev/null +++ b/tests/ui/generic-associated-types/issue-78671.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:5:47 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:2:10 + | +LL | type Member; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily=usize> + | +++ + +error[E0038]: the trait `CollectionFamily` cannot be made into an object + --> $DIR/issue-78671.rs:5:25 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-78671.rs:2:10 + | +LL | trait CollectionFamily { + | ---------------- this trait cannot be made into an object... +LL | type Member; + | ^^^^^^ ...because it contains the generic associated type `Member` + = help: consider moving `Member` to another trait + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-79422.rs b/tests/ui/generic-associated-types/issue-79422.rs index bf61dcaee3a5..fba7a86990ec 100644 --- a/tests/ui/generic-associated-types/issue-79422.rs +++ b/tests/ui/generic-associated-types/issue-79422.rs @@ -1,8 +1,3 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - trait RefCont<'a, T> { fn t(&'a self) -> &'a T; } @@ -42,9 +37,8 @@ impl MapLike for Source { fn main() { let m = Box::new(std::collections::BTreeMap::::new()) - //[base]~^ ERROR the trait - //[extended]~^^ type mismatch + //~^ ERROR the trait as Box>>; //~^ ERROR missing generics for associated type - //[base]~^^ ERROR the trait + //~| ERROR the trait } diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr new file mode 100644 index 000000000000..26567e5e927d --- /dev/null +++ b/tests/ui/generic-associated-types/issue-79422.stderr @@ -0,0 +1,57 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:41:36 + | +LL | as Box>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:18:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box = dyn RefCont<'_, u8>>>; + | ++++ + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:41:12 + | +LL | as Box>>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-79422.rs:18:10 + | +LL | trait MapLike { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: + std::collections::BTreeMap + Source + +error[E0038]: the trait `MapLike` cannot be made into an object + --> $DIR/issue-79422.rs:39:13 + | +LL | let m = Box::new(std::collections::BTreeMap::::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-79422.rs:18:10 + | +LL | trait MapLike { + | ------- this trait cannot be made into an object... +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` + = help: consider moving `VRefCont` to another trait + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: + std::collections::BTreeMap + Source + = note: required for the cast from `Box>` to `Box = (dyn RefCont<'_, u8> + 'static)>>` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs index 743a3df0acc8..bad9289ee5ee 100644 --- a/tests/ui/generic-associated-types/trait-objects.rs +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -1,8 +1,3 @@ -//@ revisions: base extended - -#![cfg_attr(extended, feature(generic_associated_types_extended))] -#![cfg_attr(extended, allow(incomplete_features))] - trait StreamingIterator { type Item<'a> where Self: 'a; fn size_hint(&self) -> (usize, Option); @@ -11,11 +6,10 @@ trait StreamingIterator { } fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { - //[base]~^ the trait `StreamingIterator` cannot be made into an object + //~^ the trait `StreamingIterator` cannot be made into an object x.size_hint().0 - //[extended]~^ borrowed data escapes - //[base]~^^ the trait `StreamingIterator` cannot be made into an object - //[base]~| the trait `StreamingIterator` cannot be made into an object + //~^ the trait `StreamingIterator` cannot be made into an object + //~| the trait `StreamingIterator` cannot be made into an object } fn main() {} diff --git a/tests/ui/generic-associated-types/trait-objects.stderr b/tests/ui/generic-associated-types/trait-objects.stderr new file mode 100644 index 000000000000..3e74776f999a --- /dev/null +++ b/tests/ui/generic-associated-types/trait-objects.stderr @@ -0,0 +1,48 @@ +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:8:21 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/trait-objects.rs:2:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:10:7 + | +LL | x.size_hint().0 + | ^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/trait-objects.rs:2:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error[E0038]: the trait `StreamingIterator` cannot be made into an object + --> $DIR/trait-objects.rs:10:5 + | +LL | x.size_hint().0 + | ^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/trait-objects.rs:2:10 + | +LL | trait StreamingIterator { + | ----------------- this trait cannot be made into an object... +LL | type Item<'a> where Self: 'a; + | ^^^^ ...because it contains the generic associated type `Item` + = help: consider moving `Item` to another trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. From 89b70b919656bc8d1b119dc1ce4f882e3da0d4fc Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Tue, 3 Dec 2024 12:44:35 -0500 Subject: [PATCH 324/330] change aix default codemodel=large --- compiler/rustc_target/src/spec/base/aix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs index 1869369b9e3a..fe37d313294d 100644 --- a/compiler/rustc_target/src/spec/base/aix.rs +++ b/compiler/rustc_target/src/spec/base/aix.rs @@ -4,7 +4,7 @@ use crate::spec::{Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions, cr pub(crate) fn opts() -> TargetOptions { TargetOptions { abi: "vec-extabi".into(), - code_model: Some(CodeModel::Small), + code_model: Some(CodeModel::Large), cpu: "pwr7".into(), os: "aix".into(), vendor: "ibm".into(), From c0a00b73f82a0e46155b342d62a44ba47fff5b15 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 10:21:12 -0800 Subject: [PATCH 325/330] Update wasm-component-ld to 0.5.11 This pulls in an update that supports `@`-files used to pass arguments to linkers to fix invocations on Windows that are large. Closes #133649 --- Cargo.lock | 13 +++++++++++-- src/tools/wasm-component-ld/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a96e06858583..f59dcdcf28d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5803,17 +5803,20 @@ checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-component-ld" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44" +checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938" dependencies = [ "anyhow", "clap", "lexopt", + "libc", "tempfile", "wasi-preview1-component-adapter-provider", "wasmparser 0.219.1", "wat", + "windows-sys 0.59.0", + "winsplit", "wit-component", "wit-parser", ] @@ -6185,6 +6188,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "winsplit" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956" + [[package]] name = "wit-component" version = "0.219.1" diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index acdb1aa1ab7d..965e9b01a446 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.10" +wasm-component-ld = "0.5.11" From ab38efefae34f9d69f92f09376eb40482b871de1 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 3 Dec 2024 18:43:22 +0000 Subject: [PATCH 326/330] compiletest: explain that UI tests are expected not to compile by default --- src/tools/compiletest/src/runtest.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7be9e2f2d577..84269fd44a1e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -350,10 +350,13 @@ impl<'test> TestCx<'test> { } } else { if proc_res.status.success() { - self.fatal_proc_rec( - &format!("{} test compiled successfully!", self.config.mode)[..], - proc_res, - ); + { + self.error(&format!("{} test did not emit an error", self.config.mode)); + if self.config.mode == crate::common::Mode::Ui { + println!("note: by default, ui tests are expected not to compile"); + } + proc_res.fatal(None, || ()); + }; } if !self.props.dont_check_failure_status { From db8bef50736160db2c06064fcdacda3c2e6dfeb0 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 4 Dec 2024 05:02:38 +0000 Subject: [PATCH 327/330] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e193c786effd..377639882c59 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -eddb717281a9031f645d88dd3b8323a7e25632cc +3b382642aba7cffbb2f47829b24635fad87bcf5c From f4217f42967621c53dbeb1ecdd698c1d17e97b7a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Dec 2024 08:37:23 +0100 Subject: [PATCH 328/330] clarify simd_relaxed_fma non-determinism --- library/core/src/intrinsics/simd.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 0d24b0558c59..f80a60d471c0 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -619,7 +619,8 @@ extern "rust-intrinsic" { /// set has support for a fused operation, and that the fused operation is more efficient /// than the equivalent, separate pair of mul and add instructions. It is unspecified /// whether or not a fused operation is selected, and that may depend on optimization - /// level and context, for example. + /// level and context, for example. It may even be the case that some SIMD lanes get fused + /// and others do not. /// /// `T` must be a vector of floats. #[cfg(not(bootstrap))] From 6c9402012e4e442aff1194f1888f773fa93b9517 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 4 Dec 2024 05:12:09 +0000 Subject: [PATCH 329/330] fmt --- src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index 4b49e105562f..fd7fc801dc28 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -48,7 +48,11 @@ fn test_readlink() { // Test that we report a proper error for a missing path. let res = unsafe { - libc::readlink(c"MIRI_MISSING_FILE_NAME".as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) + libc::readlink( + c"MIRI_MISSING_FILE_NAME".as_ptr(), + small_buf.as_mut_ptr().cast(), + small_buf.len(), + ) }; assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); From 76c27a98495e5d61b32ad285e5d1a6533678cf38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Dec 2024 08:15:05 +0100 Subject: [PATCH 330/330] update lockfile --- src/tools/miri/Cargo.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 01e32229f257..363b96fdff1f 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -403,16 +403,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -540,7 +530,6 @@ dependencies = [ "colored", "directories", "getrandom", - "jemalloc-sys", "libc", "libffi", "libloading", @@ -550,6 +539,7 @@ dependencies = [ "rustc_version", "smallvec", "tempfile", + "tikv-jemalloc-sys", "ui_test", "windows-sys 0.52.0", ] @@ -1002,6 +992,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "tracing" version = "0.1.40"