From bff5a0e24d5bad22ea088d3779e16c2efd03a110 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Mon, 31 Aug 2026 15:41:10 +0300 Subject: [PATCH 01/31] core: fix the docs of PanicInfo::location After `core::panic::PanicInfo` and `std::panic::PanicHookInfo` were split, the docs for `location` still showed incorrect usage of `std::panic::set_hook` for `core::panic::PanicInfo` location, leftover from before the split. Also notes for location methods of `PanicInfo` and `PanicHookInfo` were updated, explaining that if it is ever changed to return None, it should be addressed where the location is created and where it's unwrapped, to avoid unexpected behaviour when callers may expect to always receive location. For `PanicInfo`, `panic_fmt` builds it, and `panic_handler` unwraps it. For `PanicHookInfo`, `panic_with_hook` builds it, and `default_hook` unwraps it. --- library/core/src/panic/panic_info.rs | 23 ++++++++--------------- library/std/src/panic.rs | 2 +- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index ee22521cb014c..6812e2758ed02 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -68,29 +68,22 @@ impl<'a> PanicInfo<'a> { /// This method will currently always return [`Some`], but this may change /// in future versions. /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; + /// # Example /// - /// panic::set_hook(Box::new(|panic_info| { + /// ```ignore (no_std) + /// #[panic_handler] + /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! { /// if let Some(location) = panic_info.location() { - /// println!("panic occurred in file '{}' at line {}", - /// location.file(), - /// location.line(), - /// ); - /// } else { - /// println!("panic occurred but can't get location information..."); + /// write!(DEBUG_OUTPUT, "panicked at {}", location); /// } - /// })); - /// - /// panic!("Normal panic"); + /// loop {} + /// } /// ``` #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&'static Location<'static>> { // NOTE: If this is changed to sometimes return None, - // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. + // deal with that case in std::panicking::panic_handler and core::panicking::panic_fmt. Some(self.location) } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index a07a5fb6290ca..23a4cabc320b0 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -162,7 +162,7 @@ impl<'a> PanicHookInfo<'a> { #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&'static Location<'static>> { // NOTE: If this is changed to sometimes return None, - // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. + // deal with that case in std::panicking::default_hook and std::panicking::panic_with_hook. Some(self.location) } From 5040a040c961df16814ca4101d6485da91bee594 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Tue, 15 Sep 2026 22:19:41 +0300 Subject: [PATCH 02/31] docs: PanicInfo::location handling example with no location --- library/core/src/panic/panic_info.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 6812e2758ed02..d8d4073c83b9e 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -75,6 +75,8 @@ impl<'a> PanicInfo<'a> { /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! { /// if let Some(location) = panic_info.location() { /// write!(DEBUG_OUTPUT, "panicked at {}", location); + /// } else { + /// write!(DEBUG_OUTPUT, "panicked at unknown location"); /// } /// loop {} /// } From 9379da62b25d050b6aeb8caa80cea550e9e68635 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Fri, 25 Sep 2026 18:01:50 +0200 Subject: [PATCH 03/31] Don't imply incorrect things about `Global` in the docs of `System` --- library/std/src/alloc.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c6f94944006c9..cf5011c6eed5a 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -102,8 +102,14 @@ use crate::{hint, mem, ptr}; /// } /// ``` /// +/// Note that this does *not* mean you can deallocate allocations from [`Global`] +/// with [`System`] (or vice-versa), as the [`Global`] allocator is special in +/// the compiler. For more details, see the relevant docs about +/// [`#[global_allocator]`][global_allocator]. +/// /// You can also define your own wrapper around `System` if you'd like, such as -/// keeping track of the number of all bytes allocated: +/// keeping track of the number of all bytes allocated (note that due to +/// optimizations, this may not be accurate): /// /// ```rust /// use std::alloc::{System, GlobalAlloc, Layout}; @@ -140,6 +146,8 @@ use crate::{hint, mem, ptr}; /// global allocator has been selected for a Rust program. For example if a Rust /// program opts in to using jemalloc as the global allocator, `System` will /// still allocate memory using `malloc` and `HeapAlloc`. +/// +/// [global_allocator]: GlobalAlloc#the-global_allocator-attribute #[stable(feature = "alloc_system_type", since = "1.28.0")] #[derive(Copy, Debug)] #[derive_const(Clone, Default)] From 4ce013ca6530bd7cb74347879836b264b1d9d9d8 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Sun, 27 Sep 2026 20:52:15 +0300 Subject: [PATCH 04/31] Align the fallback message in panic location examples Use the same fallback string as the PanicInfo::location example in the PanicHookInfo::location and Location doc examples for consistency. --- library/core/src/panic/location.rs | 8 ++++---- library/std/src/panic.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index f37f5370997e1..63c6132c985a0 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -21,7 +21,7 @@ use crate::ptr::NonNull; /// if let Some(location) = panic_info.location() { /// println!("panic occurred in file '{}' at line {}", location.file(), location.line()); /// } else { -/// println!("panic occurred but can't get location information..."); +/// println!("panicked at unknown location"); /// } /// })); /// @@ -208,7 +208,7 @@ impl<'a> Location<'a> { /// if let Some(location) = panic_info.location() { /// println!("panic occurred in file '{}'", location.file()); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// @@ -255,7 +255,7 @@ impl<'a> Location<'a> { /// if let Some(location) = panic_info.location() { /// println!("panic occurred at line {}", location.line()); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// @@ -280,7 +280,7 @@ impl<'a> Location<'a> { /// if let Some(location) = panic_info.location() { /// println!("panic occurred at column {}", location.column()); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 23a4cabc320b0..2fef17041101c 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -151,7 +151,7 @@ impl<'a> PanicHookInfo<'a> { /// location.line(), /// ); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// From 8cafe4c32c7163465602948f0c31e97c7e8a40bf Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Sun, 30 Aug 2026 20:38:11 +0300 Subject: [PATCH 05/31] std: add `fs::rename_noreplace` Unlike `fs::rename`, the destination is never overwritten, returning `ErrorKind::AlreadyExists` if `to` already exists. Platform-specific APIs used: `renameat2` with `RENAME_NOREPLACE` flag on `Linux` and `Android`, `renamex_np` with `RENAME_EXCL` on `Apple`, and `MoveFileExW` without the `MOVEFILE_REPLACE_EXISTING` flag on `Windows`. On other Unix platforms, and on Linux, Android and Apple when the kernel or the filesystem doesn't support it, `link` followed by `unlink` is used instead. Platforms with neither return `Unsupported`. --- library/std/src/fs.rs | 67 +++++++++++++++++++++++++++ library/std/src/sys/fs/hermit.rs | 4 ++ library/std/src/sys/fs/mod.rs | 4 ++ library/std/src/sys/fs/motor.rs | 4 ++ library/std/src/sys/fs/solid.rs | 4 ++ library/std/src/sys/fs/uefi.rs | 4 ++ library/std/src/sys/fs/unix.rs | 60 +++++++++++++++++++++++- library/std/src/sys/fs/unsupported.rs | 4 ++ library/std/src/sys/fs/vexos.rs | 4 +- library/std/src/sys/fs/windows.rs | 30 +++++++++--- 10 files changed, 176 insertions(+), 9 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 65b8ed634bc05..f040b35013c7e 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -3078,6 +3078,73 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> fs_imp::rename(from.as_ref(), to.as_ref()) } +/// Renames a file or directory to a new name, returning [`AlreadyExists`] if `to` already +/// exists. +/// +/// Unlike [`fs::rename`], the destination is never overwritten. The check happens as part of the +/// same operation, which avoids check-then-rename races, but does not guarantee crash safety. +/// +/// This will not work if the new name is on a different mount point. +/// +/// # Platform-specific behavior +/// +/// This function currently corresponds to: +/// +/// * [renameat2] with `RENAME_NOREPLACE` on Linux and Android +/// * `renamex_np` with `RENAME_EXCL` on Apple platforms +/// * [MoveFileExW] without the `MOVEFILE_REPLACE_EXISTING` flag, with a fallback to +/// `SetFileInformationByHandle`, on Windows +/// * `link` followed by `unlink` on other Unix platforms and on WASI +/// * Otherwise, this function returns [`Unsupported`] +/// +/// The `link` and `unlink` fallback is also used at runtime on Linux, Android and Apple platforms +/// when the kernel or the filesystem does not support the flag, so which of these applies can +/// differ between filesystems on the same machine. +/// +/// Note that, this [may change in the future][changes]. +/// +/// [changes]: io#platform-specific-behavior +/// [renameat2]: https://man7.org/linux/man-pages/man2/renameat2.2.html +/// [MoveFileExW]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefileexw +/// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists +/// [`Unsupported`]: crate::io::ErrorKind::Unsupported +/// [`fs::rename`]: crate::fs::rename +/// +/// # Errors +/// +/// This function will return an error in the following situations, but is not +/// limited to just these cases: +/// +/// * `from` does not exist. +/// * The user lacks permissions to view contents. +/// * `from` and `to` are on separate filesystems. +/// * `to` already exists. +/// * The platform does not support this operation. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(rename_noreplace)] +/// use std::fs; +/// use std::io::ErrorKind; +/// +/// fn main() -> std::io::Result<()> { +/// // Renames a.txt to b.txt, b.txt does not exist yet. +/// fs::rename_noreplace("a.txt", "b.txt")?; +/// +/// // b.txt exists now, so this fails instead of silently overwriting it. +/// let err = fs::rename_noreplace("c.txt", "b.txt").unwrap_err(); +/// assert_eq!(err.kind(), ErrorKind::AlreadyExists); +/// Ok(()) +/// } +/// ``` +#[doc(alias = "renameat2", alias = "renamex_np", alias = "MoveFileEx", alias = "RENAME_NOREPLACE")] +#[unstable(feature = "rename_noreplace", issue = "161427")] +#[cfg_attr(not(test), rustc_diagnostic_item = "fs_rename_noreplace")] +pub fn rename_noreplace, Q: AsRef>(from: P, to: Q) -> io::Result<()> { + fs_imp::rename_noreplace(from.as_ref(), to.as_ref()) +} + /// Copies the contents of one file to another. This function will also /// copy the permission bits of the original file to the destination file. /// diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 33feee4fc1c97..9751b0a3a0ca7 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -594,6 +594,10 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { unsupported() } +pub fn rename_noreplace(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { unsupported() } diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index b2666eb2a3da9..059ba6c046076 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -78,6 +78,10 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new))) } +pub fn rename_noreplace(old: &Path, new: &Path) -> io::Result<()> { + with_native_path(old, &|old| with_native_path(new, &|new| imp::rename_noreplace(old, new))) +} + pub fn remove_dir(path: &Path) -> io::Result<()> { with_native_path(path, &imp::rmdir) } diff --git a/library/std/src/sys/fs/motor.rs b/library/std/src/sys/fs/motor.rs index 938d1537790a1..d4eb30f518fe0 100644 --- a/library/std/src/sys/fs/motor.rs +++ b/library/std/src/sys/fs/motor.rs @@ -324,6 +324,10 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { moto_rt::fs::rename(old, new).map_err(map_motor_error) } +pub fn rename_noreplace(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + pub fn rmdir(path: &Path) -> io::Result<()> { let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; moto_rt::fs::rmdir(path).map_err(map_motor_error) diff --git a/library/std/src/sys/fs/solid.rs b/library/std/src/sys/fs/solid.rs index bd963b1d2f038..b1d2acdc2b79c 100644 --- a/library/std/src/sys/fs/solid.rs +++ b/library/std/src/sys/fs/solid.rs @@ -530,6 +530,10 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { Ok(()) } +pub fn rename_noreplace(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { // Solid does not support symlinks set_perm_nofollow(p, perm) diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 08473e245cc8e..2d14a92a6b8c9 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -474,6 +474,10 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { f.set_file_info(new_info) } +pub fn rename_noreplace(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { // UEFI does not support symlinks set_perm_nofollow(p, perm) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 46d5d33d23ac2..d5e8db4e9030a 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -60,7 +60,7 @@ use crate::sys::fd::FileDesc; pub use crate::sys::fs::common::exists; use crate::sys::helpers::run_path_with_cstr; use crate::sys::time::SystemTime; -#[cfg(all(target_os = "linux", target_env = "gnu"))] +#[cfg(any(target_os = "linux", target_os = "android"))] use crate::sys::weak::syscall; #[cfg(target_os = "android")] use crate::sys::weak::weak; @@ -1885,6 +1885,59 @@ pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> { cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) } +#[cfg(any(target_os = "linux", target_os = "android"))] +pub fn rename_noreplace(old: &CStr, new: &CStr) -> io::Result<()> { + syscall!( + fn renameat2( + olddirfd: c_int, + oldpath: *const libc::c_char, + newdirfd: c_int, + newpath: *const libc::c_char, + flags: libc::c_uint, + ) -> c_int; + ); + + // `RENAME_NOREPLACE` is `c_uint` on linux and `c_int` on Android, so casting is needed here. + let flags = libc::RENAME_NOREPLACE as libc::c_uint; + let res = cvt(unsafe { + renameat2(libc::AT_FDCWD, old.as_ptr(), libc::AT_FDCWD, new.as_ptr(), flags) + }); + + match res { + Ok(_) => Ok(()), + Err(err) => match err.raw_os_error() { + // The kernel predates `renameat2`. + Some(libc::ENOSYS) => link_then_unlink(old, new), + // The filesystem does not support `RENAME_NOREPLACE`. + // `EINVAL` also covers misuse, so report it unchanged unless the fallback found `new`. + Some(libc::EINVAL) => match link_then_unlink(old, new) { + Err(fallback) if fallback.raw_os_error() != Some(libc::EEXIST) => Err(err), + res => res, + }, + _ => Err(err), + }, + } +} + +#[cfg(target_vendor = "apple")] +pub fn rename_noreplace(old: &CStr, new: &CStr) -> io::Result<()> { + let res = cvt(unsafe { libc::renamex_np(old.as_ptr(), new.as_ptr(), libc::RENAME_EXCL) }); + match res { + Ok(_) => Ok(()), + Err(err) => match err.raw_os_error() { + // The filesystem does not support `RENAME_EXCL`. + // Unlike Linux, Darwin keeps `EINVAL` for misuse only. + Some(libc::ENOTSUP) => link_then_unlink(old, new), + _ => Err(err), + }, + } +} + +#[cfg(not(any(target_os = "linux", target_os = "android", target_vendor = "apple")))] +pub fn rename_noreplace(old: &CStr, new: &CStr) -> io::Result<()> { + link_then_unlink(old, new) +} + pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> { cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()) } @@ -2094,6 +2147,11 @@ pub fn canonicalize(path: &CStr) -> io::Result { }))) } +fn link_then_unlink(old: &CStr, new: &CStr) -> io::Result<()> { + link(old, new)?; + unlink(old) +} + fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::File; use crate::sys::fs::common::NOT_FILE_ERROR; diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index 512af27401dfe..b7aa0871a8088 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs @@ -309,6 +309,10 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { unsupported() } +pub fn rename_noreplace(_old: &Path, _new: &Path) -> io::Result<()> { + unsupported() +} + pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> { match perm.0 {} } diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index 1357787c44c77..d9fc8fd26e8b2 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs @@ -12,8 +12,8 @@ use crate::sys::{unsupported, unsupported_err}; #[path = "unsupported.rs"] mod unsupported_fs; pub use unsupported_fs::{ - Dir, DirBuilder, FileTimes, canonicalize, link, readlink, remove_dir_all, rename, rmdir, - symlink, unlink, + Dir, DirBuilder, FileTimes, canonicalize, link, readlink, remove_dir_all, rename, + rename_noreplace, rmdir, symlink, unlink, }; /// VEXos file descriptor. diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 399c0749bc21e..479d3655db369 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1302,8 +1302,13 @@ pub fn unlink(path: &WCStr) -> io::Result<()> { } } -pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { - if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) } == 0 { +fn rename_inner( + old: &WCStr, + new: &WCStr, + move_flags: c::MOVE_FILE_FLAGS, + rename_flags: u32, +) -> io::Result<()> { + if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), move_flags) } == 0 { let err = api::get_last_error(); // if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move // the file while ignoring the readonly attribute. @@ -1335,10 +1340,8 @@ pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { return Err(io::ErrorKind::OutOfMemory.into()); } - (&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 { - Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS - | c::FILE_RENAME_FLAG_POSIX_SEMANTICS, - }); + (&raw mut (*file_rename_info).Anonymous) + .write(c::FILE_RENAME_INFO_0 { Flags: rename_flags }); (&raw mut (*file_rename_info).RootDirectory).write(ptr::null_mut()); // Don't include the NULL in the size @@ -1373,6 +1376,21 @@ pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { Ok(()) } +pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { + rename_inner( + old, + new, + c::MOVEFILE_REPLACE_EXISTING, + c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS | c::FILE_RENAME_FLAG_POSIX_SEMANTICS, + ) +} + +pub fn rename_noreplace(old: &WCStr, new: &WCStr) -> io::Result<()> { + // Without `MOVEFILE_REPLACE_EXISTING`, `MoveFileExW` fails if the destination + // exists. + rename_inner(old, new, 0, c::FILE_RENAME_FLAG_POSIX_SEMANTICS) +} + pub fn rmdir(p: &WCStr) -> io::Result<()> { cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?; Ok(()) From f09e0ef7eabceadb32c2e9a0a9ec95a40380cece Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Sun, 30 Aug 2026 21:54:55 +0300 Subject: [PATCH 06/31] std: add tests for `fs::rename_noreplace` --- library/std/src/fs/tests.rs | 84 +++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 250109f277dab..98d8708b5ad86 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -2647,6 +2647,90 @@ fn test_rename_symlink() { assert_eq!(fs::read_link(&dest).unwrap().as_path(), not_exist); } +#[test] +fn test_rename_noreplace() { + let tmpdir = tmpdir(); + let source_path = tmpdir.join("source_file.txt"); + let target_path = tmpdir.join("target_file.txt"); + + fs::write(&source_path, b"source hello world").unwrap(); + + fs::rename_noreplace(&source_path, &target_path).unwrap(); + assert!(!source_path.exists()); + assert_eq!(fs::read(&target_path).unwrap(), b"source hello world"); +} + +#[test] +fn test_rename_noreplace_existing_file() { + let tmpdir = tmpdir(); + let source_path = tmpdir.join("source_file.txt"); + let target_path = tmpdir.join("target_file.txt"); + + fs::write(&source_path, b"source hello world").unwrap(); + fs::write(&target_path, b"target hello world").unwrap(); + + let err = fs::rename_noreplace(&source_path, &target_path).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::AlreadyExists); + // Make sure the failed rename left both files untouched. + assert_eq!(fs::read(&source_path).unwrap(), b"source hello world"); + assert_eq!(fs::read(&target_path).unwrap(), b"target hello world"); +} + +#[test] +fn test_rename_noreplace_directory_to_empty_directory() { + // Renaming a directory over an existing empty directory should fail; + // plain `rename` would succeed here. + let tmpdir = tmpdir(); + let source_path = tmpdir.join("source_directory"); + let target_path = tmpdir.join("target_directory"); + + fs::create_dir(&source_path).unwrap(); + fs::create_dir(&target_path).unwrap(); + + let err = fs::rename_noreplace(&source_path, &target_path).unwrap_err(); + assert_matches!( + err.kind(), + // A native no-replace rename returns `AlreadyExists`. The `link`/`unlink` + // fallback cannot rename directories and returns `PermissionDenied`. + ErrorKind::AlreadyExists | ErrorKind::PermissionDenied, + "Expected AlreadyExists or PermissionDenied error, got {err}" + ); +} + +#[test] +#[cfg(any(target_os = "linux", target_os = "android", target_vendor = "apple", windows))] +fn test_rename_noreplace_directory() { + // The `link`/`unlink` fallback cannot move directories, so only platforms + // with a native no-replace rename are tested. + let tmpdir = tmpdir(); + let source_path = tmpdir.join("source_directory"); + let target_path = tmpdir.join("target_directory"); + + fs::create_dir(&source_path).unwrap(); + fs::write(source_path.join("file.txt"), b"hello world").unwrap(); + + fs::rename_noreplace(&source_path, &target_path).unwrap(); + assert!(!source_path.exists()); + assert_eq!(fs::read(target_path.join("file.txt")).unwrap(), b"hello world"); +} + +#[test] +fn test_rename_noreplace_symlink() { + let tmpdir = tmpdir(); + if !got_symlink_permission(&tmpdir) { + return; + }; + + let original = tmpdir.join("original"); + let dest = tmpdir.join("dest"); + let not_exist = Path::new("does not exist"); + + symlink_file(not_exist, &original).unwrap(); + fs::rename_noreplace(&original, &dest).unwrap(); + // Make sure that renaming `original` to `dest` preserves the symlink. + assert_eq!(fs::read_link(&dest).unwrap().as_path(), not_exist); +} + #[test] #[cfg(windows)] #[cfg_attr( From d0d58b4a64468599732faa682006113a386e041c Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Sun, 27 Sep 2026 21:42:02 +0300 Subject: [PATCH 07/31] std: clarify rename_noreplace crash guarantees Co-authored-by: Josh Triplett --- library/std/src/fs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f040b35013c7e..7c833f76f3929 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -3082,7 +3082,10 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// exists. /// /// Unlike [`fs::rename`], the destination is never overwritten. The check happens as part of the -/// same operation, which avoids check-then-rename races, but does not guarantee crash safety. +/// same operation, which avoids check-then-rename races. +/// +/// If the system crashes in the middle, it may be possible to end up with both copies of the file +/// existing, but it should not be possible to end up with zero copies, or with a half-written file. /// /// This will not work if the new name is on a different mount point. /// From 7b7ed95383a3f402319717c72d751c80d35d300f Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Sun, 27 Sep 2026 22:46:35 +0300 Subject: [PATCH 08/31] std: take plain u32 move flags on Windows windows-bindgen no longer generates the `MOVE_FILE_FLAGS` alias, so `u32` is used instead. --- library/std/src/sys/fs/windows.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 479d3655db369..af909bc403590 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1302,12 +1302,7 @@ pub fn unlink(path: &WCStr) -> io::Result<()> { } } -fn rename_inner( - old: &WCStr, - new: &WCStr, - move_flags: c::MOVE_FILE_FLAGS, - rename_flags: u32, -) -> io::Result<()> { +fn rename_inner(old: &WCStr, new: &WCStr, move_flags: u32, rename_flags: u32) -> io::Result<()> { if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), move_flags) } == 0 { let err = api::get_last_error(); // if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move From 99cc8cf3c959e411c075eb8f7d3555590fa1a369 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Mon, 28 Sep 2026 15:48:41 +0800 Subject: [PATCH 09/31] document safety requirements for atomic intrinsics --- library/core/src/intrinsics/mod.rs | 190 ++++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 16 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ecc8b66ec5785..2ff0777a2885d 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -95,7 +95,9 @@ use macros::intrinsic_dispatch_on_type; // These imports are used for simplifying intra-doc links #[allow(unused_imports)] #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))] -use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering}; +use crate::sync::atomic::{ + self, AtomicBool, AtomicI32, AtomicIsize, AtomicPtr, AtomicU32, Ordering, +}; /// A type for atomic ordering parameters for intrinsics. This is a separate type from /// `atomic::Ordering` so that we can make it `ConstParamTy` and fix the values used here without a @@ -115,12 +117,28 @@ pub enum AtomicOrdering { // N.B., these intrinsics take raw pointers because they mutate aliased // memory, which is not valid for either `&` or `&mut`. -/// Stores a value if the current value is the same as the `old` value. +/// Stores a value if the current value is the same as the `old` value, +/// with the returned `T` being the previous value and the returned `bool` being +/// whether the exchange was successful. /// `T` must be an integer or pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::compare_exchange`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::compare_exchange`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method. /// For example, [`AtomicBool::compare_exchange`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::compare_exchange`]: AtomicI32::compare_exchange +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::compare_exchange`]: AtomicPtr::compare_exchange #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_cxchg< @@ -133,12 +151,28 @@ pub const unsafe fn atomic_cxchg< src: T, ) -> (T, bool); -/// Stores a value if the current value is the same as the `old` value. +/// Stores a value if the current value is the same as the `old` value, +/// with the returned `T` being the previous value and the returned `bool` being +/// whether the exchange was successful. /// `T` must be an integer or pointer type. The comparison may spuriously fail. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::compare_exchange_weak`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::compare_exchange_weak`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method. /// For example, [`AtomicBool::compare_exchange_weak`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::compare_exchange_weak`]: AtomicI32::compare_exchange_weak +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::compare_exchange_weak`]: AtomicPtr::compare_exchange_weak #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_cxchgweak< @@ -156,18 +190,18 @@ pub const unsafe fn atomic_cxchgweak< /// /// # Safety /// -/// * If `VOLATILE` is `true`, this is equivalent to [Atomic::load_volatile]. +/// * If `VOLATILE` is `true`, this is equivalent to [`Atomic::load_volatile`]. /// Refer to the documentation of that method for safety requirements. /// -/// * If `VOLATILE` is `false`, this is equivalent to [Atomic::from_ptr] followed -/// by [Atomic::load]. Refer to the documentation of [Atomic::from_ptr] for safety requirements. +/// * If `VOLATILE` is `false`, this is equivalent to [`Atomic::from_ptr`] followed +/// by [`Atomic::load`]. Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`]. /// -/// [Atomic::load_volatile]: AtomicI32::load_volatile -/// [Atomic::from_ptr]: AtomicI32::from_ptr -/// [Atomic::load]: AtomicI32::load +/// [`Atomic::load_volatile`]: AtomicI32::load_volatile +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::load`]: AtomicI32::load #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_load( @@ -179,18 +213,18 @@ pub const unsafe fn atomic_load::store_volatile`]. /// Refer to the documentation of that method for safety requirements. /// -/// * If `VOLATILE` is `false`, this is equivalent to [Atomic::from_ptr] followed -/// by [Atomic::store]. Refer to the documentation of [Atomic::from_ptr] for safety requirements. +/// * If `VOLATILE` is `false`, this is equivalent to [`Atomic::from_ptr`] followed +/// by [`Atomic::store`]. Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method. For example, [`AtomicBool::store`]. /// -/// [Atomic::store_volatile]: AtomicI32::store_volatile -/// [Atomic::from_ptr]: AtomicI32::from_ptr -/// [Atomic::store]: AtomicI32::store +/// [`Atomic::store_volatile`]: AtomicI32::store_volatile +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::store`]: AtomicI32::store #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_store( @@ -201,8 +235,22 @@ pub const unsafe fn atomic_store::from_ptr`] followed by [`Atomic::swap`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::swap`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method. For example, [`AtomicBool::swap`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::swap`]: AtomicI32::swap +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::swap`]: AtomicPtr::swap #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xchg(dst: *mut T, src: T) -> T; @@ -211,8 +259,22 @@ pub const unsafe fn atomic_xchg(dst: *mut T, /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_add`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::fetch_byte_add`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method. For example, [`AtomicIsize::fetch_add`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_add`]: AtomicI32::fetch_add +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::fetch_byte_add`]: AtomicPtr::fetch_byte_add #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xadd( @@ -224,8 +286,22 @@ pub const unsafe fn atomic_xadd( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_sub`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::fetch_byte_sub`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method. For example, [`AtomicIsize::fetch_sub`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_sub`]: AtomicI32::fetch_sub +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::fetch_byte_sub`]: AtomicPtr::fetch_byte_sub #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xsub( @@ -237,8 +313,22 @@ pub const unsafe fn atomic_xsub( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_and`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::fetch_and`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method. For example, [`AtomicBool::fetch_and`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_and`]: AtomicI32::fetch_and +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::fetch_and`]: AtomicPtr::fetch_and #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_and( @@ -250,8 +340,16 @@ pub const unsafe fn atomic_and( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_nand`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the -/// [`AtomicBool`] type via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`]. +/// [`atomic`] types via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_nand`]: AtomicI32::fetch_nand #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_nand( @@ -263,8 +361,22 @@ pub const unsafe fn atomic_nand( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_or`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::fetch_or`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method. For example, [`AtomicBool::fetch_or`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_or`]: AtomicI32::fetch_or +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::fetch_or`]: AtomicPtr::fetch_or #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_or( @@ -276,8 +388,22 @@ pub const unsafe fn atomic_or( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_xor`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

::from_ptr`] followed by [`AtomicPtr

::fetch_xor`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method. For example, [`AtomicBool::fetch_xor`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_xor`]: AtomicI32::fetch_xor +/// [`AtomicPtr

::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

::fetch_xor`]: AtomicPtr::fetch_xor #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xor( @@ -288,8 +414,16 @@ pub const unsafe fn atomic_xor( /// Maximum with the current value using a signed comparison. /// `T` must be a signed integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_max`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method. For example, [`AtomicI32::fetch_max`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_max`]: AtomicI32::fetch_max #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_max(dst: *mut T, src: T) -> T; @@ -297,8 +431,16 @@ pub const unsafe fn atomic_max(dst: *mut T, /// Minimum with the current value using a signed comparison. /// `T` must be a signed integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_min`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method. For example, [`AtomicI32::fetch_min`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_min`]: AtomicI32::fetch_min #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_min(dst: *mut T, src: T) -> T; @@ -306,8 +448,16 @@ pub const unsafe fn atomic_min(dst: *mut T, /// Minimum with the current value using an unsigned comparison. /// `T` must be an unsigned integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_min`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method. For example, [`AtomicU32::fetch_min`]. +/// +/// [`Atomic::from_ptr`]: AtomicU32::from_ptr +/// [`Atomic::fetch_min`]: AtomicU32::fetch_min #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_umin(dst: *mut T, src: T) -> T; @@ -315,8 +465,16 @@ pub const unsafe fn atomic_umin(dst: *mut T, /// Maximum with the current value using an unsigned comparison. /// `T` must be an unsigned integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_max`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method. For example, [`AtomicU32::fetch_max`]. +/// +/// [`Atomic::from_ptr`]: AtomicU32::from_ptr +/// [`Atomic::fetch_max`]: AtomicU32::fetch_max #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_umax(dst: *mut T, src: T) -> T; From 0012416ca7a155b3c2849b095b4d6ee1ecaa3a27 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Mon, 28 Sep 2026 22:39:19 +0800 Subject: [PATCH 10/31] Add safety comments for alloc::str --- library/alloc/src/str.rs | 85 +++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index cd1c149c3c4fc..a736a25ccdeb8 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -73,7 +73,8 @@ impl> Join<&str> for [S] { type Output = String; fn join(slice: &Self, sep: &str) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: slice can be borrowed as `[&str]` and sep is `&str`, both are valid UTF-8, + // so the returned `Vec` of `join_generic_copy` is also valid UTF-8. unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) } } } @@ -183,30 +184,37 @@ where let pos = result.len(); debug_assert!(reserved_len >= pos); - // ignore-tidy-undocumented-unsafe - unsafe { - let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos); - // Convert the separator and slices to slices of MaybeUninit - // to simplify implementation in specialize_for_lengths. - let sep_uninit = core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len()); - let iter_uninit = iter.map(|it| { - let it = it.borrow().as_ref(); - core::slice::from_raw_parts(it.as_ptr().cast(), it.len()) - }); + // SAFETY: The size of remaining spare is at least `reserved_len - pos`. + let target = unsafe { result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos) }; + + // Convert the separator and slices to slices of MaybeUninit + // to simplify implementation in specialize_for_lengths. + // SAFETY: `sep` is a slice of `T`, so `sep.as_ptr().cast()` is a valid pointer, + // and `sep.len()` is the number of elements in the slice, so `from_raw_parts` is safe. + let sep_uninit = unsafe { core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len()) }; + let iter_uninit = iter.map(|it| { + let it = it.borrow().as_ref(); + // SAFETY: `it` is a slice of `T`, so `it.as_ptr().cast()` is a valid pointer, + // and `it.len()` is the number of elements in the slice, so `from_raw_parts` is safe. + unsafe { core::slice::from_raw_parts(it.as_ptr().cast(), it.len()) } + }); - // copy separator and slices over without bounds checks. - // `specialize_for_lengths!` internally calls `s.borrow()`, but because it uses - // the bounds-checked `split_at_mut` any misbehaving implementation - // will not write out of bounds. - let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4); + // copy separator and slices over without bounds checks. + // `specialize_for_lengths!` internally calls `s.borrow()`, but because it uses + // the bounds-checked `split_at_mut` any misbehaving implementation + // will not write out of bounds. + let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4); - // A weird borrow implementation may return different - // slices for the length calculation and the actual copy. - // Make sure we don't expose uninitialized bytes to the caller. - let result_len = reserved_len - remain.len(); + // A weird borrow implementation may return different + // slices for the length calculation and the actual copy. + // Make sure we don't expose uninitialized bytes to the caller. + let result_len = reserved_len - remain.len(); + // SAFETY: `result_len` is less than `reserved_len`, and all elements in `0..result_len` are initialized. + unsafe { result.set_len(result_len); } + result } @@ -250,7 +258,7 @@ impl ToOwned for str { #[inline] fn to_owned(&self) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: `self` is a valid UTF-8 str. unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } } @@ -319,7 +327,7 @@ impl str { _ => None, } { if let [to_byte] = to.as_bytes() { - // ignore-tidy-undocumented-unsafe + // SAFETY: `self` is a valid UTF-8 str, `from_byte` and `to_byte` are ASCII bytes. return unsafe { replace_ascii(self.as_bytes(), from_byte, *to_byte) }; } } @@ -332,12 +340,16 @@ impl str { let mut result = String::with_capacity(default_capacity); let mut last_end = 0; for (start, part) in self.match_indices(from) { - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` does not exceed `start`, and `start` does not exceed `self.len()`. + // Therefore, `last_end..start` is within bounds of `self`. + // For each iteration, `last_end` and `start` lie on UTF-8 sequence boundaries. result.push_str(unsafe { self.get_unchecked(last_end..start) }); result.push_str(to); last_end = start + part.len(); } - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` is the start of the remaining unmatched suffix of `self`. + // It is 0 or the end of a match returned by `match_indices`, so it is + // a UTF-8 boundary within `self`. `self.len()` is also a UTF-8 boundary. result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); result } @@ -374,12 +386,16 @@ impl str { let mut result = String::with_capacity(32); let mut last_end = 0; for (start, part) in self.match_indices(pat).take(count) { - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` does not exceed `start`, and `start` does not exceed `self.len()`. + // Therefore, `last_end..start` is within bounds of `self`. + // For each iteration, `last_end` and `start` lie on UTF-8 sequence boundaries. result.push_str(unsafe { self.get_unchecked(last_end..start) }); result.push_str(to); last_end = start + part.len(); } - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` is the start of the remaining suffix of `self`. + // It is 0 or the end of a match returned by `match_indices`, so it is + // a UTF-8 boundary within `self`. `self.len()` is also a UTF-8 boundary. result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); result } @@ -793,7 +809,7 @@ impl str { #[inline] pub fn into_string(self: Box) -> String { let slice = Box::<[u8]>::from(self); - // ignore-tidy-undocumented-unsafe + // SAFETY: `slice` is a valid UTF-8 sequence because it is created from a `Box`. unsafe { String::from_utf8_unchecked(slice.into_vec()) } } @@ -823,7 +839,7 @@ impl str { #[stable(feature = "repeat_str", since = "1.16.0")] #[inline] pub fn repeat(&self, n: usize) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: The created Vec is valid UTF-8 because `self` is str. unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } } @@ -984,9 +1000,9 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & } ascii_prefix_len += N; - // ignore-tidy-undocumented-unsafe + // SAFETY: checked in loop condition. slice = unsafe { slice.get_unchecked(N..) }; - // ignore-tidy-undocumented-unsafe + // SAFETY: out_slice has at least same length as input slice. out_slice = unsafe { out_slice.get_unchecked_mut(N..) }; } @@ -1001,9 +1017,9 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte)); } ascii_prefix_len += 1; - // ignore-tidy-undocumented-unsafe + // SAFETY: slice has at least one byte, so slicing from 1.. is safe slice = unsafe { slice.get_unchecked(1..) }; - // ignore-tidy-undocumented-unsafe + // SAFETY: out_slice has at least same length as input slice out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; } @@ -1024,6 +1040,11 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & #[allow(dead_code)] /// Faster implementation of string replacement for ASCII to ASCII cases. /// Should produce fast vectorized code. +/// +/// # Safety +/// +/// * `utf8_bytes` must contain valid UTF-8. +/// * Both `from` and `to` must be ASCII bytes (at most `0x7F`). unsafe fn replace_ascii(utf8_bytes: &[u8], from: u8, to: u8) -> String { let result: Vec = utf8_bytes.iter().map(|b| if *b == from { to } else { *b }).collect(); // SAFETY: We replaced ascii with ascii on valid utf8 strings. From 583e737e941c2b46eeb1ce3c1859bd17a3034cc8 Mon Sep 17 00:00:00 2001 From: Jeff Schwab Date: Tue, 29 Sep 2026 15:04:55 -0400 Subject: [PATCH 11/31] Mark Rc strong/weak count methods must_use --- library/alloc/src/rcs/rc.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 8cca09d1d4a8c..1b779be08197f 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -1675,6 +1675,7 @@ impl Rc { /// } /// ``` #[inline] + #[must_use] #[unstable(feature = "arc_raw_get_strong", issue = "157021")] pub unsafe fn strong_count_from_raw(ptr: *const T) -> usize { // SAFETY: Upheld by caller. @@ -1875,6 +1876,7 @@ impl Rc { /// assert_eq!(1, Rc::weak_count(&five)); /// ``` #[inline] + #[must_use] #[stable(feature = "rc_counts", since = "1.15.0")] pub fn weak_count(this: &Self) -> usize { this.inner().weak() - 1 @@ -1893,6 +1895,7 @@ impl Rc { /// assert_eq!(2, Rc::strong_count(&five)); /// ``` #[inline] + #[must_use] #[stable(feature = "rc_counts", since = "1.15.0")] pub fn strong_count(this: &Self) -> usize { this.inner().strong() From 06660e62a77abc3fe7c1b8bdfd6447513da0ece9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 15:26:43 +0200 Subject: [PATCH 12/31] simplify and clarify fs::set_permissions_nofollow tests --- library/std/src/fs.rs | 2 +- library/std/src/fs/tests.rs | 39 ++++++++++++++++--------------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 65b8ed634bc05..afc421ab82e86 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -3645,7 +3645,7 @@ pub fn set_permissions>(path: P, perm: Permissions) -> io::Result /// This function currently corresponds to the following underlying operations: /// * Android: returns [`Unsupported`] on all files. /// * Linux, BSD-based platforms, QNX, NTO: `fchmodat` with `AT_SYMLINK_NOFOLLOW`. -/// If that is not supported, we fall back to: +/// If that is not supported, we fall back to: /// * Unix-based platforms with symlinks: `open` with `O_NOFOLLOW` followed by /// [`fs::set_permissions`]. /// * Unix-based platforms without symlinks: `open` followed by [`fs::set_permissions`]. diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index db9a9f3f20b88..6ed1bdd29ebd2 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -613,12 +613,14 @@ fn set_get_unix_permissions() { assert_eq!(mask & metadata1.permissions().mode(), 0o0777); } +/// Test set_permissions_nofollow on a regular file. #[cfg(not(target_os = "android"))] #[test] fn set_get_permissions_nofollows() { let tmpdir = tmpdir(); let filename = tmpdir.join("set_get_unix_permissions_file"); check!(File::create(&filename)); + let file_metadata = check!(fs::metadata(&filename)); assert!(!file_metadata.permissions().readonly()); let mut permission_bits = file_metadata.permissions(); @@ -648,12 +650,8 @@ fn set_get_permissions_nofollows() { } } -// Only Windows and Unix support `fs::set_permissions_nofollow` +#[cfg(not(target_os = "android"))] #[test] -#[cfg(all( - any(windows, unix), - not(any(target_os = "espidf", target_os = "horizon", target_os = "wasi")) -))] fn set_get_permissions_nofollows_symlink() { #[cfg(not(windows))] use crate::os::unix::fs::symlink as symlink_file; @@ -667,14 +665,20 @@ fn set_get_permissions_nofollows_symlink() { check!(symlink_file(&filename, &symlink_name)); let init_symlink_metadata = check!(fs::symlink_metadata(&symlink_name)); - let mut init_symlink_permissions = init_symlink_metadata.permissions(); - + assert!(!init_symlink_metadata.permissions().readonly()); let init_target_metadata = check!(fs::metadata(&symlink_name)); - let init_target_permissions = init_target_metadata.permissions(); + assert!(!init_target_metadata.permissions().readonly()); // Set symlink permissions to readonly - init_symlink_permissions.set_readonly(true); - let result = fs::set_permissions_nofollow(&symlink_name, init_symlink_permissions); + let result = fs::set_permissions_nofollow(&symlink_name, { + let mut permissions = init_symlink_metadata.permissions(); + permissions.set_readonly(true); + permissions + }); + + // This should not change the permissions of the target! + let after_target_metadata = check!(fs::metadata(&symlink_name)); + assert_eq!(after_target_metadata.permissions(), init_target_metadata.permissions()); cfg_select! { any( @@ -687,16 +691,11 @@ fn set_get_permissions_nofollows_symlink() { target_os = "nto", target_os = "qnx" ) => { + // On these systems, it's confirmed the symlink itself is marked readonly + // https://superuser.com/questions/1099634/change-permissions-symbolic-link-mac-os assert_eq!(result.unwrap(), ()); - let after_target_metadata = check!(fs::metadata(&symlink_name)); - // We should expect the target file to not have its permission bits - // changed - assert_eq!(after_target_metadata.permissions(), init_target_permissions); - let after_symlink_metadata = check!(fs::symlink_metadata(&symlink_name)); - // On these systems, it's confirmed the symlink itself is marked readonly - // https://superuser.com/questions/1099634/change-permissions-symbolic-link-mac-os assert!(after_symlink_metadata.permissions().readonly()); // Reset the read-only bit under Windows 7: avoids the @@ -710,11 +709,7 @@ fn set_get_permissions_nofollows_symlink() { } } _ => { - let after_target_metadata = check!(fs::metadata(&symlink_name)); - // We should expect the target file to not have its permission bits - // changed - assert_eq!(after_target_metadata.permissions(), init_target_permissions); - + // Everywhere else, this just fails. let error_kind = result.unwrap_err().kind(); assert_eq!(error_kind, crate::io::ErrorKind::Unsupported); } From 1188653aeffa390376327267af7f19d684bba918 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Thu, 1 Oct 2026 00:12:34 -0500 Subject: [PATCH 13/31] create `debugger_visualizer` assign group --- triagebot.toml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 611f7724f5cae..1ca1d6a11e396 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1698,7 +1698,12 @@ ast_lowering = [ "@spastorino", ] debuginfo = [ - "@davidtwco" + "@davidtwco", + "@Walnut356", +] +debugger_visualizer = [ + "@Mark-Simulacrum", + "@Walnut356", ] fallback = [ "@Mark-Simulacrum", @@ -1778,6 +1783,13 @@ dep-bumps = [ "/src/doc/style-guide" = ["style-team"] "/src/doc/unstable-book" = ["compiler"] "/src/etc" = ["@Mark-Simulacrum"] +"/src/etc/gdb_load_rust_pretty_printers.py" = ["debugger_visualizer"] +"/src/etc/gdb_lookup.py" = ["debugger_visualizer"] +"/src/etc/gdb_providers.py" = ["debugger_visualizer"] +"/src/etc/lldb_lookup.py" = ["debugger_visualizer"] +"/src/etc/lldb_providers.py" = ["debugger_visualizer"] +"/src/etc/natvis" = ["debugger_visualizer"] +"/src/etc/rust_types.py" = ["debugger_visualizer"] "/src/librustdoc" = ["rustdoc"] "/src/llvm-project" = ["@cuviper"] "/src/rustdoc-json-types" = ["rustdoc"] From 64f5516c3baf5d1e232dc67c65649970ff28b036 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Thu, 1 Oct 2026 12:43:47 +0200 Subject: [PATCH 14/31] Add `SplitPathsRef` implementation for motor --- library/std/src/sys/paths/motor.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/std/src/sys/paths/motor.rs b/library/std/src/sys/paths/motor.rs index 82f8a35e50db6..cd7605d6f2662 100644 --- a/library/std/src/sys/paths/motor.rs +++ b/library/std/src/sys/paths/motor.rs @@ -15,6 +15,16 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { unparsed.as_str().split(PATH_SEPARATOR).map(into_pathbuf as fn(&str) -> PathBuf) } +pub type SplitPathsRef<'a> = iter::Map, fn(&str) -> &path::Path>; + +pub fn split_paths_ref(unparsed: &OsStr) -> Option> { + fn as_path(part: &str) -> &path::Path { + part.as_ref() + } + + Some(unparsed.as_str().split(PATH_SEPARATOR).map(as_path as fn(&str) -> &path::Path)) +} + #[derive(Debug)] pub struct JoinPathsError; From a44e8af588de848630400033c065516ca2125b99 Mon Sep 17 00:00:00 2001 From: Sinan Nalkaya Date: Thu, 1 Oct 2026 13:45:11 +0200 Subject: [PATCH 15/31] Move media & home dirs tests to fs tests. --- library/std/src/fs/dirs.rs | 67 ------------------------------------- library/std/src/fs/tests.rs | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 67 deletions(-) diff --git a/library/std/src/fs/dirs.rs b/library/std/src/fs/dirs.rs index f8b855c994ff2..a9e11e37b2639 100644 --- a/library/std/src/fs/dirs.rs +++ b/library/std/src/fs/dirs.rs @@ -519,70 +519,3 @@ impl MediaDirs { self } } - -#[cfg(test)] -mod tests { - use super::*; - - fn test_dir(what: &str) -> PathBuf { - crate::env::current_dir().unwrap().ancestors().last().unwrap().join(what) - } - - #[test] - fn test_home_dirs_field_hookup_matches() { - let mut dirs = HomeDirs::empty(); - - assert_eq!(dirs.config_home(), None); - assert_eq!(dirs.data_home(), None); - assert_eq!(dirs.state_home(), None); - assert_eq!(dirs.cache_home(), None); - - let config = test_dir("config"); - let data = test_dir("data"); - let state = test_dir("state"); - let cache = test_dir("cache"); - - dirs.set_config_home(config.clone()); - dirs.set_data_home(data.clone()); - dirs.set_state_home(state.clone()); - dirs.set_cache_home(cache.clone()); - - assert_eq!(dirs.config_home(), Some(config.as_ref())); - assert_eq!(dirs.data_home(), Some(data.as_ref())); - assert_eq!(dirs.state_home(), Some(state.as_ref())); - assert_eq!(dirs.cache_home(), Some(cache.as_ref())); - } - - #[test] - fn test_media_dirs_field_hookup_matches() { - let mut dirs = MediaDirs::empty(); - - assert_eq!(dirs.desktop(), None); - assert_eq!(dirs.documents(), None); - assert_eq!(dirs.downloads(), None); - assert_eq!(dirs.music(), None); - assert_eq!(dirs.pictures(), None); - assert_eq!(dirs.videos(), None); - - let desktop = test_dir("desktop"); - let documents = test_dir("documents"); - let downloads = test_dir("downloads"); - let music = test_dir("music"); - let pictures = test_dir("pictures"); - let videos = test_dir("videos"); - - dirs.set_desktop(desktop.clone()); - dirs.set_documents(documents.clone()); - dirs.set_downloads(downloads.clone()); - dirs.set_music(music.clone()); - dirs.set_pictures(pictures.clone()); - dirs.set_videos(videos.clone()); - - assert_eq!(dirs.desktop(), Some(desktop.as_ref())); - assert_eq!(dirs.documents(), Some(documents.as_ref())); - assert_eq!(dirs.downloads(), Some(downloads.as_ref())); - assert_eq!(dirs.music(), Some(music.as_ref())); - assert_eq!(dirs.pictures(), Some(pictures.as_ref())); - assert_eq!(dirs.videos(), Some(videos.as_ref())); - } -} diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 29c1aad06e98c..7f16e41dcf5d7 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,6 +1,7 @@ use rand::RngCore; use super::Dir; +use super::dirs::{HomeDirs, MediaDirs}; use crate::fs::{self, File, FileTimes, OpenOptions, TryLockError, exists}; use crate::io::prelude::*; use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; @@ -3166,3 +3167,65 @@ fn test_dir_metadata() { assert!(!metadata.is_file()); assert!(metadata.is_symlink()); } + +fn root_test_dir(what: &str) -> PathBuf { + crate::env::current_dir().unwrap().ancestors().last().unwrap().join(what) +} + +#[test] +fn test_home_dirs_field_hookup_matches() { + let mut dirs = HomeDirs::empty(); + + assert_eq!(dirs.config_home(), None); + assert_eq!(dirs.data_home(), None); + assert_eq!(dirs.state_home(), None); + assert_eq!(dirs.cache_home(), None); + + let config = root_test_dir("config"); + let data = root_test_dir("data"); + let state = root_test_dir("state"); + let cache = root_test_dir("cache"); + + dirs.set_config_home(config.clone()); + dirs.set_data_home(data.clone()); + dirs.set_state_home(state.clone()); + dirs.set_cache_home(cache.clone()); + + assert_eq!(dirs.config_home(), Some(config.as_ref())); + assert_eq!(dirs.data_home(), Some(data.as_ref())); + assert_eq!(dirs.state_home(), Some(state.as_ref())); + assert_eq!(dirs.cache_home(), Some(cache.as_ref())); +} + +#[test] +fn test_media_dirs_field_hookup_matches() { + let mut dirs = MediaDirs::empty(); + + assert_eq!(dirs.desktop(), None); + assert_eq!(dirs.documents(), None); + assert_eq!(dirs.downloads(), None); + assert_eq!(dirs.music(), None); + assert_eq!(dirs.pictures(), None); + assert_eq!(dirs.videos(), None); + + let desktop = root_test_dir("desktop"); + let documents = root_test_dir("documents"); + let downloads = root_test_dir("downloads"); + let music = root_test_dir("music"); + let pictures = root_test_dir("pictures"); + let videos = root_test_dir("videos"); + + dirs.set_desktop(desktop.clone()); + dirs.set_documents(documents.clone()); + dirs.set_downloads(downloads.clone()); + dirs.set_music(music.clone()); + dirs.set_pictures(pictures.clone()); + dirs.set_videos(videos.clone()); + + assert_eq!(dirs.desktop(), Some(desktop.as_ref())); + assert_eq!(dirs.documents(), Some(documents.as_ref())); + assert_eq!(dirs.downloads(), Some(downloads.as_ref())); + assert_eq!(dirs.music(), Some(music.as_ref())); + assert_eq!(dirs.pictures(), Some(pictures.as_ref())); + assert_eq!(dirs.videos(), Some(videos.as_ref())); +} From b999348c3543e43ee0a47668bddd4662df21b8bb Mon Sep 17 00:00:00 2001 From: DeaconSteiner Date: Fri, 2 Oct 2026 09:25:49 -0600 Subject: [PATCH 16/31] Fix capitalisation issues in fmt documentation --- library/core/src/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 55296a62e947a..1f1b581c5e546 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1611,7 +1611,7 @@ pub trait UpperExp: PointeeSized { /// /// let mut output = String::new(); /// fmt::write(&mut output, format_args!("Hello {}!", "world")) -/// .expect("Writing to a `String` should not fail"); +/// .expect("writing to a `String` should not fail"); /// assert_eq!(output, "Hello world!"); /// ``` /// @@ -1622,7 +1622,7 @@ pub trait UpperExp: PointeeSized { /// /// let mut output = String::new(); /// write!(&mut output, "Hello {}!", "world") -/// .expect("Writing to a `String` should not fail"); +/// .expect("writing to a `String` should not fail"); /// assert_eq!(output, "Hello world!"); /// ``` /// From 19fad968ff29e16ae895f7d948f8cb17fdb90978 Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Fri, 2 Oct 2026 19:56:33 -0400 Subject: [PATCH 17/31] chore: fix codegen backend comment --- src/bootstrap/src/core/build_steps/dist.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 7073b334c414d..7edec3d1bce30 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1736,7 +1736,7 @@ impl CommandLineStep for GccCodegenBackend { fn is_default_step(builder: &Builder<'_>) -> bool { // We only want to build the gcc backend in `x dist` if the backend was enabled // in rust.codegen-backends. - // Sadly, we don't have access to the actual target for which we're disting clif here.. + // Sadly, we don't have access to the actual target for which we're disting gcc here.. // So we just use the host target. builder .config From afc06630d2dd367b8547e3874e913b8f1fc8730e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 15:41:18 +0200 Subject: [PATCH 18/31] add Android support based on fallback path --- library/std/src/fs/tests.rs | 3 +-- library/std/src/sys/fs/unix.rs | 21 ++++++--------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 6ed1bdd29ebd2..05ab05e922a32 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -614,7 +614,6 @@ fn set_get_unix_permissions() { } /// Test set_permissions_nofollow on a regular file. -#[cfg(not(target_os = "android"))] #[test] fn set_get_permissions_nofollows() { let tmpdir = tmpdir(); @@ -650,7 +649,7 @@ fn set_get_permissions_nofollows() { } } -#[cfg(not(target_os = "android"))] +/// Test set_permissions_nofollow on a symlink. #[test] fn set_get_permissions_nofollows_symlink() { #[cfg(not(windows))] diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 46d5d33d23ac2..7c29cacbe262d 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1896,22 +1896,11 @@ pub fn set_perm_nofollow(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { Err(crate::io::ErrorKind::Unsupported.into()) } -#[cfg(target_os = "android")] -pub fn set_perm_nofollow(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { - // Currently Android seems to be having inconsistent behavior with fchmodat - // with `AT_SYMLINK_NOFOLLOW` or openat with `O_NOFOLLOW` + fchmod. - // See this issue here mentioning inconsistent behavior on fchmodat: - // https://github.com/android/ndk/issues/1258 - // On the arm-android CI job, using fchmodat with `AT_SYMLINK_NOFOLLOW` + - // fallback behavior on a symlink sets the target file's permissions, - // which is incorrect behavior. - Err(crate::io::ErrorKind::Unsupported.into()) -} - -#[cfg(not(any(target_os = "android", target_os = "vxworks")))] +#[cfg(not(target_os = "vxworks"))] pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { + /// Helper function for fallback open with `O_NOFOLLOW` + `fchmod` behavior. This will + /// successfully change the permissions of non-symlinks and fail when there's a symlink. #[inline] - /// Helper function for fallback open with `O_NOFOLLOW` + `fchmod` behavior fn open_and_set_permissions(p: &CStr, perm: FilePermissions) -> io::Result<()> { use crate::fs::{OpenOptions, Permissions}; @@ -1926,6 +1915,7 @@ pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { use crate::os::unix::fs::OpenOptionsExt; #[cfg(target_os = "wasi")] use crate::os::wasi::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); } @@ -1940,7 +1930,8 @@ pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { #[allow(unused)] let mut res: Result<(), core::io::Error> = Err(crate::io::ErrorKind::Unsupported.into()); - // These platforms support `fchmodat`, so utilize this syscall over `open` + `fchmod` + // These platforms support `fchmodat`, so utilize this syscall over `open` + `fchmod`. + // We can *not* use this on Android due to . #[cfg(any( target_os = "linux", target_os = "macos", From 56bb24407d291bed280defc757b9460fcaed0019 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 2 Oct 2026 23:30:23 +0200 Subject: [PATCH 19/31] Correctly link to enum variants when present in `Cache::external_paths` when using the `--generate-link-to-definition` feature --- src/librustdoc/html/format.rs | 10 ++++++--- .../jump-to-def/link-to-variant.rs | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/rustdoc-html/jump-to-def/link-to-variant.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b97bd93181f7a..3f1ed079f2686 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -768,11 +768,15 @@ pub(crate) fn href_with_root_path( false, ), None => { - // Associated items are handled differently with "jump to def". The anchor is generated + // Associated items are handled differently with "jump to def": the anchor is generated // directly here whereas for intra-doc links, we have some extra computation being // performed there. - let def_id_to_get = if root_path.is_some() { original_did } else { did }; - if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&def_id_to_get) { + // + // So if `root_path` is `Some()` and it's an associated item, we enter to enter the + // `else` branch to have the anchor generated here directly. + if (root_path.is_none() || original_did == did) + && let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) + { let module_fqp = to_module_fqp(shortty, fqp); let (parts, is_absolute) = url_parts(cache, did, module_fqp, relative_to)?; (fqp.as_slice(), shortty, parts, is_absolute) diff --git a/tests/rustdoc-html/jump-to-def/link-to-variant.rs b/tests/rustdoc-html/jump-to-def/link-to-variant.rs new file mode 100644 index 0000000000000..dd01f636f873f --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/link-to-variant.rs @@ -0,0 +1,21 @@ +// This test ensures that even if enum variants are imported (and thus present in the +// `Cache::external_paths` rustdoc data), we still link correctly to them. + +#![no_std] +#![crate_name = "foo"] + +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +//@ has 'src/foo/link-to-variant.rs.html' +//@ has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html#variant.Equal"]' 'Equal' +//@ has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html"]' 'Ordering' +//@ has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html"]' 'self' + +use core::cmp::Ordering::{self, Equal}; + +pub fn foo(o: Ordering) -> bool { + match o { + Ordering::Equal => true, + _ => false, + } +} From 73b2a849a09a936d92be71fcbf0e08c31a44d8c2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Oct 2026 17:16:02 +0200 Subject: [PATCH 20/31] Move `rustdoc-html` tests into the right location --- tests/rustdoc-html/{ => deref}/auxiliary/issue-19190-3.rs | 0 .../rustdoc-html/{ => deref}/deref-methods-19190-foreign-type.rs | 0 tests/rustdoc-html/{ => deref}/deref-methods-19190-inline.rs | 0 tests/rustdoc-html/{ => deref}/deref-methods-19190.rs | 0 tests/rustdoc-html/{ => private}/fake-items-doc-private-items.rs | 0 tests/rustdoc-html/{ => private}/pub-method.rs | 0 tests/rustdoc-html/{ => private}/static.rs | 0 tests/rustdoc-html/{ => private}/visibility.rs | 0 tests/rustdoc-html/{ => reexport}/auxiliary/issue-13698.rs | 0 tests/rustdoc-html/{ => reexport}/auxiliary/issue-99221-aux.rs | 0 tests/rustdoc-html/{ => reexport}/auxiliary/issue-99734-aux.rs | 0 tests/rustdoc-html/{ => reexport}/doc-hidden-method-13698.rs | 0 .../{ => reexport}/multiple-foreigns-w-same-name-99734.rs | 0 tests/rustdoc-html/{ => reexport}/multiple-import-levels.rs | 0 .../{ => reexport}/multiple-mods-w-same-name-99734.rs | 0 .../{ => reexport}/multiple-mods-w-same-name-doc-inline-83375.rs | 0 .../multiple-mods-w-same-name-doc-inline-last-item-83375.rs | 0 .../{ => reexport}/multiple-structs-w-same-name-99221.rs | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename tests/rustdoc-html/{ => deref}/auxiliary/issue-19190-3.rs (100%) rename tests/rustdoc-html/{ => deref}/deref-methods-19190-foreign-type.rs (100%) rename tests/rustdoc-html/{ => deref}/deref-methods-19190-inline.rs (100%) rename tests/rustdoc-html/{ => deref}/deref-methods-19190.rs (100%) rename tests/rustdoc-html/{ => private}/fake-items-doc-private-items.rs (100%) rename tests/rustdoc-html/{ => private}/pub-method.rs (100%) rename tests/rustdoc-html/{ => private}/static.rs (100%) rename tests/rustdoc-html/{ => private}/visibility.rs (100%) rename tests/rustdoc-html/{ => reexport}/auxiliary/issue-13698.rs (100%) rename tests/rustdoc-html/{ => reexport}/auxiliary/issue-99221-aux.rs (100%) rename tests/rustdoc-html/{ => reexport}/auxiliary/issue-99734-aux.rs (100%) rename tests/rustdoc-html/{ => reexport}/doc-hidden-method-13698.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-foreigns-w-same-name-99734.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-import-levels.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-mods-w-same-name-99734.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-mods-w-same-name-doc-inline-83375.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-mods-w-same-name-doc-inline-last-item-83375.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-structs-w-same-name-99221.rs (100%) diff --git a/tests/rustdoc-html/auxiliary/issue-19190-3.rs b/tests/rustdoc-html/deref/auxiliary/issue-19190-3.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-19190-3.rs rename to tests/rustdoc-html/deref/auxiliary/issue-19190-3.rs diff --git a/tests/rustdoc-html/deref-methods-19190-foreign-type.rs b/tests/rustdoc-html/deref/deref-methods-19190-foreign-type.rs similarity index 100% rename from tests/rustdoc-html/deref-methods-19190-foreign-type.rs rename to tests/rustdoc-html/deref/deref-methods-19190-foreign-type.rs diff --git a/tests/rustdoc-html/deref-methods-19190-inline.rs b/tests/rustdoc-html/deref/deref-methods-19190-inline.rs similarity index 100% rename from tests/rustdoc-html/deref-methods-19190-inline.rs rename to tests/rustdoc-html/deref/deref-methods-19190-inline.rs diff --git a/tests/rustdoc-html/deref-methods-19190.rs b/tests/rustdoc-html/deref/deref-methods-19190.rs similarity index 100% rename from tests/rustdoc-html/deref-methods-19190.rs rename to tests/rustdoc-html/deref/deref-methods-19190.rs diff --git a/tests/rustdoc-html/fake-items-doc-private-items.rs b/tests/rustdoc-html/private/fake-items-doc-private-items.rs similarity index 100% rename from tests/rustdoc-html/fake-items-doc-private-items.rs rename to tests/rustdoc-html/private/fake-items-doc-private-items.rs diff --git a/tests/rustdoc-html/pub-method.rs b/tests/rustdoc-html/private/pub-method.rs similarity index 100% rename from tests/rustdoc-html/pub-method.rs rename to tests/rustdoc-html/private/pub-method.rs diff --git a/tests/rustdoc-html/static.rs b/tests/rustdoc-html/private/static.rs similarity index 100% rename from tests/rustdoc-html/static.rs rename to tests/rustdoc-html/private/static.rs diff --git a/tests/rustdoc-html/visibility.rs b/tests/rustdoc-html/private/visibility.rs similarity index 100% rename from tests/rustdoc-html/visibility.rs rename to tests/rustdoc-html/private/visibility.rs diff --git a/tests/rustdoc-html/auxiliary/issue-13698.rs b/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-13698.rs rename to tests/rustdoc-html/reexport/auxiliary/issue-13698.rs diff --git a/tests/rustdoc-html/auxiliary/issue-99221-aux.rs b/tests/rustdoc-html/reexport/auxiliary/issue-99221-aux.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-99221-aux.rs rename to tests/rustdoc-html/reexport/auxiliary/issue-99221-aux.rs diff --git a/tests/rustdoc-html/auxiliary/issue-99734-aux.rs b/tests/rustdoc-html/reexport/auxiliary/issue-99734-aux.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-99734-aux.rs rename to tests/rustdoc-html/reexport/auxiliary/issue-99734-aux.rs diff --git a/tests/rustdoc-html/doc-hidden-method-13698.rs b/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs similarity index 100% rename from tests/rustdoc-html/doc-hidden-method-13698.rs rename to tests/rustdoc-html/reexport/doc-hidden-method-13698.rs diff --git a/tests/rustdoc-html/multiple-foreigns-w-same-name-99734.rs b/tests/rustdoc-html/reexport/multiple-foreigns-w-same-name-99734.rs similarity index 100% rename from tests/rustdoc-html/multiple-foreigns-w-same-name-99734.rs rename to tests/rustdoc-html/reexport/multiple-foreigns-w-same-name-99734.rs diff --git a/tests/rustdoc-html/multiple-import-levels.rs b/tests/rustdoc-html/reexport/multiple-import-levels.rs similarity index 100% rename from tests/rustdoc-html/multiple-import-levels.rs rename to tests/rustdoc-html/reexport/multiple-import-levels.rs diff --git a/tests/rustdoc-html/multiple-mods-w-same-name-99734.rs b/tests/rustdoc-html/reexport/multiple-mods-w-same-name-99734.rs similarity index 100% rename from tests/rustdoc-html/multiple-mods-w-same-name-99734.rs rename to tests/rustdoc-html/reexport/multiple-mods-w-same-name-99734.rs diff --git a/tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-83375.rs b/tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-83375.rs similarity index 100% rename from tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-83375.rs rename to tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-83375.rs diff --git a/tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-last-item-83375.rs b/tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-last-item-83375.rs similarity index 100% rename from tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-last-item-83375.rs rename to tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-last-item-83375.rs diff --git a/tests/rustdoc-html/multiple-structs-w-same-name-99221.rs b/tests/rustdoc-html/reexport/multiple-structs-w-same-name-99221.rs similarity index 100% rename from tests/rustdoc-html/multiple-structs-w-same-name-99221.rs rename to tests/rustdoc-html/reexport/multiple-structs-w-same-name-99221.rs From d78744aa4709ad118b8ceab06c84ff42bd8a7051 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Oct 2026 17:29:07 +0200 Subject: [PATCH 21/31] Remove `@ !has` annotations from `tests/rustdoc-html/reexport/doc-hidden-method-13698.rs` --- tests/rustdoc-html/reexport/auxiliary/issue-13698.rs | 1 + tests/rustdoc-html/reexport/doc-hidden-method-13698.rs | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs b/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs index 5e5381e0d07a3..6bca72ec38f9a 100644 --- a/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs +++ b/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs @@ -3,6 +3,7 @@ pub trait Foo { #[doc(hidden)] fn foo(&self) {} + fn not_hidden(&self) {} } impl Foo for i32 {} diff --git a/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs b/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs index 5c0ad18ee2989..2b2d14b2c7067 100644 --- a/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs +++ b/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs @@ -7,7 +7,11 @@ extern crate issue_13698; pub struct Foo; -//@ !has issue_13698/struct.Foo.html '//*[@id="method.foo"]' 'fn foo' +//@ has 'issue_13698/struct.Foo.html' +// There is only one visible trait impl method (from the `Foo` trait). +//@ count - '//*[@id="trait-implementations-list"]//*[@class="method trait-impl"]' 1 +//@ has - '//*[@id="trait-implementations-list"]//*[@class="method trait-impl"]' \ +// 'fn not_hidden(&self)' impl issue_13698::Foo for Foo {} pub trait Bar { @@ -15,5 +19,4 @@ pub trait Bar { fn bar(&self) {} } -//@ !has issue_13698/struct.Foo.html '//*[@id="method.bar"]' 'fn bar' impl Bar for Foo {} From c1259d23980bbfb5cba6d63b14b52b81fb2ee052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 22:33:26 +0000 Subject: [PATCH 22/31] Point at found impl in "not general enough" ``` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | LL | fn tuple_one() | --------- due to a where-clause on `tuple_one`... LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` ... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` --- compiler/rustc_error_messages/src/lib.rs | 6 +++ .../src/diagnostics/subdiagnostic.rs | 2 +- .../rustc_trait_selection/src/diagnostics.rs | 2 + .../nice_region_error/placeholder_error.rs | 16 ++++++- .../src/error_reporting/traits/ambiguity.rs | 7 ++- .../traits/fulfillment_errors.rs | 23 +++++---- .../src/error_reporting/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 5 +- .../associated-types-eq-hr.stderr | 48 +++++++++++++++---- ...n-with-leaking-placeholders.current.stderr | 6 ++- .../trait-bounds/hrtb-conflate-regions.stderr | 12 ++++- ...b-exists-forall-trait-contravariant.stderr | 6 ++- .../hrtb-exists-forall-trait-covariant.stderr | 6 ++- .../hrtb-exists-forall-trait-invariant.stderr | 6 ++- .../trait-bounds/hrtb-just-for-static.stderr | 6 ++- .../hrtb-perfect-forwarding.stderr | 6 ++- tests/ui/impl-trait/nested-rpit-hrtb.stderr | 6 ++- 17 files changed, 134 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index cb3b43aafa155..881f11ff17b0a 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -216,6 +216,12 @@ impl From for MultiSpan { } } +impl From> for MultiSpan { + fn from(span: Option) -> MultiSpan { + MultiSpan::from_spans(span.into_iter().collect()) + } +} + impl From> for MultiSpan { fn from(spans: Vec) -> MultiSpan { MultiSpan::from_spans(spans) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index baf38d2fc381f..058d93e83719a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -315,7 +315,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let binding = info.binding.binding.clone(); // FIXME(#100717): support `Option` on `primary_span` like in the // diagnostic derive - if !matches!(info.ty, FieldInnerTy::Plain(_)) { + if !matches!(info.ty, FieldInnerTy::Plain(_) | FieldInnerTy::Option(_)) { throw_invalid_attr!(attr, |diag| { let diag = diag.note("there must be exactly one primary span"); diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 1b597583d53fc..917f2e83c2282 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1052,6 +1052,8 @@ pub(crate) enum ActualImplExplNotes<'tcx> { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, + #[primary_span] + span: Option, }, #[note( "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 390e21e34ef4c..07b4a142e4014 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -613,7 +613,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let lifetime = actual_has_vid.unwrap_or_default(); let note_2 = if same_self_type { - ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime } + let impl_candidates = self.cx.find_similar_impl_candidates( + actual_trait_ref.value.def_id, + actual_trait_ref.value.self_ty(), + ); + let span = if let [candidate] = impl_candidates { + Some(self.tcx().def_span(candidate.impl_def_id)) + } else { + None + }; + ActualImplExplNotes::ButActuallyImplementsTrait { + trait_path, + has_lifetime, + lifetime, + span, + } } else if passive_voice { ActualImplExplNotes::ButActuallyImplementedForTy { trait_path, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 05e1cb6210b50..2a3ddaa54aadd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -361,8 +361,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let pred = self.tcx.short_string(predicate, &mut err.long_ty_path()); err.note(format!("cannot satisfy `{pred}`")); } - let impl_candidates = - self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap()); + let clause = predicate.as_trait_clause().unwrap(); + let impl_candidates = self.find_similar_impl_candidates( + clause.def_id(), + clause.self_ty().skip_binder(), + ); if impl_candidates.len() < 40 { self.report_similar_impl_candidates( impl_candidates.as_slice(), 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 ed0ecf459c3b8..3b21c5e5f19ba 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 @@ -2121,13 +2121,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - pub(super) fn find_similar_impl_candidates( + pub(crate) fn find_similar_impl_candidates( &self, - trait_pred: ty::PolyTraitClause<'tcx>, + trait_def_id: DefId, + self_ty: Ty<'tcx>, ) -> Vec> { let mut candidates: Vec<_> = self .tcx - .all_impls(trait_pred.def_id()) + .all_impls(trait_def_id) .filter_map(|def_id| { let imp = self.tcx.impl_trait_header(def_id); if imp.polarity != ty::ImplPolarity::Positive @@ -2137,9 +2138,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let imp = imp.trait_ref.skip_binder(); - self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map( - |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id }, - ) + self.fuzzy_match_tys(self_ty, imp.self_ty(), false).map(|similarity| { + ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id } + }) }) .collect(); if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) { @@ -2772,7 +2773,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // the user might expect to be presented with. Instead this is // useful for less general traits. if peeled && !self.tcx.trait_is_auto(def_id) && self.tcx.as_lang_item(def_id).is_none() { - let impl_candidates = self.find_similar_impl_candidates(trait_pred); + let impl_candidates = self.find_similar_impl_candidates( + trait_pred.def_id(), + trait_pred.self_ty().skip_binder(), + ); self.report_similar_impl_candidates( &impl_candidates, obligation, @@ -3475,7 +3479,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } else if !suggested && trait_predicate.polarity() == ty::ClausePolarity::Positive { // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(trait_predicate); + let impl_candidates = self.find_similar_impl_candidates( + trait_predicate.def_id(), + trait_predicate.self_ty().skip_binder(), + ); if !self.report_similar_impl_candidates( &impl_candidates, obligation, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index a7a907e8f4d94..1a661270a5d5d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -45,7 +45,7 @@ pub enum CandidateSimilarity { pub struct ImplCandidate<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, pub similarity: CandidateSimilarity, - impl_def_id: DefId, + pub impl_def_id: DefId, } enum GetSafeTransmuteErrorAndReason { 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 9219c709eee83..76755eb481db7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1245,7 +1245,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { main_trait_predicate: ty::PolyTraitClause<'tcx>, span: Span, ) -> bool { - let &[candidate] = &self.find_similar_impl_candidates(leaf_trait_predicate)[..] else { + let &[candidate] = &self.find_similar_impl_candidates( + leaf_trait_predicate.def_id(), + leaf_trait_predicate.self_ty().skip_binder(), + )[..] else { return false; }; let candidate = candidate.trait_ref; diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 70596cbab1225..4a24b75700b8b 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -53,7 +53,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -68,7 +72,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough @@ -84,7 +92,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -99,7 +111,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough @@ -115,7 +131,11 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 @@ -130,7 +150,11 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types @@ -175,7 +199,11 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 @@ -190,7 +218,11 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 12 previous errors diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index 3de229af2a077..f7f000992c06c 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -15,7 +15,11 @@ LL | | }); | |______^ | = note: ...`Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... - = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` +note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` + --> $DIR/obligation-with-leaking-placeholders.rs:15:1 + | +LL | impl<'a, T> Foo<'a> for Wrap where T: Fn(&'a i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 830ed0638a80d..4111d1f82a89c 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -10,7 +10,11 @@ LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/hrtb-conflate-regions.rs:22:1 + | +LL | impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 @@ -24,7 +28,11 @@ LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/hrtb-conflate-regions.rs:22:1 + | +LL | impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index 28ae64dff3e47..d27bf6588cddf 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -11,7 +11,11 @@ LL | foo::<()>(); | ^^^^^^^^^^^ | = note: ...`()` must implement `Trait fn(&'b u32)>` - = note: ...but it actually implements `Trait`, for some specific lifetime `'0` +note: ...but it actually implements `Trait`, for some specific lifetime `'0` + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:14:1 + | +LL | impl<'a> Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index 4b9d7e1d7109e..0fd20dbb3f0e5 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -11,7 +11,11 @@ LL | foo::<()>(); | ^^^^^^^^^^^ | = note: ...`()` must implement `Trait fn(fn(&'b u32))>` - = note: ...but it actually implements `Trait`, for some specific lifetime `'0` +note: ...but it actually implements `Trait`, for some specific lifetime `'0` + --> $DIR/hrtb-exists-forall-trait-covariant.rs:14:1 + | +LL | impl<'a> Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index 45ff3ef758713..eaecabbf544e1 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -11,7 +11,11 @@ LL | foo::<()>(); | ^^^^^^^^^^^ | = note: ...`()` must implement `Trait fn(Cell<&'b u32>)>` - = note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` +note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` + --> $DIR/hrtb-exists-forall-trait-invariant.rs:16:1 + | +LL | impl<'a> Trait)> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index 6ba3d119ccb94..1f33e65e7e715 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -10,7 +10,11 @@ LL | want_hrtb::() | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Foo<&'static isize>` +note: ...but it actually implements `Foo<&'static isize>` + --> $DIR/hrtb-just-for-static.rs:22:1 + | +LL | impl Foo<&'static isize> for StaticInt { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index db22eeb46aef0..2b68dced8af0d 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -66,7 +66,11 @@ LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` +note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` + --> $DIR/hrtb-perfect-forwarding.rs:14:1 + | +LL | impl<'a, X, F> Bar for &'a mut F where F: Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: function cannot return without recursing --> $DIR/hrtb-perfect-forwarding.rs:48:1 diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index 6c1253678e991..1f21373210a6d 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -102,7 +102,11 @@ LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = | ^^ implementation of `Bar` is not general enough | = note: `()` must implement `Bar<'a>` - = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` +note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` + --> $DIR/nested-rpit-hrtb.rs:16:1 + | +LL | impl<'a> Bar<'a> for () { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied --> $DIR/nested-rpit-hrtb.rs:60:64 From 3862c503043e2f26648b8fd634ba8854958aa266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:04:22 +0000 Subject: [PATCH 23/31] Tweak "not general enough" rendering Use a span note instead of span labels so that when talking about the trait that should have been implemented, we always point at where the obligation was introduced in a consistent place. ``` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... --> $DIR/associated-types-eq-hr.rs:59:8 | LL | fn tuple_one() | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` --- .../rustc_trait_selection/src/diagnostics.rs | 198 +++++++++--------- .../nice_region_error/placeholder_error.rs | 28 ++- .../associated-types-eq-hr.stderr | 120 ++++++----- ...outine-auto-trait-span-issue-155880.stderr | 13 +- ...olved-typeck-results.no_assumptions.stderr | 26 +-- ...ranked-auto-trait-12.no_assumptions.stderr | 13 +- ...er-ranked-auto-trait-13.assumptions.stderr | 52 ++--- ...ranked-auto-trait-13.no_assumptions.stderr | 78 +++---- ...ranked-auto-trait-15.no_assumptions.stderr | 26 +-- ...er-ranked-auto-trait-16.assumptions.stderr | 26 +-- ...ranked-auto-trait-16.no_assumptions.stderr | 26 +-- ...-ranked-auto-trait-5.no_assumptions.stderr | 15 +- .../issue-110963-early.no_assumptions.stderr | 30 +-- ...ation-not-general-enough-ice-133252.stderr | 11 +- ...n-with-leaking-placeholders.current.stderr | 15 +- ...rtb-closure-suggest-type-annotation.stderr | 30 +-- tests/ui/coroutine/auto-trait-regions.stderr | 26 +-- .../ui/coroutine/resume-arg-late-bound.stderr | 13 +- ...ot-checked-with-right-substitutions.stderr | 13 +- ...hr-fn-ptr-trait-impl-mismatch-29061.stderr | 39 ++-- ...tb-associated-type-leak-check-55731.stderr | 15 +- ...n-ptr-impl-not-general-enough-57936.stderr | 13 +- .../trait-bounds/hrtb-conflate-regions.stderr | 26 +-- ...b-exists-forall-trait-contravariant.stderr | 15 +- .../hrtb-exists-forall-trait-covariant.stderr | 15 +- .../hrtb-exists-forall-trait-invariant.stderr | 15 +- .../trait-bounds/hrtb-just-for-static.stderr | 13 +- .../hrtb-perfect-forwarding.stderr | 15 +- .../trait-bounds/issue-46989.stderr | 13 +- .../trait-bounds/issue-59311.stderr | 30 +-- .../issue-71955.current.stderr | 60 +++--- tests/ui/lifetimes/issue-105675.stderr | 78 +++---- tests/ui/lifetimes/issue-79187-2.stderr | 26 +-- tests/ui/lifetimes/issue-79187.stderr | 26 +-- .../lifetime-errors/issue_74400.stderr | 22 +- .../closure-arg-type-mismatch.stderr | 26 +-- .../closure-mismatch.current.stderr | 52 ++--- tests/ui/nll/ice-106874.stderr | 54 ++--- tests/ui/nll/issue-54302-cases.stderr | 44 ++-- ...missing-universe-cause-issue-114907.stderr | 52 ++--- ...insensitive-scopes-issue-117146.nll.stderr | 22 +- ...sitive-scopes-issue-117146.polonius.stderr | 22 +- .../impl-fn-ignore-binder-via-bottom.stderr | 22 +- tests/ui/unboxed-closures/issue-30906.stderr | 13 +- .../ui/where-clauses/where-for-self-2.stderr | 15 +- 45 files changed, 797 insertions(+), 705 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 917f2e83c2282..9d2238c188157 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -912,133 +912,123 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub(crate) enum ActualImplExplNotes<'tcx> { - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + #[note( + "closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two \ + lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`..." + )] ExpectedSignatureTwo { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] + #[note( + "closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime \ + `'{$lifetime_1}`..." + )] ExpectedSignatureAny { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] + #[note( + "closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific \ + lifetime `'{$lifetime_1}`..." + )] ExpectedSignatureSome { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" - )] + #[note("closure with signature `{$ty_or_sig}` must implement `{$trait_path}`")] ExpectedSignatureNothing { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + #[note( + "`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two \ + lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`..." + )] ExpectedPassiveTwo { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] + #[note( + "`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any \ + lifetime `'{$lifetime_1}`..." + )] ExpectedPassiveAny { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] + #[note( + "`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some \ + specific lifetime `'{$lifetime_1}`..." + )] ExpectedPassiveSome { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" - )] + #[note("`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`")] ExpectedPassiveNothing { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + #[note( + "`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and \ + `'{$lifetime_2}`..." + )] ExpectedOtherTwo { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." - )] + #[note("`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedOtherAny { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + "`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime \ + `'{$lifetime_1}`..." )] ExpectedOtherSome { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`" - )] + #[note("`{$ty_or_sig}` must implement `{$trait_path}`")] ExpectedOtherNothing { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, @@ -1098,66 +1088,71 @@ impl<'tcx> ActualImplExplNotes<'tcx> { pub(crate) fn new_expected( kind: ActualImplExpectedKind, lt_kind: ActualImplExpectedLifetimeKind, - leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, + satisfy_span: Option, + item_span: Option, + item_name: String, ) -> Self { + let label = format!("unsatisfied where-clause on `{item_name}`"); + let item_label = format!("due to a where-clause on `{item_name}`"); + let span = match (satisfy_span, item_span) { + (Some(satisfy_span), Some(item_span)) => { + let mut span = MultiSpan::from(satisfy_span); + span.push_span_label(satisfy_span, label); + span.push_span_label(item_span, item_label); + span + } + (None, Some(item_span)) => { + let mut span = MultiSpan::from(item_span); + span.push_span_label(item_span, item_label); + span + } + (Some(satisfy_span), None) => { + let mut span = MultiSpan::from(satisfy_span); + span.push_span_label(satisfy_span, label); + span + } + _ => MultiSpan::from(vec![]), + }; match (kind, lt_kind) { (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { - Self::ExpectedSignatureTwo { - leading_ellipsis, - ty_or_sig, - trait_path, - lifetime_1, - lifetime_2, - } + Self::ExpectedSignatureTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } } (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => { - Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedSignatureAny { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => { - Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedSignatureSome { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => { - Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path } + Self::ExpectedSignatureNothing { span, ty_or_sig, trait_path } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => { - Self::ExpectedPassiveTwo { - leading_ellipsis, - ty_or_sig, - trait_path, - lifetime_1, - lifetime_2, - } + Self::ExpectedPassiveTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => { - Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedPassiveAny { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => { - Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedPassiveSome { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => { - Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path } + Self::ExpectedPassiveNothing { span, ty_or_sig, trait_path } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => { - Self::ExpectedOtherTwo { - leading_ellipsis, - ty_or_sig, - trait_path, - lifetime_1, - lifetime_2, - } + Self::ExpectedOtherTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => { - Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedOtherAny { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => { - Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedOtherSome { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => { - Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path } + Self::ExpectedOtherNothing { span, ty_or_sig, trait_path } } } } @@ -1168,13 +1163,8 @@ impl<'tcx> ActualImplExplNotes<'tcx> { pub(crate) struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label("unsatisfied where-clause on `{$def_id}`")] - pub satisfy_span: Option, - #[label("due to a where-clause on `{$def_id}`...")] - pub where_span: Option, #[label("implementation of `{$trait_def_id}` is not general enough")] pub dup_span: Option, - pub def_id: String, pub trait_def_id: String, #[subdiagnostic] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 07b4a142e4014..1b57e3d77d503 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt}; -use rustc_span::bug; +use rustc_span::{Span, bug}; use rustc_structures::Limit; use tracing::{debug, instrument}; @@ -279,13 +279,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { _ => break, } } - let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = + let (mut satisfy_span, mut item_span, dup_span, item_name) = if let ObligationCauseCode::WhereClause(def_id, span) | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code && def_id != CRATE_DEF_ID.to_def_id() { ( - true, Some(span), Some( self.tcx() @@ -296,8 +295,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { self.tcx().def_path_str(def_id), ) } else { - (false, None, None, Some(span), String::new()) + (None, None, Some(span), String::new()) }; + if let Some(span) = satisfy_span && span.is_dummy() { + satisfy_span = None; + } + if let Some(span) = item_span && span.is_dummy() { + item_span = None; + } let expected_trait_ref = self.cx.deeply_resolve_ignoring_regions( ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, expected_args), @@ -369,15 +374,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { expected_has_vid, actual_has_vid, any_self_ty_has_vid, - leading_ellipsis, + satisfy_span, + item_span, + item_name, ); let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch { span, - satisfy_span, - where_span, dup_span, - def_id, trait_def_id: self.tcx().def_path_str(trait_def_id), actual_impl_expl_notes, }); @@ -494,7 +498,9 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { expected_has_vid: Option, actual_has_vid: Option, any_self_ty_has_vid: bool, - leading_ellipsis: bool, + satisfy_span: Option, + item_span: Option, + item_name: String, ) -> Vec> { // The weird thing here with the `maybe_highlighting_region` calls and the // the match inside is meant to be like this: @@ -592,11 +598,13 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let note_1 = ActualImplExplNotes::new_expected( kind, lt_kind, - leading_ellipsis, ty_or_sig, trait_path, lifetime_1, lifetime_2, + satisfy_span, + item_span, + item_name, ); let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 4a24b75700b8b..19fd633334f00 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -43,16 +43,17 @@ LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:8 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -62,16 +63,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:8 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -82,16 +84,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:53 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -101,16 +104,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:53 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -121,16 +125,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 | -LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_two` -... LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:66:8 + | +LL | fn tuple_two() + | --------- due to a where-clause on `tuple_two` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -140,16 +145,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 | -LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_two` -... LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:66:8 + | +LL | fn tuple_two() + | --------- due to a where-clause on `tuple_two` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -189,16 +195,17 @@ LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 | -LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | -------------------------------------------- unsatisfied where-clause on `tuple_four` -... LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:80:8 + | +LL | fn tuple_four() + | ---------- due to a where-clause on `tuple_four` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -208,16 +215,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 | -LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | -------------------------------------------- unsatisfied where-clause on `tuple_four` -... LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:80:8 + | +LL | fn tuple_four() + | ---------- due to a where-clause on `tuple_four` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr index e7f5413cdaaa0..893124920ee18 100644 --- a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr @@ -7,15 +7,16 @@ LL | | std::future::ready(x).await LL | | } | |_- this async fn captures a value whose type is not `Send` ... -LL | fn is_send(_: T) {} - | ------- ---- unsatisfied where-clause on `is_send` - | | - | due to a where-clause on `is_send`... -... LL | is_send(outer()) | ^^^^^^^^^^^^^^^^ | - = note: ...`Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... +note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + --> $DIR/coroutine-auto-trait-span-issue-155880.rs:25:15 + | +LL | fn is_send(_: T) {} + | ------- ^^^^ unsatisfied where-clause on `is_send` + | | + | due to a where-clause on `is_send` = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr index 01b99e203c426..da93d5a17547a 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr @@ -1,33 +1,35 @@ error: implementation of `FnOnce` is not general enough --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 | -LL | fn send(_: T) {} - | ---- ---- unsatisfied where-clause on `send` - | | - | due to a where-clause on `send`... -... LL | / send(async { LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); | |______^ | - = note: ...`fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... +note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 + | +LL | fn send(_: T) {} + | ---- ^^^^ unsatisfied where-clause on `send` + | | + | due to a where-clause on `send` = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 | -LL | fn send(_: T) {} - | ---- ---- unsatisfied where-clause on `send` - | | - | due to a where-clause on `send`... -... LL | / send(async { LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); | |______^ | - = note: ...`fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... +note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 + | +LL | fn send(_: T) {} + | ---- ^^^^ unsatisfied where-clause on `send` + | | + | due to a where-clause on `send` = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr index fd91fd659ac4d..39132cc9b4fb9 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr @@ -1,11 +1,6 @@ error: implementation of `Robot` is not general enough --> $DIR/higher-ranked-auto-trait-12.rs:31:20 | -LL | fn this_is_send(value: T) -> T { - | ------------ ---- unsatisfied where-clause on `this_is_send` - | | - | due to a where-clause on `this_is_send`... -... LL | let _my_task = this_is_send(async move { | ____________________^ LL | | let _my_iter = IRobot { @@ -16,7 +11,13 @@ LL | | yield_now().await; LL | | }); | |______^ | - = note: ...`Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any lifetime `'0`... +note: `Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-12.rs:24:20 + | +LL | fn this_is_send(value: T) -> T { + | ------------ ^^^^ unsatisfied where-clause on `this_is_send` + | | + | due to a where-clause on `this_is_send` = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot + Send + 'static)>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr index abc8ba5e7afa3..386a83ebbc761 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr @@ -1,58 +1,62 @@ error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr index 7c8edb40ac62f..02f91c47fffcb 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -1,87 +1,93 @@ error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Callable` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... +note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Callable` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... +note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: aborting due to 6 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr index fa6dd575527f8..c6c8479474c64 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 | -LL | fn require_send(_x: T) {} - | ------------ ---- unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send`... -... LL | require_send(future); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... +note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-15.rs:16:20 + | +LL | fn require_send(_x: T) {} + | ------------ ^^^^ unsatisfied where-clause on `require_send` + | | + | due to a where-clause on `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | for _ in things.iter().map(|n: &Vec| n.iter()).flatten() { error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 | -LL | fn require_send(_x: T) {} - | ------------ ---- unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send`... -... LL | require_send(future); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... +note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-15.rs:16:20 + | +LL | fn require_send(_x: T) {} + | ------------ ^^^^ unsatisfied where-clause on `require_send` + | | + | due to a where-clause on `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr index 69e356703c9f0..52c54f8355c39 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr @@ -1,33 +1,35 @@ error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr index 69e356703c9f0..52c54f8355c39 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr @@ -1,33 +1,35 @@ error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr index ef743392cb014..6119247429e28 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -5,14 +5,15 @@ LL | / assert_send(async { LL | | call_me.call().await; LL | | }); | |______^ -... -LL | pub fn assert_send(_future: F) - | ----------- due to a where-clause on `assert_send`... -LL | where -LL | F: Future + Send, - | ---- unsatisfied where-clause on `assert_send` | - = note: ...`Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... +note: `Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-5.rs:20:17 + | +LL | pub fn assert_send(_future: F) + | ----------- due to a where-clause on `assert_send` +LL | where +LL | F: Future + Send, + | ^^^^ unsatisfied where-clause on `assert_send` = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr index be635809f1db7..889d3c2948d61 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -11,14 +11,15 @@ LL | | log_health_check_failure().await; LL | | } LL | | }); | |______^ -... -LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn`... -LL | where -LL | F: Future + Send + 'static, - | ---- unsatisfied where-clause on `spawn` | - = note: ...`Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... +note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + --> $DIR/issue-110963-early.rs:37:17 + | +LL | fn spawn(future: F) -> JoinHandle + | ----- due to a where-clause on `spawn` +LL | where +LL | F: Future + Send + 'static, + | ^^^^ unsatisfied where-clause on `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` error: implementation of `Send` is not general enough @@ -34,14 +35,15 @@ LL | | log_health_check_failure().await; LL | | } LL | | }); | |______^ -... -LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn`... -LL | where -LL | F: Future + Send + 'static, - | ---- unsatisfied where-clause on `spawn` | - = note: ...`Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... +note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + --> $DIR/issue-110963-early.rs:37:17 + | +LL | fn spawn(future: F) -> JoinHandle + | ----- due to a where-clause on `spawn` +LL | where +LL | F: Future + Send + 'static, + | ^^^^ unsatisfied where-clause on `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr index b5ea0003b1d63..beb349c94bd1a 100644 --- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr +++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr @@ -3,13 +3,14 @@ error: implementation of `LoadQuery` is not general enough | LL | force_send(async_load(¬_static)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: `LoadQuery<'0>` would have to be implemented for the type `&u8`, for any lifetime `'0`... + --> $DIR/implementation-not-general-enough-ice-133252.rs:16:18 + | LL | fn force_send(_: T) {} - | ---------- ---- unsatisfied where-clause on `force_send` + | ---------- ^^^^ unsatisfied where-clause on `force_send` | | - | due to a where-clause on `force_send`... - | - = note: ...`LoadQuery<'0>` would have to be implemented for the type `&u8`, for any lifetime `'0`... + | due to a where-clause on `force_send` = note: ...but `LoadQuery<'1>` is actually implemented for the type `&'1 u8`, for some specific lifetime `'1` error[E0597]: `not_static` does not live long enough diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index f7f000992c06c..5f8198ec6bed9 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -1,12 +1,6 @@ error: implementation of `Foo` is not general enough --> $DIR/obligation-with-leaking-placeholders.rs:18:5 | -LL | fn needs_foo(_: T) - | --------- due to a where-clause on `needs_foo`... -LL | where -LL | for<'a> Wrap: Foo<'a>, - | ------- unsatisfied where-clause on `needs_foo` -... LL | / needs_foo(|x| { LL | | LL | | @@ -14,7 +8,14 @@ LL | | x.to_string(); LL | | }); | |______^ | - = note: ...`Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... +note: `Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... + --> $DIR/obligation-with-leaking-placeholders.rs:10:22 + | +LL | fn needs_foo(_: T) + | --------- due to a where-clause on `needs_foo` +LL | where +LL | for<'a> Wrap: Foo<'a>, + | ^^^^^^^ unsatisfied where-clause on `needs_foo` note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` --> $DIR/obligation-with-leaking-placeholders.rs:15:1 | diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr index b918a5c5179c8..5f7636bb34a0e 100644 --- a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr @@ -1,16 +1,17 @@ error: implementation of `FnOnce` is not general enough --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 | -LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner`... -LL | where -LL | F: FnOnce(&mut [u8]) -> Result, - | ----------------------------------------- unsatisfied where-clause on `inner` -... LL | inner(buf, outer_closure) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:8 + | +LL | fn inner(buf: &mut [u8], func: F) -> usize + | ----- due to a where-clause on `inner` +LL | where +LL | F: FnOnce(&mut [u8]) -> Result, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -20,16 +21,17 @@ LL | let outer_closure = |buf: &mut [u8]| { error: implementation of `FnOnce` is not general enough --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 | -LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner`... -LL | where -LL | F: FnOnce(&mut [u8]) -> Result, - | -------------------- unsatisfied where-clause on `inner` -... LL | inner(buf, outer_closure) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:29 + | +LL | fn inner(buf: &mut [u8], func: F) -> usize + | ----- due to a where-clause on `inner` +LL | where +LL | F: FnOnce(&mut [u8]) -> Result, + | ^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index 566f71d89c28d..25f6373124d34 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -1,18 +1,19 @@ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | -LL | fn assert_foo(f: T) {} - | ---------- --- unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo`... -... LL | let generator = #[coroutine] move || { | ------- this coroutine captures a value whose type is not `Foo` ... LL | assert_foo(generator); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... +note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + --> $DIR/auto-trait-regions.rs:21:18 + | +LL | fn assert_foo(f: T) {} + | ---------- ^^^ unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo` = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error[E0626]: borrow may still be in use when coroutine yields @@ -50,18 +51,19 @@ LL | let generator = #[coroutine] static move || { error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:51:5 | -LL | fn assert_foo(f: T) {} - | ---------- --- unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo`... -... LL | let generator = #[coroutine] move || { | ------- this coroutine captures a value whose type is not `Foo` ... LL | assert_foo(generator); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... +note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... + --> $DIR/auto-trait-regions.rs:21:18 + | +LL | fn assert_foo(f: T) {} + | ---------- ^^^ unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo` = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index bc1f1d29edd61..b44a8e363128f 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -1,15 +1,16 @@ error: implementation of `Coroutine` is not general enough --> $DIR/resume-arg-late-bound.rs:15:5 | -LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} - | ---- ------------------------------- unsatisfied where-clause on `test` - | | - | due to a where-clause on `test`... -... LL | test(gen); | ^^^^^^^^^ | - = note: ...`{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... +note: `{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` + | | + | due to a where-clause on `test` = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index 42aa33c0be186..92d39c70137ce 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -1,15 +1,16 @@ error: implementation of `Lengthen` is not general enough --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 | -LL | type Gat<'a>: for<'b> Lengthen>; - | --- ------------------------------- unsatisfied where-clause on `Gat::Gat` - | | - | due to a where-clause on `Gat::Gat`... -... LL | type Gat<'a> = &'a str; | ^^^^^^^ | - = note: ...`Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... +note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... + --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 + | +LL | type Gat<'a>: for<'b> Lengthen>; + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Gat::Gat` + | | + | due to a where-clause on `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` note: required by a bound in `Gat::Gat` --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 diff --git a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr index 7c3fcf47e6a40..16c1b69d3b053 100644 --- a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr +++ b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr @@ -1,43 +1,46 @@ error: implementation of `HR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:25:5 | -LL | fn hr(_: T) {} - | -- -- unsatisfied where-clause on `hr` - | | - | due to a where-clause on `hr`... -... LL | hr(not_hr_func); | ^^^^^^^^^^^^^^^ | - = note: ...`HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`... +note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`... + --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:15:10 + | +LL | fn hr(_: T) {} + | -- ^^ unsatisfied where-clause on `hr` + | | + | due to a where-clause on `hr` = note: ...but `HR` is actually implemented for the type `for<'a> fn(&'a ())` error: implementation of `NotHR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:27:5 | -LL | fn not_hr(_: T) {} - | ------ ----- unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr`... -... LL | not_hr(hr_func); | ^^^^^^^^^^^^^^^ | - = note: ...`NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` +note: `NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 + | +LL | fn not_hr(_: T) {} + | ------ ^^^^^ unsatisfied where-clause on `not_hr` + | | + | due to a where-clause on `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `NotHR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:29:5 | -LL | fn not_hr(_: T) {} - | ------ ----- unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr`... -... LL | not_hr(hr_func2); | ^^^^^^^^^^^^^^^^ | - = note: ...`NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` +note: `NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` + --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 + | +LL | fn not_hr(_: T) {} + | ------ ^^^^^ unsatisfied where-clause on `not_hr` + | | + | due to a where-clause on `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 3 previous errors diff --git a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr index eaa82c3f77871..d3e10e7a18d20 100644 --- a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr +++ b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr @@ -1,19 +1,20 @@ error: implementation of `DistributedIteratorMulti` is not general enough --> $DIR/hrtb-associated-type-leak-check-55731.rs:49:5 | -LL | fn multi(_reducer: I) - | ----- due to a where-clause on `multi`... -LL | where -LL | I: for<'a> DistributedIteratorMulti<&'a ()>, - | ---------------------------------------- unsatisfied where-clause on `multi` -... LL | / multi(Map { LL | | i: Cloned(PhantomData), LL | | f: X, LL | | }); | |______^ | - = note: ...`DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... +note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... + --> $DIR/hrtb-associated-type-leak-check-55731.rs:43:8 + | +LL | fn multi(_reducer: I) + | ----- due to a where-clause on `multi` +LL | where +LL | I: for<'a> DistributedIteratorMulti<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `multi` = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr index afed0bca3fffe..f7a9020c59e24 100644 --- a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr +++ b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr @@ -14,15 +14,16 @@ LL | trait X { error: implementation of `X` is not general enough --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:26:5 | -LL | fn indirect() { - | -------- - unsatisfied where-clause on `indirect` - | | - | due to a where-clause on `indirect`... -... LL | indirect::(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`X` would have to be implemented for the type `for<'a> fn(&'a ())` +note: `X` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:21:16 + | +LL | fn indirect() { + | -------- ^ unsatisfied where-clause on `indirect` + | | + | due to a where-clause on `indirect` = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 4111d1f82a89c..6700778198712 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -1,15 +1,16 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2`... -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- unsatisfied where-clause on `want_foo2` -... LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/hrtb-conflate-regions.rs:9:15 + | +LL | fn want_foo2() + | --------- due to a where-clause on `want_foo2` +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | @@ -19,15 +20,16 @@ LL | impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2`... -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- unsatisfied where-clause on `want_foo2` -... LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/hrtb-conflate-regions.rs:9:15 + | +LL | fn want_foo2() + | --------- due to a where-clause on `want_foo2` +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index d27bf6588cddf..e600c49d564be 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -1,16 +1,17 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | -LL | fn foo() - | --- due to a where-clause on `foo`... -LL | where -LL | T: Trait fn(&'b u32)>, - | -------------------------- unsatisfied where-clause on `foo` -... LL | foo::<()>(); | ^^^^^^^^^^^ | - = note: ...`()` must implement `Trait fn(&'b u32)>` +note: `()` must implement `Trait fn(&'b u32)>` + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:10:8 + | +LL | fn foo() + | --- due to a where-clause on `foo` +LL | where +LL | T: Trait fn(&'b u32)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-contravariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index 0fd20dbb3f0e5..dd720d9989060 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -1,16 +1,17 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-covariant.rs:33:5 | -LL | fn foo() - | --- due to a where-clause on `foo`... -LL | where -LL | T: Trait fn(fn(&'b u32))>, - | ------------------------------ unsatisfied where-clause on `foo` -... LL | foo::<()>(); | ^^^^^^^^^^^ | - = note: ...`()` must implement `Trait fn(fn(&'b u32))>` +note: `()` must implement `Trait fn(fn(&'b u32))>` + --> $DIR/hrtb-exists-forall-trait-covariant.rs:10:8 + | +LL | fn foo() + | --- due to a where-clause on `foo` +LL | where +LL | T: Trait fn(fn(&'b u32))>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-covariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index eaecabbf544e1..446a3102a0938 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -1,16 +1,17 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | fn foo() - | --- due to a where-clause on `foo`... -LL | where -LL | T: Trait fn(Cell<&'b u32>)>, - | -------------------------------- unsatisfied where-clause on `foo` -... LL | foo::<()>(); | ^^^^^^^^^^^ | - = note: ...`()` must implement `Trait fn(Cell<&'b u32>)>` +note: `()` must implement `Trait fn(Cell<&'b u32>)>` + --> $DIR/hrtb-exists-forall-trait-invariant.rs:12:8 + | +LL | fn foo() + | --- due to a where-clause on `foo` +LL | where +LL | T: Trait fn(Cell<&'b u32>)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-invariant.rs:16:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index 1f33e65e7e715..cdfcd30d44fb2 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -1,15 +1,16 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | fn want_hrtb() - | --------- due to a where-clause on `want_hrtb`... -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- unsatisfied where-clause on `want_hrtb` -... LL | want_hrtb::() | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... +note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + --> $DIR/hrtb-just-for-static.rs:9:15 + | +LL | fn want_hrtb() + | --------- due to a where-clause on `want_hrtb` +LL | where T : for<'a> Foo<&'a isize> + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_hrtb` note: ...but it actually implements `Foo<&'static isize>` --> $DIR/hrtb-just-for-static.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index 2b68dced8af0d..da60e78d2f389 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -56,16 +56,17 @@ LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 | -LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) - | ---------------- due to a where-clause on `foo_hrtb_bar_not`... -LL | where -LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, - | ---------------------- unsatisfied where-clause on `foo_hrtb_bar_not` -... LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... +note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + --> $DIR/hrtb-perfect-forwarding.rs:37:8 + | +LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) + | ---------------- due to a where-clause on `foo_hrtb_bar_not` +LL | where +LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo_hrtb_bar_not` note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` --> $DIR/hrtb-perfect-forwarding.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr index e1d900f20ce3b..23cba27a2fc00 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr @@ -1,15 +1,16 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-46989.rs:38:5 | -LL | fn assert_foo() {} - | ---------- --- unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo`... -... LL | assert_foo::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` +note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` + --> $DIR/issue-46989.rs:35:18 + | +LL | fn assert_foo() {} + | ---------- ^^^ unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index f7b72ec65db3f..9145a693c95c8 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -1,31 +1,33 @@ error: implementation of `Trait` is not general enough --> $DIR/issue-59311.rs:17:5 | -LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash`... -LL | where -LL | for<'a> &'a V: Trait + 'static, - | ----- unsatisfied where-clause on `crash` -LL | { LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: ...`Trait` would have to be implemented for the type `&'a V` +note: `Trait` would have to be implemented for the type `&'a V` + --> $DIR/issue-59311.rs:15:20 + | +LL | pub fn crash(v: &V) + | ----- due to a where-clause on `crash` +LL | where +LL | for<'a> &'a V: Trait + 'static, + | ^^^^^ unsatisfied where-clause on `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` error: implementation of `Trait` is not general enough --> $DIR/issue-59311.rs:17:5 | -LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash`... -LL | where -LL | for<'a> &'a V: Trait + 'static, - | ----- unsatisfied where-clause on `crash` -LL | { LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: ...`Trait` would have to be implemented for the type `&'a V` +note: `Trait` would have to be implemented for the type `&'a V` + --> $DIR/issue-59311.rs:15:20 + | +LL | pub fn crash(v: &V) + | ----- due to a where-clause on `crash` +LL | where +LL | for<'a> &'a V: Trait + 'static, + | ^^^^^ unsatisfied where-clause on `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr index 83a7a9836a1ad..6dd203ac806e5 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr @@ -1,16 +1,17 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:47:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---------------------------------------------------------- unsatisfied where-clause on `foo` -... LL | foo(bar, |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:9 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -20,16 +21,17 @@ LL | foo(bar, |s: &'b &'c str| s.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:47:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---- unsatisfied where-clause on `foo` -... LL | foo(bar, |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:63 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -39,16 +41,17 @@ LL | foo(bar, |s: &'b &'c str| s.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:50:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---------------------------------------------------------- unsatisfied where-clause on `foo` -... LL | foo(baz, |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:9 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -58,16 +61,17 @@ LL | foo(baz, |s: &'b Wrapper<'c>| s.0.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:50:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---- unsatisfied where-clause on `foo` -... LL | foo(baz, |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:63 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 18960ff575a2a..995c3604ca6e0 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding explicit type annotations to the closure's arguments | @@ -19,15 +20,16 @@ LL | let f = | _: &u32 , y: &u32 , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding explicit type annotations to the closure's arguments @@ -38,15 +40,16 @@ LL | let f = | _: &u32 , y: &u32 , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -56,15 +59,16 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -74,15 +78,16 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -93,15 +98,16 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 7029eeafef0eb..4b2799812fe90 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187-2.rs:8:5 | -LL | fn take_foo(_: impl Foo) {} - | -------- --- unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo`... -... LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | -------- ^^^ unsatisfied where-clause on `take_foo` + | | + | due to a where-clause on `take_foo` = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | take_foo(|a: &i32| a); error: implementation of `Fn` is not general enough --> $DIR/issue-79187-2.rs:8:5 | -LL | fn take_foo(_: impl Foo) {} - | -------- --- unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo`... -... LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | -------- ^^^ unsatisfied where-clause on `take_foo` + | | + | due to a where-clause on `take_foo` = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 3dbb6054a7ad3..2377c4d5ba5f3 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ------------ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | let f = |_: &u32| (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ------------ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 3a293cc4b2516..5670dc4ea00f7 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -45,27 +45,29 @@ LL | fn g(data: &[T]) { error: implementation of `Fn` is not general enough --> $DIR/issue_74400.rs:12:5 | -LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - ----------- unsatisfied where-clause on `f` - | | - | due to a where-clause on `f`... -... LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ | - = note: ...`fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... +note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... + --> $DIR/issue_74400.rs:8:34 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | - ^^^^^^^^^^^ unsatisfied where-clause on `f` + | | + | due to a where-clause on `f` = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 | -LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - due to a where-clause on `f`... - unsatisfied where-clause on `f` -... LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ | - = note: ...`fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... +note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... + --> $DIR/issue_74400.rs:8:44 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | - due to a where-clause on `f` ^ unsatisfied where-clause on `f` = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 856aba98d1c4c..72945d962a570 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -66,29 +66,31 @@ LL | fn baz(_: F) {} error: implementation of `Fn` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | --- ------------- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^^^^ | - = note: ...`fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... +note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | --- ------------- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^^^^ | - = note: ...`fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... +note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 6 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 0dbefa4b2aa19..0249537dcba54 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:12:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|_| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | baz(|_: &()| ()); error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:12:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|_| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -37,15 +39,16 @@ LL | baz(|_: &()| ()); error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:16:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|x| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -55,15 +58,16 @@ LL | baz(|x: &()| ()); error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:16:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|x| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 60f155eb45eb1..5e60b16903b82 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -3,13 +3,14 @@ error: implementation of `FnOnce` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + | due to a where-clause on `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` help: consider adding an explicit type annotation to the closure's argument | @@ -21,13 +22,14 @@ error: implementation of `FnOnce` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + | due to a where-clause on `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -81,14 +83,13 @@ error: implementation of `FnOnce` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: due to a where-clause on `Rc`... + = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | = note: unsatisfied where-clause on `Rc` - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -101,14 +102,13 @@ error: implementation of `Fn` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: due to a where-clause on `Rc`... + = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | = note: unsatisfied where-clause on `Rc` - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -120,13 +120,14 @@ error: implementation of `FnOnce` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + | due to a where-clause on `B` = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -138,13 +139,14 @@ error: implementation of `Fn` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + | due to a where-clause on `B` = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 4c5535258f624..8d45fc4db9c69 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -1,49 +1,53 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index f0f407afd7601..74e240122aa70 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | fn accept(_: C) -> Handshake> { - | ------ ----------- unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:27:14 + | +LL | fn accept(_: C) -> Handshake> { + | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` + | | + | due to a where-clause on `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | fn accept(_: C) -> Handshake> { - | ------ ----------- unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:27:14 + | +LL | fn accept(_: C) -> Handshake> { + | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` + | | + | due to a where-clause on `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -38,15 +40,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | struct Handshake { - | --------- ---- unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:20:21 + | +LL | struct Handshake { + | --------- ^^^^ unsatisfied where-clause on `Handshake` + | | + | due to a where-clause on `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -56,15 +59,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | struct Handshake { - | --------- ---- unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:20:21 + | +LL | struct Handshake { + | --------- ^^^^ unsatisfied where-clause on `Handshake` + | | + | due to a where-clause on `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 2e164c9b3abb7..4538c51a2bb52 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -29,13 +29,14 @@ error: implementation of `Fn` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 + | LL | fn bad &()>(_: F) {} - | --- -------------- unsatisfied where-clause on `bad` + | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -47,13 +48,14 @@ error: implementation of `FnOnce` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 + | LL | fn bad &()>(_: F) {} - | --- --- unsatisfied where-clause on `bad` + | --- ^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 2e164c9b3abb7..4538c51a2bb52 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -29,13 +29,14 @@ error: implementation of `Fn` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 + | LL | fn bad &()>(_: F) {} - | --- -------------- unsatisfied where-clause on `bad` + | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -47,13 +48,14 @@ error: implementation of `FnOnce` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 + | LL | fn bad &()>(_: F) {} - | --- --- unsatisfied where-clause on `bad` + | --- ^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index ced5c4b8058b0..e03e0cd465158 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -1,25 +1,27 @@ error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 | -LL | fn make_f() -> Self::F; - | ------ due to a where-clause on `Y::make_f`... -... LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Y::make_f` + | ^^^^^^^^^^^^^^^^^^^ + | +note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:18:8 | - = note: ...`Y` would have to be implemented for the type `for<'a> fn(&'a ())` +LL | fn make_f() -> Self::F; + | ^^^^^^ due to a where-clause on `Y::make_f` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 | -LL | trait Y { - | - due to a where-clause on `Y`... -... LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Y` + | ^^^^^^^^^^^^^^^^^^^ + | +note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:16:7 | - = note: ...`Y` would have to be implemented for the type `for<'a> fn(&'a ())` +LL | trait Y { + | ^ due to a where-clause on `Y` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index fa61b3af02cf0..5d5d712c6e3e4 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-30906.rs:18:5 | -LL | fn test FnOnce<(&'x str,)>>(_: F) {} - | ---- -------------------------- unsatisfied where-clause on `test` - | | - | due to a where-clause on `test`... -... LL | test(Compose(f, |_| {})); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... +note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... + --> $DIR/issue-30906.rs:3:12 + | +LL | fn test FnOnce<(&'x str,)>>(_: F) {} + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` + | | + | due to a where-clause on `test` = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr index 378616d9aca57..7c7af181f601b 100644 --- a/tests/ui/where-clauses/where-for-self-2.stderr +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -1,16 +1,17 @@ error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:23:5 | -LL | fn foo(x: &T) - | --- due to a where-clause on `foo`... -LL | where -LL | for<'a> &'a T: Bar, - | --- unsatisfied where-clause on `foo` -... LL | foo(&X); | ^^^^^^^ | - = note: ...`&'0 u32` must implement `Bar`, for any lifetime `'0`... +note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + --> $DIR/where-for-self-2.rs:18:20 + | +LL | fn foo(x: &T) + | --- due to a where-clause on `foo` +LL | where +LL | for<'a> &'a T: Bar, + | ^^^ unsatisfied where-clause on `foo` = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to 1 previous error From cf56d126fd0befc4fbccb2cba8eaac1d06a2bb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:09:47 +0000 Subject: [PATCH 24/31] Tweak wording --- .../rustc_trait_selection/src/diagnostics.rs | 6 ++--- .../nice_region_error/placeholder_error.rs | 8 +++++-- .../associated-types-eq-hr.stderr | 24 +++++++------------ ...outine-auto-trait-span-issue-155880.stderr | 4 +--- ...olved-typeck-results.no_assumptions.stderr | 8 ++----- ...ranked-auto-trait-12.no_assumptions.stderr | 4 +--- ...er-ranked-auto-trait-13.assumptions.stderr | 16 ++++--------- ...ranked-auto-trait-13.no_assumptions.stderr | 24 +++++-------------- ...ranked-auto-trait-15.no_assumptions.stderr | 8 ++----- ...er-ranked-auto-trait-16.assumptions.stderr | 8 ++----- ...ranked-auto-trait-16.no_assumptions.stderr | 8 ++----- ...-ranked-auto-trait-5.no_assumptions.stderr | 3 +-- .../issue-110963-early.no_assumptions.stderr | 6 ++--- ...ation-not-general-enough-ice-133252.stderr | 4 +--- ...n-with-leaking-placeholders.current.stderr | 3 +-- ...rtb-closure-suggest-type-annotation.stderr | 6 ++--- tests/ui/coroutine/auto-trait-regions.stderr | 8 ++----- .../ui/coroutine/resume-arg-late-bound.stderr | 4 +--- ...ot-checked-with-right-substitutions.stderr | 4 +--- ...hr-fn-ptr-trait-impl-mismatch-29061.stderr | 12 +++------- ...tb-associated-type-leak-check-55731.stderr | 3 +-- ...n-ptr-impl-not-general-enough-57936.stderr | 4 +--- .../trait-bounds/hrtb-conflate-regions.stderr | 6 ++--- ...b-exists-forall-trait-contravariant.stderr | 3 +-- .../hrtb-exists-forall-trait-covariant.stderr | 3 +-- .../hrtb-exists-forall-trait-invariant.stderr | 3 +-- .../trait-bounds/hrtb-just-for-static.stderr | 3 +-- .../hrtb-perfect-forwarding.stderr | 3 +-- .../trait-bounds/issue-46989.stderr | 4 +--- .../trait-bounds/issue-59311.stderr | 6 ++--- .../issue-71955.current.stderr | 12 ++++------ tests/ui/lifetimes/issue-105675.stderr | 24 +++++-------------- tests/ui/lifetimes/issue-79187-2.stderr | 8 ++----- tests/ui/lifetimes/issue-79187.stderr | 8 ++----- .../lifetime-errors/issue_74400.stderr | 6 ++--- .../closure-arg-type-mismatch.stderr | 8 ++----- .../closure-mismatch.current.stderr | 16 ++++--------- tests/ui/nll/ice-106874.stderr | 24 +++++-------------- tests/ui/nll/issue-54302-cases.stderr | 8 +++---- ...missing-universe-cause-issue-114907.stderr | 16 ++++--------- ...insensitive-scopes-issue-117146.nll.stderr | 8 ++----- ...sitive-scopes-issue-117146.polonius.stderr | 8 ++----- .../impl-fn-ignore-binder-via-bottom.stderr | 4 ++-- tests/ui/unboxed-closures/issue-30906.stderr | 4 +--- .../ui/where-clauses/where-for-self-2.stderr | 3 +-- 45 files changed, 107 insertions(+), 256 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 9d2238c188157..72b57c6af99d5 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1096,17 +1096,17 @@ impl<'tcx> ActualImplExplNotes<'tcx> { item_span: Option, item_name: String, ) -> Self { - let label = format!("unsatisfied where-clause on `{item_name}`"); - let item_label = format!("due to a where-clause on `{item_name}`"); + let label = format!("required by this bound in `{item_name}`"); let span = match (satisfy_span, item_span) { (Some(satisfy_span), Some(item_span)) => { let mut span = MultiSpan::from(satisfy_span); span.push_span_label(satisfy_span, label); - span.push_span_label(item_span, item_label); + span.push_span_context(item_span); span } (None, Some(item_span)) => { let mut span = MultiSpan::from(item_span); + let item_label = format!("required due to a bound in `{item_name}`"); span.push_span_label(item_span, item_label); span } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 1b57e3d77d503..9cf38a23bf295 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -297,10 +297,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } else { (None, None, Some(span), String::new()) }; - if let Some(span) = satisfy_span && span.is_dummy() { + if let Some(span) = satisfy_span + && span.is_dummy() + { satisfy_span = None; } - if let Some(span) = item_span && span.is_dummy() { + if let Some(span) = item_span + && span.is_dummy() + { item_span = None; } diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 19fd633334f00..4f85111897df5 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -50,10 +50,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:8 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -70,10 +69,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:8 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -91,10 +89,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:53 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -111,10 +108,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:53 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -132,10 +128,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:66:8 | LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -152,10 +147,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:66:8 | LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -202,10 +196,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:80:8 | LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -222,10 +215,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:80:8 | LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr index 893124920ee18..3bdb318678d92 100644 --- a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr @@ -14,9 +14,7 @@ note: `Send` would have to be implemented for the type `&'0 u32`, for any lifeti --> $DIR/coroutine-auto-trait-span-issue-155880.rs:25:15 | LL | fn is_send(_: T) {} - | ------- ^^^^ unsatisfied where-clause on `is_send` - | | - | due to a where-clause on `is_send` + | ^^^^ required by this bound in `is_send` = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr index da93d5a17547a..a5f148ae0ca76 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr @@ -10,9 +10,7 @@ note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implemen --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 | LL | fn send(_: T) {} - | ---- ^^^^ unsatisfied where-clause on `send` - | | - | due to a where-clause on `send` + | ^^^^ required by this bound in `send` = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough @@ -27,9 +25,7 @@ note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implemen --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 | LL | fn send(_: T) {} - | ---- ^^^^ unsatisfied where-clause on `send` - | | - | due to a where-clause on `send` + | ^^^^ required by this bound in `send` = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr index 39132cc9b4fb9..a55e42b4b6dfb 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr @@ -15,9 +15,7 @@ note: `Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any l --> $DIR/higher-ranked-auto-trait-12.rs:24:20 | LL | fn this_is_send(value: T) -> T { - | ------------ ^^^^ unsatisfied where-clause on `this_is_send` - | | - | due to a where-clause on `this_is_send` + | ^^^^ required by this bound in `this_is_send` = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot + Send + 'static)>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr index 386a83ebbc761..63eef87aa2517 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr @@ -8,9 +8,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -23,9 +21,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -39,9 +35,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -54,9 +48,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr index 02f91c47fffcb..9d89d73270f71 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -8,9 +8,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -23,9 +21,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -39,9 +35,7 @@ note: `Callable<'_>` would have to be implemented for the type `ConstructableImp --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: implementation of `Getter` is not general enough @@ -54,9 +48,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -69,9 +61,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -85,9 +75,7 @@ note: `Callable<'_>` would have to be implemented for the type `ConstructableImp --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: aborting due to 6 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr index c6c8479474c64..94a187f69c91f 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce --> $DIR/higher-ranked-auto-trait-15.rs:16:20 | LL | fn require_send(_x: T) {} - | ------------ ^^^^ unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send` + | ^^^^ required by this bound in `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce --> $DIR/higher-ranked-auto-trait-15.rs:16:20 | LL | fn require_send(_x: T) {} - | ------------ ^^^^ unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send` + | ^^^^ required by this bound in `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr index 52c54f8355c39..ff7a3230aa6c9 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr @@ -10,9 +10,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough @@ -27,9 +25,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr index 52c54f8355c39..ff7a3230aa6c9 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr @@ -10,9 +10,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough @@ -27,9 +25,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr index 6119247429e28..a95fd2179322f 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -10,10 +10,9 @@ note: `Send` would have to be implemented for the type `&'0 str`, for any lifeti --> $DIR/higher-ranked-auto-trait-5.rs:20:17 | LL | pub fn assert_send(_future: F) - | ----------- due to a where-clause on `assert_send` LL | where LL | F: Future + Send, - | ^^^^ unsatisfied where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr index 889d3c2948d61..63f44d676882d 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -16,10 +16,9 @@ note: `Send` would have to be implemented for the type `impl Future $DIR/issue-110963-early.rs:37:17 | LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn` LL | where LL | F: Future + Send + 'static, - | ^^^^ unsatisfied where-clause on `spawn` + | ^^^^ required by this bound in `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` error: implementation of `Send` is not general enough @@ -40,10 +39,9 @@ note: `Send` would have to be implemented for the type `impl Future $DIR/issue-110963-early.rs:37:17 | LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn` LL | where LL | F: Future + Send + 'static, - | ^^^^ unsatisfied where-clause on `spawn` + | ^^^^ required by this bound in `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr index beb349c94bd1a..f1a561ef88049 100644 --- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr +++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr @@ -8,9 +8,7 @@ note: `LoadQuery<'0>` would have to be implemented for the type `&u8`, for any l --> $DIR/implementation-not-general-enough-ice-133252.rs:16:18 | LL | fn force_send(_: T) {} - | ---------- ^^^^ unsatisfied where-clause on `force_send` - | | - | due to a where-clause on `force_send` + | ^^^^ required by this bound in `force_send` = note: ...but `LoadQuery<'1>` is actually implemented for the type `&'1 u8`, for some specific lifetime `'1` error[E0597]: `not_static` does not live long enough diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index 5f8198ec6bed9..d8453534d0636 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -12,10 +12,9 @@ note: `Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... --> $DIR/obligation-with-leaking-placeholders.rs:10:22 | LL | fn needs_foo(_: T) - | --------- due to a where-clause on `needs_foo` LL | where LL | for<'a> Wrap: Foo<'a>, - | ^^^^^^^ unsatisfied where-clause on `needs_foo` + | ^^^^^^^ required by this bound in `needs_foo` note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` --> $DIR/obligation-with-leaking-placeholders.rs:15:1 | diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr index 5f7636bb34a0e..a8382f3dc4d76 100644 --- a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr @@ -8,10 +8,9 @@ note: closure with signature `fn(&'2 mut [u8]) -> Result` must imp --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:8 | LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner` LL | where LL | F: FnOnce(&mut [u8]) -> Result, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -28,10 +27,9 @@ note: closure with signature `fn(&'2 mut [u8]) -> Result` must imp --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:29 | LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner` LL | where LL | F: FnOnce(&mut [u8]) -> Result, - | ^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index 25f6373124d34..ea2b5cc18cda3 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -11,9 +11,7 @@ note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... --> $DIR/auto-trait-regions.rs:21:18 | LL | fn assert_foo(f: T) {} - | ---------- ^^^ unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo` + | ^^^ required by this bound in `assert_foo` = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error[E0626]: borrow may still be in use when coroutine yields @@ -61,9 +59,7 @@ note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two l --> $DIR/auto-trait-regions.rs:21:18 | LL | fn assert_foo(f: T) {} - | ---------- ^^^ unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo` + | ^^^ required by this bound in `assert_foo` = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index b44a8e363128f..9211256766669 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -8,9 +8,7 @@ note: `{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifeti --> $DIR/resume-arg-late-bound.rs:8:17 | LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` - | | - | due to a where-clause on `test` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test` = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index 92d39c70137ce..de0882fb665d2 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -8,9 +8,7 @@ note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, f --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 | LL | type Gat<'a>: for<'b> Lengthen>; - | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Gat::Gat` - | | - | due to a where-clause on `Gat::Gat` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` note: required by a bound in `Gat::Gat` --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 diff --git a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr index 16c1b69d3b053..9e5de5e6fb61b 100644 --- a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr +++ b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr @@ -8,9 +8,7 @@ note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some spec --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:15:10 | LL | fn hr(_: T) {} - | -- ^^ unsatisfied where-clause on `hr` - | | - | due to a where-clause on `hr` + | ^^ required by this bound in `hr` = note: ...but `HR` is actually implemented for the type `for<'a> fn(&'a ())` error: implementation of `NotHR` is not general enough @@ -23,9 +21,7 @@ note: `NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 | LL | fn not_hr(_: T) {} - | ------ ^^^^^ unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr` + | ^^^^^ required by this bound in `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `NotHR` is not general enough @@ -38,9 +34,7 @@ note: `NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 | LL | fn not_hr(_: T) {} - | ------ ^^^^^ unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr` + | ^^^^^ required by this bound in `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 3 previous errors diff --git a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr index d3e10e7a18d20..53586decee2c5 100644 --- a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr +++ b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr @@ -11,10 +11,9 @@ note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the ty --> $DIR/hrtb-associated-type-leak-check-55731.rs:43:8 | LL | fn multi(_reducer: I) - | ----- due to a where-clause on `multi` LL | where LL | I: for<'a> DistributedIteratorMulti<&'a ()>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `multi` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `multi` = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr index f7a9020c59e24..f9862b8ab13a4 100644 --- a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr +++ b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr @@ -21,9 +21,7 @@ note: `X` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:21:16 | LL | fn indirect() { - | -------- ^ unsatisfied where-clause on `indirect` - | | - | due to a where-clause on `indirect` + | ^ required by this bound in `indirect` = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 6700778198712..0946314f31e80 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -8,9 +8,8 @@ note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/hrtb-conflate-regions.rs:9:15 | LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2` LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | @@ -27,9 +26,8 @@ note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/hrtb-conflate-regions.rs:9:15 | LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2` LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index e600c49d564be..8ec6646e73074 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -8,10 +8,9 @@ note: `()` must implement `Trait fn(&'b u32)>` --> $DIR/hrtb-exists-forall-trait-contravariant.rs:10:8 | LL | fn foo() - | --- due to a where-clause on `foo` LL | where LL | T: Trait fn(&'b u32)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-contravariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index dd720d9989060..4beade083b781 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -8,10 +8,9 @@ note: `()` must implement `Trait fn(fn(&'b u32))>` --> $DIR/hrtb-exists-forall-trait-covariant.rs:10:8 | LL | fn foo() - | --- due to a where-clause on `foo` LL | where LL | T: Trait fn(fn(&'b u32))>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-covariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index 446a3102a0938..691d5499bc175 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -8,10 +8,9 @@ note: `()` must implement `Trait fn(Cell<&'b u32>)>` --> $DIR/hrtb-exists-forall-trait-invariant.rs:12:8 | LL | fn foo() - | --- due to a where-clause on `foo` LL | where LL | T: Trait fn(Cell<&'b u32>)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-invariant.rs:16:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index cdfcd30d44fb2..8e224e3447205 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -8,9 +8,8 @@ note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... --> $DIR/hrtb-just-for-static.rs:9:15 | LL | fn want_hrtb() - | --------- due to a where-clause on `want_hrtb` LL | where T : for<'a> Foo<&'a isize> - | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_hrtb` + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `want_hrtb` note: ...but it actually implements `Foo<&'static isize>` --> $DIR/hrtb-just-for-static.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index da60e78d2f389..b1d725f896cf2 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -63,10 +63,9 @@ note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... --> $DIR/hrtb-perfect-forwarding.rs:37:8 | LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) - | ---------------- due to a where-clause on `foo_hrtb_bar_not` LL | where LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, - | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo_hrtb_bar_not` + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo_hrtb_bar_not` note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` --> $DIR/hrtb-perfect-forwarding.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr index 23cba27a2fc00..0592e9e149f00 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr @@ -8,9 +8,7 @@ note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` --> $DIR/issue-46989.rs:35:18 | LL | fn assert_foo() {} - | ---------- ^^^ unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo` + | ^^^ required by this bound in `assert_foo` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index 9145a693c95c8..d53ff3b080da5 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -8,10 +8,9 @@ note: `Trait` would have to be implemented for the type `&'a V` --> $DIR/issue-59311.rs:15:20 | LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash` LL | where LL | for<'a> &'a V: Trait + 'static, - | ^^^^^ unsatisfied where-clause on `crash` + | ^^^^^ required by this bound in `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` error: implementation of `Trait` is not general enough @@ -24,10 +23,9 @@ note: `Trait` would have to be implemented for the type `&'a V` --> $DIR/issue-59311.rs:15:20 | LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash` LL | where LL | for<'a> &'a V: Trait + 'static, - | ^^^^^ unsatisfied where-clause on `crash` + | ^^^^^ required by this bound in `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr index 6dd203ac806e5..2c35e1c853911 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr @@ -8,10 +8,9 @@ note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `F --> $DIR/issue-71955.rs:32:9 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -28,10 +27,9 @@ note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `F --> $DIR/issue-71955.rs:32:63 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^ unsatisfied where-clause on `foo` + | ^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -48,10 +46,9 @@ note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implemen --> $DIR/issue-71955.rs:32:9 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -68,10 +65,9 @@ note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implemen --> $DIR/issue-71955.rs:32:63 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^ unsatisfied where-clause on `foo` + | ^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 995c3604ca6e0..0c7c8f97de726 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -8,9 +8,7 @@ note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding explicit type annotations to the closure's arguments | @@ -27,9 +25,7 @@ note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding explicit type annotations to the closure's arguments @@ -47,9 +43,7 @@ note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&' --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -66,9 +60,7 @@ note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -85,9 +77,7 @@ note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&' --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -105,9 +95,7 @@ note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 4b2799812fe90..adc64984a05e9 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i --> $DIR/issue-79187-2.rs:5:21 | LL | fn take_foo(_: impl Foo) {} - | -------- ^^^ unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo` + | ^^^ required by this bound in `take_foo` = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,) --> $DIR/issue-79187-2.rs:5:21 | LL | fn take_foo(_: impl Foo) {} - | -------- ^^^ unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo` + | ^^^ required by this bound in `take_foo` = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 2377c4d5ba5f3..5e9602f80baf1 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, --> $DIR/issue-79187.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, --> $DIR/issue-79187.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 5670dc4ea00f7..d9df584bebf73 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -52,9 +52,7 @@ note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, fo --> $DIR/issue_74400.rs:8:34 | LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - ^^^^^^^^^^^ unsatisfied where-clause on `f` - | | - | due to a where-clause on `f` + | ^^^^^^^^^^^ required by this bound in `f` = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough @@ -67,7 +65,7 @@ note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>` --> $DIR/issue_74400.rs:8:44 | LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - due to a where-clause on `f` ^ unsatisfied where-clause on `f` + | ^ required by this bound in `f` = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 72945d962a570..15c37059416af 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -73,9 +73,7 @@ note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime --> $DIR/closure-arg-type-mismatch.rs:8:11 | LL | fn baz(_: F) {} - | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^^^^^^^^^^^ required by this bound in `baz` = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough @@ -88,9 +86,7 @@ note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifet --> $DIR/closure-arg-type-mismatch.rs:8:11 | LL | fn baz(_: F) {} - | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^^^^^^^^^^^ required by this bound in `baz` = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 6 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 0249537dcba54..ad734c4e77ea6 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for an --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -46,9 +42,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -65,9 +59,7 @@ note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for an --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 5e60b16903b82..0b756a1795f8a 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -85,11 +81,9 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL - | - = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: unsatisfied where-clause on `Rc` + = note: required by this bound in `Rc` = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -104,11 +98,9 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL - | - = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: unsatisfied where-clause on `Rc` + = note: required by this bound in `Rc` = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -125,9 +117,7 @@ note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,) --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -144,9 +134,7 @@ note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 8d45fc4db9c69..0ebd0293eccca 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -8,7 +8,7 @@ note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough @@ -21,7 +21,7 @@ note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough @@ -34,7 +34,7 @@ note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough @@ -47,7 +47,7 @@ note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index 74e240122aa70..c9b5eb8230a0f 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:27:14 | LL | fn accept(_: C) -> Handshake> { - | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept` + | ^^^^^^^^^^^ required by this bound in `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:27:14 | LL | fn accept(_: C) -> Handshake> { - | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept` + | ^^^^^^^^^^^ required by this bound in `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -47,9 +43,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:20:21 | LL | struct Handshake { - | --------- ^^^^ unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake` + | ^^^^ required by this bound in `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -66,9 +60,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:20:21 | LL | struct Handshake { - | --------- ^^^^ unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake` + | ^^^^ required by this bound in `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 4538c51a2bb52..3c1beb5021af8 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -34,9 +34,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 | LL | fn bad &()>(_: F) {} - | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^^^^^^^^^^^^ required by this bound in `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -53,9 +51,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (), --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 | LL | fn bad &()>(_: F) {} - | --- ^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^ required by this bound in `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 4538c51a2bb52..3c1beb5021af8 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -34,9 +34,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 | LL | fn bad &()>(_: F) {} - | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^^^^^^^^^^^^ required by this bound in `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -53,9 +51,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (), --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 | LL | fn bad &()>(_: F) {} - | --- ^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^ required by this bound in `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index e03e0cd465158..1917b5ca9cea1 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -8,7 +8,7 @@ note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/impl-fn-ignore-binder-via-bottom.rs:18:8 | LL | fn make_f() -> Self::F; - | ^^^^^^ due to a where-clause on `Y::make_f` + | ^^^^^^ required due to a bound in `Y::make_f` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough @@ -21,7 +21,7 @@ note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/impl-fn-ignore-binder-via-bottom.rs:16:7 | LL | trait Y { - | ^ due to a where-clause on `Y` + | ^ required due to a bound in `Y` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index 5d5d712c6e3e4..252ee8d85da9d 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -8,9 +8,7 @@ note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime ` --> $DIR/issue-30906.rs:3:12 | LL | fn test FnOnce<(&'x str,)>>(_: F) {} - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` - | | - | due to a where-clause on `test` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test` = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr index 7c7af181f601b..1b172f2a57f3c 100644 --- a/tests/ui/where-clauses/where-for-self-2.stderr +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -8,10 +8,9 @@ note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... --> $DIR/where-for-self-2.rs:18:20 | LL | fn foo(x: &T) - | --- due to a where-clause on `foo` LL | where LL | for<'a> &'a T: Bar, - | ^^^ unsatisfied where-clause on `foo` + | ^^^ required by this bound in `foo` = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to 1 previous error From ca762cfe3b4d9112389a92b25a3755adbe6f78d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:14:38 +0000 Subject: [PATCH 25/31] Remove redundant information --- .../nice_region_error/placeholder_error.rs | 24 ++++++++++++------- ...ot-checked-with-right-substitutions.stderr | 6 ----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 9cf38a23bf295..1cecc2c5de448 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -393,15 +393,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut current_code = cause.code(); let mut coroutine_def_id = None; if cause.body_def_id != CRATE_DEF_ID { - self.cx.note_obligation_cause_code( - cause.body_def_id, - &mut err, - actual_trait_ref, - self.tcx().param_env(cause.body_def_id), - cause.code(), - &mut vec![], - &mut Default::default(), - ); + if let ObligationCauseCode::WhereClause(..) + | ObligationCauseCode::WhereClauseInExpr(..) = *code + { + // Do not point at the same bound twice. + } else { + self.cx.note_obligation_cause_code( + cause.body_def_id, + &mut err, + actual_trait_ref, + self.tcx().param_env(cause.body_def_id), + cause.code(), + &mut vec![], + &mut Default::default(), + ); + } } loop { diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index de0882fb665d2..fe84512e6f12e 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -10,12 +10,6 @@ note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, f LL | type Gat<'a>: for<'b> Lengthen>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` -note: required by a bound in `Gat::Gat` - --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 - | -LL | trait Gat { -LL | type Gat<'a>: for<'b> Lengthen>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` error: aborting due to 1 previous error From 337f98dd5582fdc1552bc76df6060a18f00f9145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:21:26 +0000 Subject: [PATCH 26/31] Tweak note to include trait/impl when appropriate ``` error: implementation of `Lengthen` is not general enough --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 | LL | type Gat<'a> = &'a str; | ^^^^^^^ | note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 | LL | trait Gat { LL | type Gat<'a>: for<'b> Lengthen>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` ``` --- compiler/rustc_trait_selection/src/diagnostics.rs | 6 +++++- .../infer/nice_region_error/placeholder_error.rs | 15 ++++++++++++--- ...ds-not-checked-with-right-substitutions.stderr | 1 + tests/ui/nll/issue-54302-cases.stderr | 4 ++++ .../impl-fn-ignore-binder-via-bottom.stderr | 2 ++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 72b57c6af99d5..d453b3c809860 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1094,10 +1094,11 @@ impl<'tcx> ActualImplExplNotes<'tcx> { lifetime_2: usize, satisfy_span: Option, item_span: Option, + outer_span: Option, item_name: String, ) -> Self { let label = format!("required by this bound in `{item_name}`"); - let span = match (satisfy_span, item_span) { + let mut span = match (satisfy_span, item_span) { (Some(satisfy_span), Some(item_span)) => { let mut span = MultiSpan::from(satisfy_span); span.push_span_label(satisfy_span, label); @@ -1117,6 +1118,9 @@ impl<'tcx> ActualImplExplNotes<'tcx> { } _ => MultiSpan::from(vec![]), }; + if let Some(outer) = outer_span { + span.push_span_context(outer); + } match (kind, lt_kind) { (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { Self::ExpectedSignatureTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 1cecc2c5de448..fecf41c84a0e2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -3,7 +3,7 @@ use std::fmt; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, Diag, IntoDiagArg}; use rustc_hir as hir; -use rustc_hir::def::Namespace; +use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; @@ -279,11 +279,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { _ => break, } } - let (mut satisfy_span, mut item_span, dup_span, item_name) = + let (mut satisfy_span, mut item_span, outer_span, dup_span, item_name) = if let ObligationCauseCode::WhereClause(def_id, span) | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code && def_id != CRATE_DEF_ID.to_def_id() { + let parent = self.tcx().parent(def_id); ( Some(span), Some( @@ -291,11 +292,16 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { .opt_item_ident(def_id) .map_or_else(|| self.tcx().def_span(def_id), |n| n.span), ), + if let DefKind::Trait | DefKind::Impl { .. } = self.tcx().def_kind(parent) { + Some(self.tcx().def_span(parent).shrink_to_lo()) + } else { + None + }, None, self.tcx().def_path_str(def_id), ) } else { - (None, None, Some(span), String::new()) + (None, None, None, Some(span), String::new()) }; if let Some(span) = satisfy_span && span.is_dummy() @@ -380,6 +386,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { any_self_ty_has_vid, satisfy_span, item_span, + outer_span, item_name, ); @@ -510,6 +517,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { any_self_ty_has_vid: bool, satisfy_span: Option, item_span: Option, + outer_span: Option, item_name: String, ) -> Vec> { // The weird thing here with the `maybe_highlighting_region` calls and the @@ -614,6 +622,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { lifetime_2, satisfy_span, item_span, + outer_span, item_name, ); diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index fe84512e6f12e..9e56955aff17b 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -7,6 +7,7 @@ LL | type Gat<'a> = &'a str; note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 | +LL | trait Gat { LL | type Gat<'a>: for<'b> Lengthen>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 0ebd0293eccca..78acd3d640eef 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -7,6 +7,7 @@ LL | >::ref_foo(a) note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` @@ -20,6 +21,7 @@ LL | >::ref_foo(a) note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` @@ -33,6 +35,7 @@ LL | >::ref_foo(a) note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` @@ -46,6 +49,7 @@ LL | >::ref_foo(a) note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 1917b5ca9cea1..af896df38aa49 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -7,6 +7,8 @@ LL | let _x = ::make_f(); note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/impl-fn-ignore-binder-via-bottom.rs:18:8 | +LL | trait Y { +LL | type F; LL | fn make_f() -> Self::F; | ^^^^^^ required due to a bound in `Y::make_f` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` From f296fdf92ad3252d0d33e8e4a06a5ca0cb2c5d31 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 3 Oct 2026 20:07:41 +0200 Subject: [PATCH 27/31] implement FCW for `rustc_allowed_through_unstable_modules` items --- compiler/rustc_lint_defs/src/builtin.rs | 26 ++ compiler/rustc_passes/src/stability.rs | 6 +- .../clippy/tests/ui/std_instead_of_core.fixed | 2 +- .../clippy/tests/ui/std_instead_of_core.rs | 2 +- .../tests/ui/std_instead_of_core.stderr | 26 +- .../accidental-stable-in-unstable.rs | 3 +- .../accidental-stable-in-unstable.stderr | 24 +- .../accidentally-stable-intrinsics.fixed | 12 +- .../accidentally-stable-intrinsics.rs | 12 +- .../accidentally-stable-intrinsics.stderr | 224 ++++++++++++++++-- .../allowed-through-unstable.rs | 3 +- .../allowed-through-unstable.stderr | 30 ++- .../issue-99286-stable-intrinsics.rs | 2 +- .../issue-99286-stable-intrinsics.stderr | 90 +++++++ 14 files changed, 419 insertions(+), 43 deletions(-) create mode 100644 tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a722f0e103ea1..34c7e3f19a631 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -137,6 +137,7 @@ pub mod hardwired { UNREACHABLE_PATTERNS, UNSAFE_ATTR_OUTSIDE_UNSAFE, UNSAFE_OP_IN_UNSAFE_FN, + UNSTABLE_IMPORTS, UNSTABLE_NAME_COLLISIONS, UNSTABLE_SYNTAX_PRE_EXPANSION, UNSUPPORTED_CALLING_CONVENTIONS, @@ -5857,3 +5858,28 @@ declare_lint! { "`repr(C, align)` types nested inside `repr(C, packed)` types \ do not always have a C-compatible layout", } + +declare_lint! { + /// The `unstable_imports` lints detects imports that go through unstable modules. + /// + /// ### Example + /// + /// ```rust + /// use core::intrinsics::transmute; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust accidentally allowed certain imports through unstable modules + /// because stability information of modules was not correctly accounted for if the imported + /// item was stable itself. + pub UNSTABLE_IMPORTS, + Deny, + "lints on accidentally allowed unstable imports", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError # 163160), + report_in_deps: true, + }; +} diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index d607d929b0db6..162914c95c0e5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -19,8 +19,8 @@ use rustc_hir::{ UsePath, Variant, }; use rustc_lint_defs::builtin::{ - DEPRECATED, DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_REEXPORTS, - INEFFECTIVE_UNSTABLE_TRAIT_IMPL, STABLE_FEATURES, + DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_REEXPORTS, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, + STABLE_FEATURES, UNSTABLE_IMPORTS, }; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; @@ -1079,7 +1079,7 @@ impl<'tcx> Checker<'tcx> { suggestion, }; self.tcx.emit_node_span_lint( - DEPRECATED, + UNSTABLE_IMPORTS, id, method_span.unwrap_or(span), diag, diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed index c162dcb0451e2..208678a71cf35 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed +++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed @@ -1,7 +1,6 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::std_instead_of_core)] -#![expect(deprecated)] extern crate alloc; @@ -77,6 +76,7 @@ mod std_in_proc_macro_derive { // replacing std -> core fn intrinsic(a: *mut u8, b: *mut u8) { unsafe { + #[expect(unstable_imports)] core::intrinsics::copy(a, b, 1); //~^ std_instead_of_core } diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs index 6769af11def6f..8c27c1926fae4 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.rs +++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs @@ -1,7 +1,6 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::std_instead_of_core)] -#![expect(deprecated)] extern crate alloc; @@ -77,6 +76,7 @@ mod std_in_proc_macro_derive { // replacing std -> core fn intrinsic(a: *mut u8, b: *mut u8) { unsafe { + #[expect(unstable_imports)] std::intrinsics::copy(a, b, 1); //~^ std_instead_of_core } diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr index ae0783863fbc2..c18f976412611 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr +++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr @@ -1,5 +1,5 @@ error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:13:9 + --> tests/ui/std_instead_of_core.rs:12:9 | LL | use std::hash::Hasher; | ^^^ help: consider importing the item from `core`: `core` @@ -8,61 +8,61 @@ LL | use std::hash::Hasher; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:16:11 + --> tests/ui/std_instead_of_core.rs:15:11 | LL | use ::std::hash::Hash; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:22:9 + --> tests/ui/std_instead_of_core.rs:21:9 | LL | use std::fmt::{Debug, Result}; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:27:9 + --> tests/ui/std_instead_of_core.rs:26:9 | LL | use std::{ | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:34:15 + --> tests/ui/std_instead_of_core.rs:33:15 | LL | let ptr = std::ptr::null::(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:36:21 + --> tests/ui/std_instead_of_core.rs:35:21 | LL | let ptr_mut = ::std::ptr::null_mut::(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:40:16 + --> tests/ui/std_instead_of_core.rs:39:16 | LL | let cell = std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:42:27 + --> tests/ui/std_instead_of_core.rs:41:27 | LL | let cell_absolute = ::std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:47:9 + --> tests/ui/std_instead_of_core.rs:46:9 | LL | use std::error::Error; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:51:9 + --> tests/ui/std_instead_of_core.rs:50:9 | LL | use std::iter::Iterator; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:58:9 + --> tests/ui/std_instead_of_core.rs:57:9 | LL | use std::vec; | ^^^ help: consider importing the item from `alloc`: `alloc` @@ -71,13 +71,13 @@ LL | use std::vec; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:60:9 + --> tests/ui/std_instead_of_core.rs:59:9 | LL | use std::vec::Vec; | ^^^ help: consider importing the item from `alloc`: `alloc` error: used import from `alloc` instead of `core` - --> tests/ui/std_instead_of_core.rs:66:9 + --> tests/ui/std_instead_of_core.rs:65:9 | LL | use alloc::slice::from_ref; | ^^^^^ help: consider importing the item from `core`: `core` diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs index a36a78ee442ce..b52912938539e 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs @@ -8,4 +8,5 @@ use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature `u // Known accidental stabilizations with known users // fully stable @ core::mem::transmute use core::intrinsics::transmute; // depended upon by rand_core -//~^WARN deprecated +//~^ERROR use of deprecated import through accidentally stabilized module +//~| WARN previously accepted diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr index b0b1f78cb28b2..b2e8072101759 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -7,19 +7,37 @@ LL | use core::unicode::UNICODE_VERSION; = help: add `#![feature(unicode_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: use of deprecated import through accidentally stabilized module `intrinsics` +error: use of deprecated import through accidentally stabilized module `intrinsics` --> $DIR/accidental-stable-in-unstable.rs:10:5 | LL | use core::intrinsics::transmute; // depended upon by rand_core | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(deprecated)]` on by default + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default help: import this function via the `mem` module instead | LL - use core::intrinsics::transmute; // depended upon by rand_core LL + use core::mem::transmute; // depended upon by rand_core | -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. +Future incompatibility report: Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidental-stable-in-unstable.rs:10:5 + | +LL | use core::intrinsics::transmute; // depended upon by rand_core + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `mem` module instead + | +LL - use core::intrinsics::transmute; // depended upon by rand_core +LL + use core::mem::transmute; // depended upon by rand_core + | + diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed index 41917c65f5215..47e42c13a4589 100644 --- a/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed @@ -1,26 +1,32 @@ //@ run-rustfix #![crate_type = "lib"] #![allow(unnecessary_transmutes, unused_imports)] -#![deny(deprecated)] extern crate core; use std::mem::transmute as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::ptr::copy as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use std::ptr::copy_nonoverlapping as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::ptr::write_bytes as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::ptr::{ copy as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted copy_nonoverlapping as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted write_bytes as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted }; pub fn what() { @@ -29,11 +35,15 @@ pub fn what() { let mut dst = 0; let _ = std::mem::transmute::(value); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::ptr::copy(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::ptr::copy_nonoverlapping(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted std::ptr::write_bytes(&mut dst, value, 1) //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted } } diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs index 189927e9e8989..f3d9bd14cf62f 100644 --- a/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs @@ -1,26 +1,32 @@ //@ run-rustfix #![crate_type = "lib"] #![allow(unnecessary_transmutes, unused_imports)] -#![deny(deprecated)] extern crate core; use std::intrinsics::transmute as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::intrinsics::copy as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use std::intrinsics::copy_nonoverlapping as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::intrinsics::write_bytes as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::intrinsics::{ copy as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted copy_nonoverlapping as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted write_bytes as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted }; pub fn what() { @@ -29,11 +35,15 @@ pub fn what() { let mut dst = 0; let _ = std::intrinsics::transmute::(value); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::intrinsics::copy(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted std::intrinsics::write_bytes(&mut dst, value, 1) //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted } } diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr index 645437a306f74..96f56043af189 100644 --- a/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr @@ -1,14 +1,12 @@ error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:8:5 + --> $DIR/accidentally-stable-intrinsics.rs:7:5 | LL | use std::intrinsics::transmute as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/accidentally-stable-intrinsics.rs:4:9 - | -LL | #![deny(deprecated)] - | ^^^^^^^^^^ + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default help: import this function via the `mem` module instead | LL - use std::intrinsics::transmute as _; @@ -21,6 +19,8 @@ error: use of deprecated import through accidentally stabilized module `intrinsi LL | use core::intrinsics::copy as _; | ^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::copy as _; @@ -28,11 +28,13 @@ LL + use core::ptr::copy as _; | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:12:5 + --> $DIR/accidentally-stable-intrinsics.rs:13:5 | LL | use std::intrinsics::copy_nonoverlapping as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - use std::intrinsics::copy_nonoverlapping as _; @@ -40,11 +42,13 @@ LL + use std::ptr::copy_nonoverlapping as _; | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:14:5 + --> $DIR/accidentally-stable-intrinsics.rs:16:5 | LL | use core::intrinsics::write_bytes as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::write_bytes as _; @@ -52,11 +56,13 @@ LL + use core::ptr::write_bytes as _; | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:18:5 + --> $DIR/accidentally-stable-intrinsics.rs:21:5 | LL | copy as _, | ^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::{ @@ -64,11 +70,13 @@ LL + use core::ptr::{ | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:20:5 + --> $DIR/accidentally-stable-intrinsics.rs:24:5 | LL | copy_nonoverlapping as _, | ^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::{ @@ -76,11 +84,13 @@ LL + use core::ptr::{ | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:22:5 + --> $DIR/accidentally-stable-intrinsics.rs:27:5 | LL | write_bytes as _, | ^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::{ @@ -88,11 +98,13 @@ LL + use core::ptr::{ | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:30:17 + --> $DIR/accidentally-stable-intrinsics.rs:36:17 | LL | let _ = std::intrinsics::transmute::(value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `mem` module instead | LL - let _ = std::intrinsics::transmute::(value); @@ -100,11 +112,13 @@ LL + let _ = std::mem::transmute::(value); | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:32:9 + --> $DIR/accidentally-stable-intrinsics.rs:39:9 | LL | core::intrinsics::copy(&value, &mut dst, 1); | ^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - core::intrinsics::copy(&value, &mut dst, 1); @@ -112,11 +126,13 @@ LL + core::ptr::copy(&value, &mut dst, 1); | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:34:9 + --> $DIR/accidentally-stable-intrinsics.rs:42:9 | LL | core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); @@ -124,11 +140,13 @@ LL + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:36:9 + --> $DIR/accidentally-stable-intrinsics.rs:45:9 | LL | std::intrinsics::write_bytes(&mut dst, value, 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = 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 #163160 help: import this function via the `ptr` module instead | LL - std::intrinsics::write_bytes(&mut dst, value, 1) @@ -137,3 +155,179 @@ LL + std::ptr::write_bytes(&mut dst, value, 1) error: aborting due to 11 previous errors +Future incompatibility report: Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:7:5 + | +LL | use std::intrinsics::transmute as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `mem` module instead + | +LL - use std::intrinsics::transmute as _; +LL + use std::mem::transmute as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:10:5 + | +LL | use core::intrinsics::copy as _; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::copy as _; +LL + use core::ptr::copy as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:13:5 + | +LL | use std::intrinsics::copy_nonoverlapping as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy_nonoverlapping as _; +LL + use std::ptr::copy_nonoverlapping as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:16:5 + | +LL | use core::intrinsics::write_bytes as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::write_bytes as _; +LL + use core::ptr::write_bytes as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:21:5 + | +LL | copy as _, + | ^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:24:5 + | +LL | copy_nonoverlapping as _, + | ^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:27:5 + | +LL | write_bytes as _, + | ^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:36:17 + | +LL | let _ = std::intrinsics::transmute::(value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `mem` module instead + | +LL - let _ = std::intrinsics::transmute::(value); +LL + let _ = std::mem::transmute::(value); + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:39:9 + | +LL | core::intrinsics::copy(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy(&value, &mut dst, 1); +LL + core::ptr::copy(&value, &mut dst, 1); + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:42:9 + | +LL | core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); +LL + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:45:9 + | +LL | std::intrinsics::write_bytes(&mut dst, value, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - std::intrinsics::write_bytes(&mut dst, value, 1) +LL + std::ptr::write_bytes(&mut dst, value, 1) + | + diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs index eaa3ad9b830b4..4af64189dbfe3 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.rs +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -2,8 +2,9 @@ // //@ aux-build:allowed-through-unstable-core.rs #![crate_type = "lib"] - +#![warn(unstable_imports)] extern crate allowed_through_unstable_core; use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated import through accidentally stabilized module `unstable_module` +//~| WARN previously accepted use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature` diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 160dd4d4babff..6f2e0bf7a1fe9 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -4,7 +4,13 @@ warning: use of deprecated import through accidentally stabilized module `unstab LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(deprecated)]` on by default + = 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 #163160 +note: the lint level is defined here + --> $DIR/allowed-through-unstable.rs:5:9 + | +LL | #![warn(unstable_imports)] + | ^^^^^^^^^^^^^^^^ help: use the new path instead | LL - use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; @@ -12,7 +18,7 @@ LL + use allowed_through_unstable_core::stable::OldStableTraitAllowedThoughUnsta | error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/allowed-through-unstable.rs:9:36 + --> $DIR/allowed-through-unstable.rs:10:36 | LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; | ^^^^^^^^^^^^^^^ @@ -24,3 +30,23 @@ LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowe error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0658`. +Future incompatibility report: Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `unstable_module` + --> $DIR/allowed-through-unstable.rs:8:5 + | +LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 +note: the lint level is defined here + --> $DIR/allowed-through-unstable.rs:5:9 + | +LL | #![warn(unstable_imports)] + | ^^^^^^^^^^^^^^^^ +help: use the new path instead + | +LL - use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; +LL + use allowed_through_unstable_core::stable::OldStableTraitAllowedThoughUnstable; + | + diff --git a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs index d9e810362f2e9..9af880b63042b 100644 --- a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs +++ b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs @@ -6,7 +6,7 @@ // is unstable. #![allow(unused_imports)] -#![allow(deprecated)] +#![allow(unstable_imports)] use std::intrinsics::copy_nonoverlapping as _; use std::intrinsics::copy as _; diff --git a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr new file mode 100644 index 0000000000000..5391a1a43889d --- /dev/null +++ b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr @@ -0,0 +1,90 @@ +Future incompatibility report: Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:11:5 + | +LL | use std::intrinsics::copy_nonoverlapping as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy_nonoverlapping as _; +LL + use std::ptr::copy_nonoverlapping as _; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:12:5 + | +LL | use std::intrinsics::copy as _; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy as _; +LL + use std::ptr::copy as _; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:13:5 + | +LL | use std::intrinsics::write_bytes as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::write_bytes as _; +LL + use std::ptr::write_bytes as _; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:14:23 + | +LL | use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; + | ^^^^^^^^^^^^^^^^^^^ + | + = 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 #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; +LL + use std::ptr::{copy_nonoverlapping, copy, write_bytes}; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:14:44 + | +LL | use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; + | ^^^^ + | + = 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 #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; +LL + use std::ptr::{copy_nonoverlapping, copy, write_bytes}; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:14:50 + | +LL | use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; + | ^^^^^^^^^^^ + | + = 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 #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; +LL + use std::ptr::{copy_nonoverlapping, copy, write_bytes}; + | + From 0103c947a52c4f82123f174881aae86a136fc3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Jun 2026 20:28:36 +0000 Subject: [PATCH 28/31] When compiling without a specified `--edition`, emit a `eprintln` message Use same wording as cargo does when `package.edition` is unspecified. Do not suggest `--edition=future` on stable. --- compiler/rustc_driver_impl/src/lib.rs | 14 +++- compiler/rustc_interface/src/tests.rs | 10 +-- compiler/rustc_session/src/config.rs | 46 ++++++++---- compiler/rustc_span/src/edition.rs | 21 ++++-- src/librustdoc/config.rs | 4 +- src/tools/compiletest/src/directives.rs | 9 +-- src/tools/compiletest/src/rustdoc_gui_test.rs | 5 +- tests/run-make/broken-pipe-no-ice/rmake.rs | 2 +- tests/run-make/compressed-debuginfo/rmake.rs | 1 + .../const-destruct-stable-toolchain/rmake.rs | 2 + .../const-trait-stable-toolchain/rmake.rs | 4 + .../rmake.rs | 3 +- .../rmake.rs | 15 +++- tests/run-make/crate-loading/rmake.rs | 11 ++- tests/run-make/emit-to-stdout/rmake.rs | 22 +++++- tests/run-make/jobserver-error/rmake.rs | 2 + tests/run-make/linker-warning/rmake.rs | 10 ++- .../missing-unstable-trait-bound/rmake.rs | 1 + tests/run-make/multiline-args-value/rmake.rs | 3 +- tests/run-make/non-unicode-env/rmake.rs | 6 +- .../run-make/option-output-no-space/rmake.rs | 34 +++++++-- tests/run-make/overwrite-input/rmake.rs | 5 +- .../pointer-auth-link-with-c/rmake.rs | 3 + .../rmake.rs | 5 +- .../rustdoc/doctest/test_harness/rmake.rs | 1 + tests/run-make/target-cpu-native/rmake.rs | 1 + tests/run-make/unknown-mod-stdin/rmake.rs | 3 +- .../help-unspecified-edition.stdout | 74 +++++++++++++++++++ tests/run-make/unspecified-edition/main.rs | 1 + tests/run-make/unspecified-edition/rmake.rs | 39 ++++++++++ ...specified-edition-without-compiling.stderr | 4 + .../unspecified-edition.stderr | 2 + 32 files changed, 302 insertions(+), 61 deletions(-) create mode 100644 tests/run-make/unspecified-edition/help-unspecified-edition.stdout create mode 100644 tests/run-make/unspecified-edition/main.rs create mode 100644 tests/run-make/unspecified-edition/rmake.rs create mode 100644 tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr create mode 100644 tests/run-make/unspecified-edition/unspecified-edition.stderr diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 959222b19c6e9..1ba7ce953b5d4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -184,14 +184,24 @@ pub fn compiler_entrypoint(at_args: &[String], callbacks: &mut (dyn Callbacks + let args = args::arg_expand_all(&default_early_dcx, at_args); + // For the purposes of checking that an --edition was passed, we only emit a message if the only + // argument passed to rustc is a file name. + let warn_unspecified_edition = match &args[..] { + [] => false, + // We explicitly don't emit the note if we're consuming code from stdin, or passing non-file + // flags. This can happen on some cargo invocations too. + [name] if name.starts_with("-") => false, + [_] => true, + _ => false, + }; let (matches, help_only) = match handle_options(&default_early_dcx, &args) { HandledOptions::None => return, HandledOptions::Normal(matches) => (matches, false), HandledOptions::HelpOnly(matches) => (matches, true), }; - let sopts = config::build_session_options(&mut default_early_dcx, &matches); - // fully initialize ice path static once unstable options are available as context + let sopts = + config::build_session_options(&mut default_early_dcx, &matches, warn_unspecified_edition); let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); if let Some(ref code) = matches.opt_str("explain") { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2f9489ac67ad4..2dfb8f04f58f2 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -42,7 +42,7 @@ where { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(args).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, true); let target = rustc_session::config::build_target_config( &early_dcx, &sessopts.target_triple, @@ -942,7 +942,7 @@ fn test_edition_parsing() { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, false); assert!(sessopts.edition == Edition::Edition2018) } @@ -953,7 +953,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { // `-Zassumptions-on-binders` alone enables the next solver globally. let matches = optgroups().parse(&["-Zassumptions-on-binders".to_string()]).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); @@ -964,7 +964,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { ["-Znext-solver=coherence".to_string(), "-Zassumptions-on-binders".to_string()], ] { let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); } @@ -977,7 +977,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { ["-Znext-solver=no".to_string(), "-Zassumptions-on-binders".to_string()], ] { let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 798dcaf969965..fdfc2aacc79a8 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -21,7 +21,9 @@ use rustc_errors::{ColorConfig, DiagCtxtFlags}; use rustc_feature::UnstableFeatures; use rustc_hashes::Hash64; use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash}; -use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION}; +use rustc_span::edition::{ + DEFAULT_EDITION, EDITION_NAME_LIST, EDITION_NAME_LIST_STABLE, Edition, LATEST_STABLE_EDITION, +}; use rustc_span::source_map::FilePathMapping; use rustc_span::{ FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym, @@ -2369,22 +2371,35 @@ pub fn parse_error_format( error_format } -pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition { +pub fn parse_crate_edition( + early_dcx: &EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Edition { + let is_nightly = nightly_options::match_is_nightly_build(matches); + let edition_list = if is_nightly { EDITION_NAME_LIST } else { EDITION_NAME_LIST_STABLE }; let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { early_dcx.early_fatal(format!( - "argument for `--edition` must be one of: \ - {EDITION_NAME_LIST}. (instead was `{arg}`)" + "argument for `--edition` must be one of: {edition_list} (instead was `{arg}`)", )) }), - None => DEFAULT_EDITION, + None => { + if has_input { + eprintln!( + "`--edition` is unspecified, defaulting to `{DEFAULT_EDITION}` while the \ + latest is `{LATEST_STABLE_EDITION}`; it must be one of: {edition_list}\n", + ); + } + DEFAULT_EDITION + } }; if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { - let is_nightly = nightly_options::match_is_nightly_build(matches); let msg = if !is_nightly { format!( - "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}" + "the crate requires edition {edition}, but the latest edition supported by this \ + Rust version is {LATEST_STABLE_EDITION}" ) } else { format!("edition {edition} is unstable and only available with -Z unstable-options") @@ -2681,10 +2696,14 @@ fn parse_remap_path_prefix( // JUSTIFICATION: before wrapper fn is available #[allow(rustc::bad_opt_access)] -pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options { +pub fn build_session_options( + early_dcx: &mut EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Options { let color = parse_color(early_dcx, matches); - let edition = parse_crate_edition(early_dcx, matches); + let edition = parse_crate_edition(early_dcx, matches, has_input); let crate_name = matches.opt_str("crate-name"); let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref()); @@ -2852,14 +2871,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf { early_dcx.early_fatal( "`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \ - and a nightly compiler", + and a nightly compiler", ) } if !nightly_options::is_unstable_enabled(matches) && !unstable_opts.offload.is_empty() { early_dcx.early_fatal( - "`-Zoffload=Enable` also requires `-Zunstable-options` \ - and a nightly compiler", + "`-Zoffload=Enable` also requires `-Zunstable-options` and a nightly compiler", ) } @@ -2875,8 +2893,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if let Some(flavor) = cg.linker_flavor { if flavor.is_unstable() { early_dcx.early_fatal(format!( - "the linker flavor `{}` is unstable, the `-Z unstable-options` \ - flag must also be passed to use the unstable values", + "the linker flavor `{}` is unstable, the `-Z unstable-options` flag must also \ + be passed to use the unstable values", flavor.desc() )); } diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 38165f511b417..d4f3f0e208e34 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -45,7 +45,10 @@ pub const ALL_EDITIONS: &[Edition] = &[ Edition::EditionFuture, ]; +/// All the valid editions that `--edition` will accept on nightly. pub const EDITION_NAME_LIST: &str = "<2015|2018|2021|2024|future>"; +/// All the valid editions on stable, which doesn't include `future`. +pub const EDITION_NAME_LIST_STABLE: &str = "<2015|2018|2021|2024>"; pub const DEFAULT_EDITION: Edition = Edition::Edition2015; @@ -53,13 +56,7 @@ pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2024; impl fmt::Display for Edition { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - Edition::Edition2015 => "2015", - Edition::Edition2018 => "2018", - Edition::Edition2021 => "2021", - Edition::Edition2024 => "2024", - Edition::EditionFuture => "future", - }; + let s = self.as_str(); write!(f, "{s}") } } @@ -75,6 +72,16 @@ impl Edition { } } + pub fn as_str(&self) -> &'static str { + match *self { + Edition::Edition2015 => "2015", + Edition::Edition2018 => "2018", + Edition::Edition2021 => "2021", + Edition::Edition2024 => "2024", + Edition::EditionFuture => "future", + } + } + pub fn is_stable(self) -> bool { match self { Edition::Edition2015 => true, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index fb89a6547a931..170352dabf656 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -777,7 +777,9 @@ impl Options { } } - let edition = config::parse_crate_edition(early_dcx, matches); + // We don't want rustdoc invocations to complain about the lack of `--edition`. + let has_input = false; + let edition = config::parse_crate_edition(early_dcx, matches, has_input); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 94e949b78d0a1..1037b2c6375b7 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -405,11 +405,10 @@ impl TestProps { } } - if let Some(edition) = self.edition.or(config.edition) { - // The edition is added at the start, since flags from //@compile-flags must be passed - // to rustc last. - self.compile_flags.insert(0, format!("--edition={edition}")); - } + let edition = self.edition.or(config.edition).unwrap_or(Edition::Year(2015)); + // The edition is added at the start, since flags from //@compile-flags must be passed + // to rustc last. + self.compile_flags.insert(0, format!("--edition={edition}")); } fn update_pass_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { diff --git a/src/tools/compiletest/src/rustdoc_gui_test.rs b/src/tools/compiletest/src/rustdoc_gui_test.rs index 5a768519f616d..4e1d1138b3168 100644 --- a/src/tools/compiletest/src/rustdoc_gui_test.rs +++ b/src/tools/compiletest/src/rustdoc_gui_test.rs @@ -33,7 +33,10 @@ impl RustdocGuiTestProps { let props = TestProps::from_file(test_file_path, None, &config); - let TestProps { compile_flags, run_flags, .. } = props; + let TestProps { mut compile_flags, run_flags, .. } = props; + // We don't want to pass `--edition=2015` in, which is being set by default by + // `TestProps::from_file`. + compile_flags.remove(0); Self { compile_flags, run_flags } } } diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index b0a28b6c899da..0e43ebda9c3e1 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -68,7 +68,7 @@ fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { fn main() { let mut rustc = bare_rustc(); - rustc.arg("--print=sysroot"); + rustc.arg("--print=sysroot").edition("2015"); let rustc = rustc.into_raw_command(); check_broken_pipe_handled_gracefully(Binary::Rustc, rustc); diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index 45bfaa6041d97..4a5305a87cbfb 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -12,6 +12,7 @@ use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { let out = rustc() + .edition("2015") .crate_name("foo") .crate_type("lib") .emit("obj") diff --git a/tests/run-make/const-destruct-stable-toolchain/rmake.rs b/tests/run-make/const-destruct-stable-toolchain/rmake.rs index c4990582d40ba..47d66cf267ab9 100644 --- a/tests/run-make/const-destruct-stable-toolchain/rmake.rs +++ b/tests/run-make/const-destruct-stable-toolchain/rmake.rs @@ -10,12 +10,14 @@ use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { let out = stable_bare_rustc() .input("const-drop.rs") + .edition("2015") .run_fail() .assert_stderr_not_contains("consider restricting type parameter `T`") .stderr_utf8(); diff().expected_file("const-drop-stable.stderr").actual_text("(rustc)", &out).run(); let out = rustc() .input("const-drop.rs") + .edition("2015") .ui_testing() .run_fail() .assert_stderr_contains( diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index c778873463063..a13b1cb936bbb 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -8,6 +8,7 @@ use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { let out = stable_bare_rustc() + .edition("2015") .input("const-super-trait.rs") .cfg("feature_enabled") .run_fail() @@ -22,6 +23,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .cfg("feature_enabled") .ui_testing() @@ -34,6 +36,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = stable_bare_rustc() + .edition("2015") .input("const-super-trait.rs") .run_fail() .assert_stderr_not_contains("enable `#![feature(const_trait_impl)]` in your crate and mark") @@ -44,6 +47,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .ui_testing() .run_fail() 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 57e0cab92f1ef..f49a848052411 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 @@ -10,9 +10,10 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("foo-prev.rs").run(); + rustc().edition("2015").input("foo-prev.rs").run(); let out = rustc() + .edition("2015") .extra_filename("current") .metadata("current") .input("foo-current.rs") diff --git a/tests/run-make/crate-loading-multiple-candidates/rmake.rs b/tests/run-make/crate-loading-multiple-candidates/rmake.rs index ce090850500b8..9775a1672f0cb 100644 --- a/tests/run-make/crate-loading-multiple-candidates/rmake.rs +++ b/tests/run-make/crate-loading-multiple-candidates/rmake.rs @@ -9,8 +9,18 @@ use run_make_support::{bare_rustc, diff, rfs, rustc}; fn main() { // Check that relative paths are preserved in the diagnostic rfs::create_dir("mylibs"); - rustc().input("crateresolve1-1.rs").out_dir("mylibs").extra_filename("-1").run(); - rustc().input("crateresolve1-2.rs").out_dir("mylibs").extra_filename("-2").run(); + rustc() + .edition("2015") + .input("crateresolve1-1.rs") + .out_dir("mylibs") + .extra_filename("-1") + .run(); + rustc() + .edition("2015") + .input("crateresolve1-2.rs") + .out_dir("mylibs") + .extra_filename("-2") + .run(); check("./mylibs"); // Check that symlinks aren't followed when printing the diagnostic @@ -21,6 +31,7 @@ fn main() { fn check(library_path: &str) { let out = rustc() + .edition("2015") .input("multiple-candidates.rs") .library_search_path(library_path) .ui_testing() diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 8f2577861239d..79f14e1851eff 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -6,11 +6,16 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("dependency-1.rs").run(); - rustc().input("dependency-2.rs").extra_filename("2").metadata("2").run(); - rustc().input("dep-2-reexport.rs").extern_("dependency", rust_lib_name("dependency2")).run(); + rustc().edition("2015").input("dependency-1.rs").run(); + rustc().edition("2015").input("dependency-2.rs").extra_filename("2").metadata("2").run(); + rustc() + .edition("2015") + .input("dep-2-reexport.rs") + .extern_("dependency", rust_lib_name("dependency2")) + .run(); let out = rustc() + .edition("2015") .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) diff --git a/tests/run-make/emit-to-stdout/rmake.rs b/tests/run-make/emit-to-stdout/rmake.rs index 19c15b72fe475..851ab3cb45881 100644 --- a/tests/run-make/emit-to-stdout/rmake.rs +++ b/tests/run-make/emit-to-stdout/rmake.rs @@ -13,8 +13,9 @@ use run_make_support::{diff, run_in_tmpdir, rustc}; // Test emitting text outputs to stdout works correctly fn run_diff(name: &str, file_args: &[&str]) { - rustc().emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); - let out = rustc().emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); + rustc().edition("2015").emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); + let out = + rustc().edition("2015").emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); diff().expected_file(name).actual_text("stdout", &out).run(); } @@ -29,7 +30,13 @@ fn run_terminal_err_diff(name: &str) { let terminal = File::options().read(true).write(true).open(r"\\.\CONOUT$").unwrap(); let err = File::create(name).unwrap(); - rustc().emit(format!("{name}=-")).input("test.rs").stdout(terminal).stderr(err).run_fail(); + rustc() + .edition("2015") + .emit(format!("{name}=-")) + .input("test.rs") + .stdout(terminal) + .stderr(err) + .run_fail(); diff().expected_file(format!("emit-{name}.stderr")).actual_file(name).run(); } @@ -47,6 +54,7 @@ fn main() { // Test error for emitting multiple types to stdout rustc() + .edition("2015") .input("test.rs") .emit("asm=-") .emit("llvm-ir=-") @@ -58,6 +66,7 @@ fn main() { // Same as above, but using `-o` rustc() + .edition("2015") .input("test.rs") .output("-") .emit("asm,llvm-ir,dep-info,mir") @@ -69,6 +78,11 @@ fn main() { .run(); // Test that `-o -` redirected to a file works correctly (#26719) - rustc().input("test.rs").output("-").stdout(File::create("out-stdout").unwrap()).run(); + rustc() + .edition("2015") + .input("test.rs") + .output("-") + .stdout(File::create("out-stdout").unwrap()) + .run(); }); } diff --git a/tests/run-make/jobserver-error/rmake.rs b/tests/run-make/jobserver-error/rmake.rs index 265eec7190d4e..80c1562299e72 100644 --- a/tests/run-make/jobserver-error/rmake.rs +++ b/tests/run-make/jobserver-error/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .env("MAKEFLAGS", "--jobserver-auth=1000,1000") .run_fail() @@ -23,6 +24,7 @@ fn main() { diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run(); let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .input("-") .env("MAKEFLAGS", "--jobserver-auth=3,3") diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index f1a561e1291a5..8b0c22b0fb940 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -5,6 +5,7 @@ use run_make_support::{Rustc, diff, regex, rustc}; fn run_rustc() -> Rustc { let mut rustc = rustc(); rustc + .edition("2015") .arg("main.rs") // NOTE: `link-self-contained` can vary depending on bootstrap.toml. // Make sure we use a consistent value. @@ -23,9 +24,9 @@ fn run_rustc() -> Rustc { fn main() { // first, compile our linker and our dependencies - rustc().arg("fake-linker.rs").output("fake-linker").run(); - rustc().arg("foo.rs").crate_type("rlib").run(); - rustc().arg("bar.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("fake-linker.rs").output("fake-linker").run(); + rustc().edition("2015").arg("foo.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("bar.rs").crate_type("rlib").run(); // Run rustc with our fake linker, and make sure it shows warnings let warnings = run_rustc().link_arg("run_make_warn").run(); @@ -93,12 +94,14 @@ fn main() { // Make sure we show linker warnings even across `-Z no-link` rustc() + .edition("2015") .arg("-Zno-link") .input("-") .stdin_buf("#![deny(linker_messages)] \n fn main() {}") .run() .assert_stderr_equals(""); rustc() + .edition("2015") .arg("-Zlink-only") .arg("rust_out.rlink") .linker("./fake-linker") @@ -112,6 +115,7 @@ fn main() { // Same thing, but with json output. rustc() + .edition("2015") .error_format("json") .arg("-Zlink-only") .arg("rust_out.rlink") diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs index 52a011285c95c..807d24b630fd6 100644 --- a/tests/run-make/missing-unstable-trait-bound/rmake.rs +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -11,6 +11,7 @@ use run_make_support::{diff, stable_bare_rustc}; fn main() { let out = stable_bare_rustc() + .edition("2015") .input("missing-bound.rs") .run_fail() .assert_stderr_not_contains("help: consider restricting type parameter `T`") diff --git a/tests/run-make/multiline-args-value/rmake.rs b/tests/run-make/multiline-args-value/rmake.rs index 3964cbbc1e605..f9e6290f7d919 100644 --- a/tests/run-make/multiline-args-value/rmake.rs +++ b/tests/run-make/multiline-args-value/rmake.rs @@ -3,7 +3,8 @@ use run_make_support::{cwd, diff, rustc}; fn test_and_compare(test_name: &str, flag: &str, val: &str) { let mut cmd = rustc(); - let output = cmd.input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); + let output = + cmd.edition("2015").input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); assert_eq!(output.stdout_utf8(), ""); diff() diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs index b7a3c51db5bfd..7a1c7e4322ddc 100644 --- a/tests/run-make/non-unicode-env/rmake.rs +++ b/tests/run-make/non-unicode-env/rmake.rs @@ -6,7 +6,11 @@ fn main() { let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]); #[cfg(windows)] let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]); - let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail(); + let output = rustc() + .edition("2015") + .input("non_unicode_env.rs") + .env("NON_UNICODE_VAR", non_unicode) + .run_fail(); let expected = rfs::read_to_string("non_unicode_env.stderr"); output.assert_stderr_equals(expected); } diff --git a/tests/run-make/option-output-no-space/rmake.rs b/tests/run-make/option-output-no-space/rmake.rs index 63d2389890155..d77ae4bef12a8 100644 --- a/tests/run-make/option-output-no-space/rmake.rs +++ b/tests/run-make/option-output-no-space/rmake.rs @@ -7,6 +7,7 @@ use run_make_support::rustc; fn main() { // test fake args rustc() + .edition("2015") .input("main.rs") .arg("-optimize") .run() @@ -17,6 +18,7 @@ fn main() { "= note: output filename `-o ptimize` is applied instead of a flag named `optimize`", ); rustc() + .edition("2015") .input("main.rs") .arg("-o0") .run() @@ -26,9 +28,10 @@ fn main() { .assert_stderr_contains( "= note: output filename `-o 0` is applied instead of a flag named `o0`", ); - rustc().input("main.rs").arg("-o1").run(); + rustc().edition("2015").input("main.rs").arg("-o1").run(); // test real args by iter optgroups rustc() + .edition("2015") .input("main.rs") .arg("-out-dir") .run() @@ -43,6 +46,7 @@ fn main() { ); // test real args by iter CG_OPTIONS rustc() + .edition("2015") .input("main.rs") .arg("-opt_level") .run() @@ -58,6 +62,7 @@ fn main() { ); // separater in-sensitive rustc() + .edition("2015") .input("main.rs") .arg("-opt-level") .run() @@ -72,6 +77,7 @@ fn main() { `-o pt-level`", ); rustc() + .edition("2015") .input("main.rs") .arg("-overflow-checks") .run() @@ -88,10 +94,28 @@ fn main() { ); // No warning for Z_OPTIONS - rustc().input("main.rs").arg("-oom").run().assert_stderr_equals(""); + rustc().edition("2015").input("main.rs").arg("-oom").run().assert_stderr_equals(""); // test no warning when there is space between `-o` and arg - rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("ptimize") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("--out-dir") + .arg("xxx") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("out-dir") + .run() + .assert_stderr_equals(""); } diff --git a/tests/run-make/overwrite-input/rmake.rs b/tests/run-make/overwrite-input/rmake.rs index bdf7860caa8a0..581fee8fe0136 100644 --- a/tests/run-make/overwrite-input/rmake.rs +++ b/tests/run-make/overwrite-input/rmake.rs @@ -8,8 +8,9 @@ use run_make_support::{diff, rustc}; fn main() { - let file_out = rustc().input("main.rs").output("main.rs").run_fail().stderr_utf8(); - let folder_out = rustc().input("main.rs").output(".").run_fail().stderr_utf8(); + let file_out = + rustc().edition("2015").input("main.rs").output("main.rs").run_fail().stderr_utf8(); + let folder_out = rustc().edition("2015").input("main.rs").output(".").run_fail().stderr_utf8(); diff().expected_file("file.stderr").actual_text("actual-file-stderr", file_out).run(); diff().expected_file("folder.stderr").actual_text("actual-folder-stderr", folder_out).run(); } diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs index 1ac68c95559c6..e5793130c6550 100644 --- a/tests/run-make/pointer-auth-link-with-c/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{build_native_static_lib, cc, is_windows_msvc, llvm_ar, ru fn main() { build_native_static_lib("test"); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -30,6 +31,7 @@ fn main() { let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -46,6 +48,7 @@ fn main() { // let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; // llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); // rustc() + // .edition("2015") // .arg("-Cunsafe-allow-abi-mismatch=branch-protection") // .arg("-Zbranch-protection=bti,pac-ret,pc,leaf") // .input("test.rs") diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs index 01572a5aad942..49df84b353cd4 100644 --- a/tests/run-make/print-request-help-stable-unstable/rmake.rs +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -8,14 +8,15 @@ use run_make_support::{diff, rustc, similar, stable_bare_rustc}; fn main() { let stable_invalid_print_request_help = - stable_bare_rustc().print("xxx").run_fail().stderr_utf8(); + stable_bare_rustc().edition("2015").print("xxx").run_fail().stderr_utf8(); assert!(!stable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("stable-invalid-print-request-help.err") .actual_text("stable_invalid_print_request_help", &stable_invalid_print_request_help) .run(); - let unstable_invalid_print_request_help = rustc().print("xxx").run_fail().stderr_utf8(); + let unstable_invalid_print_request_help = + rustc().edition("2015").print("xxx").run_fail().stderr_utf8(); assert!(unstable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("unstable-invalid-print-request-help.err") diff --git a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs index 608adebbd54f2..87d57ca1f76ac 100644 --- a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs +++ b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs @@ -19,6 +19,7 @@ fn main() { rustc().input(runtool_path).run(); let output = rustdoc() + .edition("2015") .input(doctests_path) .arg("--test") // for the outer test suite diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs index 5791bf01bba2b..dbea1bda2cab5 100644 --- a/tests/run-make/target-cpu-native/rmake.rs +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{run, rustc}; fn main() { let out = rustc() + .edition("2015") .input("foo.rs") .arg("-Ctarget-cpu=native") .arg("-Zverify-llvm-ir") diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs index 101711b0d2c70..56833569e54bf 100644 --- a/tests/run-make/unknown-mod-stdin/rmake.rs +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -14,7 +14,8 @@ use run_make_support::{diff, rustc}; fn main() { - let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); + let out = + rustc().edition("2015").crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); diff() .actual_text("actual-stdout", out.stdout_utf8()) .expected_file("unknown-mod.stdout") diff --git a/tests/run-make/unspecified-edition/help-unspecified-edition.stdout b/tests/run-make/unspecified-edition/help-unspecified-edition.stdout new file mode 100644 index 0000000000000..eea9ae297848a --- /dev/null +++ b/tests/run-make/unspecified-edition/help-unspecified-edition.stdout @@ -0,0 +1,74 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg Configure the compilation environment. + SPEC supports the syntax `[=""]`. + --check-cfg + Provide list of expected cfgs for checking + -L [=] Add a directory to the library search path. The + optional KIND can be one of + (default: + all). + -l [[:]=][:] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + (default: dylib). + Optional comma separated MODIFIERS + + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type + Comma separated list of types of crates + for the compiler to emit + --crate-name + Specify the name of the crate being built + --edition <2015|2018|2021|2024|future> + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2024. + --emit [=] + Comma separated list of types of output for the + compiler to emit. + Each TYPE has the default FILE name: + * asm - CRATE_NAME.s + * llvm-bc - CRATE_NAME.bc + * dep-info - CRATE_NAME.d + * link - (platform and crate-type dependent) + * llvm-ir - CRATE_NAME.ll + * metadata - libCRATE_NAME.rmeta + * mir - CRATE_NAME.mir + * obj - CRATE_NAME.o + * thin-link-bitcode - CRATE_NAME.indexing.o + --print [=] + Compiler information to print on stdout (or to a file) + INFO may be one of + . + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=3 + -o Write output to FILENAME + --out-dir

Write output to compiler-chosen filename in DIR + --explain Provide a detailed explanation of an error message + --test Build a test harness + --target + Target tuple for which the code is compiled + -A, --allow Set lint allowed + -W, --warn Set lint warnings + --force-warn + Set lint force-warn + -D, --deny Set lint denied + -F, --forbid Set lint forbidden + --cap-lints + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen [=] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/unspecified-edition/main.rs b/tests/run-make/unspecified-edition/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/unspecified-edition/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/unspecified-edition/rmake.rs b/tests/run-make/unspecified-edition/rmake.rs new file mode 100644 index 0000000000000..d20ac26b8e71d --- /dev/null +++ b/tests/run-make/unspecified-edition/rmake.rs @@ -0,0 +1,39 @@ +// When calling `rustc` without an explicit edition, emit a note asking the user to specify one, +// clarifying that the default is 2015. +//@ needs-target-std +//@ ignore-cross-compile + +use run_make_support::{bare_rustc, diff, rustc, rustdoc}; + +fn main() { + bare_rustc().edition("2015").input("main.rs").run().assert_stderr_not_contains("--edition"); + let out = bare_rustc().input("main.rs").run().assert_stderr_contains("--edition").stderr_utf8(); + diff().expected_file("unspecified-edition.stderr").actual_text("(rustc)", &out).run(); + + // Ensure that we only mention --edition when compiling code. + let out = rustc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_file("unspecified-edition-without-compiling.stderr") + .actual_text("(rustc)", &out) + .run(); + + // Ensure that we dont mention --edition when running rustdoc. + let out = rustdoc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_text("(test)", "error: missing file operand\n\n") + .actual_text("(rustc)", &out) + .run(); + + let out = + rustdoc().input("main.rs").run().assert_stderr_not_contains("--edition").stderr_utf8(); + diff().expected_text("(test)", "").actual_text("(rustc)", &out).run(); + + // Ensure that we don't mention --edition when getting help. + let result = bare_rustc().arg("--help").run(); + result.assert_stderr_not_contains("--edition"); + let out = result.stdout_utf8(); + let err = result.stderr_utf8(); + diff().expected_file("help-unspecified-edition.stdout").actual_text("(rustc)", &out).run(); + diff().expected_text("(test)", "").actual_text("(rustc)", &err).run(); + bare_rustc().arg("--version").run().assert_stderr_not_contains("--edition"); +} diff --git a/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr new file mode 100644 index 0000000000000..c36ecca4af4a2 --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr @@ -0,0 +1,4 @@ +error: no input filename given + +error: aborting due to 1 previous error + diff --git a/tests/run-make/unspecified-edition/unspecified-edition.stderr b/tests/run-make/unspecified-edition/unspecified-edition.stderr new file mode 100644 index 0000000000000..0a15e47d49fae --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition.stderr @@ -0,0 +1,2 @@ +`--edition` is unspecified, defaulting to `2015` while the latest is `2024`; it must be one of: <2015|2018|2021|2024|future> + From 465aca6dd3e8f33ee6e9e3ca07c20c7be4ce5813 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 14 Sep 2026 12:19:25 +0200 Subject: [PATCH 29/31] Route `fn_hir_id` into `lower_fn_decl` --- compiler/rustc_ast_lowering/src/expr/closure.rs | 8 ++++++-- compiler/rustc_ast_lowering/src/item.rs | 17 +++++++++++++---- compiler/rustc_ast_lowering/src/lib.rs | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index c72956545b7c8..a40ce1696b033 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -133,6 +133,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, capture_clause, closure_id, + expr_hir_id, constness, movability, decl, @@ -159,6 +160,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, + closure_hir_id: HirId, constness: Const, movability: Movability, decl: &FnDecl, @@ -205,7 +207,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, closure_id, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { def_id: closure_def_id, @@ -328,7 +331,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl(&decl, closure_id, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(&decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); if let Const::Yes(span) = constness { self.dcx().span_err(span, "const coroutines are not supported"); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 6ec5903c5fb3b..b56759a252b4e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -278,7 +278,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(decl, id, FnDeclKind::Fn, coroutine_marker) + this.lower_fn_decl( + decl, + id, + hir_id, + FnDeclKind::Fn, + coroutine_marker) }); let sig = hir::FnSig { decl, @@ -616,7 +621,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, i.id, FnDeclKind::ExternFn, None), + this.lower_fn_decl(fdec, i.id, hir_id, FnDeclKind::ExternFn, None), this.lower_fn_params_to_idents(fdec), ) }); @@ -838,6 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, + hir_id, FnDeclKind::Trait, sig.header.coroutine_marker, attrs, @@ -878,6 +884,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, + hir_id, FnDeclKind::Trait, sig.header.coroutine_marker, attrs, @@ -1088,6 +1095,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, + hir_id, if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_marker, attrs, @@ -1533,7 +1541,8 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, sig: &FnSig, - id: NodeId, + node_id: NodeId, + hir_id: HirId, kind: FnDeclKind, coroutine_marker: Option, attrs: &[rustc_attr_ir::Attribute], @@ -1541,7 +1550,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(&sig.decl, id, kind, coroutine_marker) + this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4b6e897da4c87..2bee965db9f3f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1547,14 +1547,22 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::TyKind::Path(path) } TyKind::FnPtr(f) => { + let hir_id = self.lower_node_id(t.id); let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); - hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy { + let kind = hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy { generic_params, safety: self.lower_safety(f.safety, hir::Safety::Safe), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, t.id, FnDeclKind::Pointer, None), + decl: self.lower_fn_decl( + &f.decl, + t.id, + hir_id, + FnDeclKind::Pointer, + None, + ), param_idents: self.lower_fn_params_to_idents(&f.decl), - })) + })); + return hir::Ty { kind, span: self.lower_span(t.span), hir_id }; } TyKind::UnsafeBinder(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); @@ -1910,6 +1918,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, decl: &FnDecl, fn_node_id: NodeId, + fn_hir_id: HirId, kind: FnDeclKind, coro: Option, ) -> &'hir hir::FnDecl<'hir> { From 539bfe3225367d2a080e829dfc2dd5a0b28ae8fb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 14 Sep 2026 13:04:19 +0200 Subject: [PATCH 30/31] Add regression tests --- tests/ui/attributes/attrs-on-params.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs index c8e9810327c2a..ed4a50efa25db 100644 --- a/tests/ui/attributes/attrs-on-params.rs +++ b/tests/ui/attributes/attrs-on-params.rs @@ -5,4 +5,23 @@ fn function(#[inline] param: u32) { //~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes } +trait Test { + fn meow( + #[rustc_splat] a1: u32, + ); + fn meow2( + #[rustc_splat(invalid)] a4: u32, + ); +} + +type Meow = fn( + #[rustc_splat] a1: u32, +); + +extern "Rust" { + fn meow2( + #[rustc_splat] a1: u32, + ); +} + fn main() {} From 9c9d810f25ea3babf1f14e4524d5ee93ab360cab Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 14 Sep 2026 13:32:59 +0200 Subject: [PATCH 31/31] Lower attributes for functions without bodies --- .../rustc_ast_lowering/src/expr/closure.rs | 22 +- compiler/rustc_ast_lowering/src/item.rs | 25 ++- compiler/rustc_ast_lowering/src/lib.rs | 30 ++- library/coretests/tests/lib.rs | 2 + tests/ui/attributes/attrs-on-params.rs | 5 + tests/ui/attributes/attrs-on-params.stderr | 62 +++++- .../param-attrs-builtin-attrs.rs | 8 + .../param-attrs-builtin-attrs.stderr | 190 +++++++++++------- tests/ui/splat/splat-invalid.rs | 2 + tests/ui/splat/splat-invalid.stderr | 36 +++- 10 files changed, 284 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index a40ce1696b033..5924d53dd11e4 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -6,8 +6,8 @@ use rustc_hir::HirId; use rustc_span::{Span, span_bug}; use super::{LoweringContext, MoveExprState}; -use crate::FnDeclKind; use crate::diagnostics::{ClosureCannotBeStatic, CoroutineTooManyParameters}; +use crate::{DiscardParams, FnDeclKind}; impl<'hir> LoweringContext<'_, 'hir> { // Entry point for `ExprKind::Closure`. Plain closures go through @@ -207,8 +207,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = - self.lower_fn_decl(decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl( + decl, + closure_id, + closure_hir_id, + FnDeclKind::Closure, + None, + DiscardParams::No, + ); let c = self.arena.alloc(hir::Closure { def_id: closure_def_id, @@ -331,8 +337,14 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = - self.lower_fn_decl(&decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl( + &decl, + closure_id, + closure_hir_id, + FnDeclKind::Closure, + None, + DiscardParams::No, + ); if let Const::Yes(span) = constness { self.dcx().span_err(span, "const coroutines are not supported"); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b56759a252b4e..32229aeea0f9f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -19,8 +19,8 @@ use super::diagnostics::{ }; use super::stability::{enabled_names, gate_unstable_abi}; use super::{ - FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, - RelaxedBoundForbiddenReason, RelaxedBoundPolicy, + DiscardParams, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, + LoweringContext, ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, }; use crate::diagnostics::{ConstComptimeFn, ResolvingRestrictionKind, RestrictionAncestorOnly}; @@ -283,7 +283,9 @@ impl<'hir> LoweringContext<'_, 'hir> { id, hir_id, FnDeclKind::Fn, - coroutine_marker) + coroutine_marker, + if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, + ) }); let sig = hir::FnSig { decl, @@ -621,7 +623,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, i.id, hir_id, FnDeclKind::ExternFn, None), + // Parameters are discarded because foreign functions don't have a body + this.lower_fn_decl( + fdec, + i.id, + hir_id, + FnDeclKind::ExternFn, + None, + DiscardParams::Yes, + ), this.lower_fn_params_to_idents(fdec), ) }); @@ -847,6 +857,8 @@ impl<'hir> LoweringContext<'_, 'hir> { FnDeclKind::Trait, sig.header.coroutine_marker, attrs, + // Parameters are discarded for functions without a body + DiscardParams::Yes, ); if define_opaque.is_some() { self.dcx().span_err( @@ -888,6 +900,7 @@ impl<'hir> LoweringContext<'_, 'hir> { FnDeclKind::Trait, sig.header.coroutine_marker, attrs, + DiscardParams::No, ); self.lower_define_opaque(hir_id, &define_opaque); ( @@ -1099,6 +1112,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_marker, attrs, + if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, ); self.lower_define_opaque(hir_id, &define_opaque); @@ -1546,11 +1560,12 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: FnDeclKind, coroutine_marker: Option, attrs: &[rustc_attr_ir::Attribute], + discard_params: DiscardParams, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker) + this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker, discard_params) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2bee965db9f3f..66e0f595da0ee 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -807,6 +807,14 @@ enum GenericArgsMode { Silence, } +#[derive(Debug, Copy, Clone)] +enum DiscardParams { + /// Should be used for functions without a body. Lowers the attributes on the parameter and then discards them. + Yes, + /// Should be used for functions with a body. Does not lower the attributes, as lowering of the parameters is done by `lower_body`. + No, +} + impl<'hir> LoweringContext<'_, 'hir> { fn create_def( &mut self, @@ -1559,6 +1567,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id, FnDeclKind::Pointer, None, + DiscardParams::Yes, ), param_idents: self.lower_fn_params_to_idents(&f.decl), })); @@ -1908,11 +1917,17 @@ impl<'hir> LoweringContext<'_, 'hir> { /// /// `decl`: the unlowered (AST) function declaration. /// - /// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given - /// `NodeId`. + /// `fn_node_id`: Node Id of the function. /// - /// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is - /// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details. + /// `fn_hir_id`: Hir Id of the function. Used for attribute parsing. + /// + /// `kind`: The kind of function. + /// + /// `coro`: If the function is a coroutine, information about the coroutine. + /// + /// `discard_params`: if `DiscardParams::Yes`, the parameters are lowered and then discarded. Set this to `DiscardParams::Yes` + /// for functions without bodies, as attributes on parameters are otherwise not validated. + /// Set this to `DiscardParams::No` for functions with bodies, as lowering of the parameters is done by `lower_body`. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, @@ -1921,6 +1936,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_hir_id: HirId, kind: FnDeclKind, coro: Option, + discard_params: DiscardParams, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); let mut splatted = decl.splatted(); @@ -1935,6 +1951,12 @@ impl<'hir> LoweringContext<'_, 'hir> { inputs = &inputs[..inputs.len() - 1]; } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { + if let DiscardParams::Yes = discard_params { + // FIXME This uses `fn_hir_id`, which is not correct, it should use the parameter hir id instead + // The parameter is currently not lowered for functions without bodies, so there is no place to store the lowered hir id + // This should be fixed by storing function parameters in the `hir::FnSig` instead of `hir::Body` + self.lower_attrs(fn_hir_id, ¶m.attrs, param.span, Target::Param); + } let itctx = match kind { FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => { ImplTraitContext::Universal diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index fc2430a10edb4..bf84f27c7a0f5 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -111,6 +111,7 @@ #![feature(slice_shift)] #![feature(slice_split_once)] #![feature(sliceindex_wrappers)] +#![feature(splat)] #![feature(split_array)] #![feature(split_as_slice)] #![feature(std_internals)] @@ -131,6 +132,7 @@ #![feature(unicode_internals)] #![feature(unsize)] // tidy-alphabetical-end +#![allow(incomplete_features)] #![allow(internal_features)] #![deny(implicit_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs index ed4a50efa25db..e12ff906fa3f5 100644 --- a/tests/ui/attributes/attrs-on-params.rs +++ b/tests/ui/attributes/attrs-on-params.rs @@ -8,19 +8,24 @@ fn function(#[inline] param: u32) { trait Test { fn meow( #[rustc_splat] a1: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature ); fn meow2( #[rustc_splat(invalid)] a4: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature + //~| ERROR malformed `rustc_splat` attribute input ); } type Meow = fn( #[rustc_splat] a1: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature ); extern "Rust" { fn meow2( #[rustc_splat] a1: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature ); } diff --git a/tests/ui/attributes/attrs-on-params.stderr b/tests/ui/attributes/attrs-on-params.stderr index b38c590a19a5c..748f189590a46 100644 --- a/tests/ui/attributes/attrs-on-params.stderr +++ b/tests/ui/attributes/attrs-on-params.stderr @@ -12,5 +12,65 @@ LL | fn function(#[inline] param: u32) { | = help: the `inline` attribute can only be applied to functions -error: aborting due to 2 previous errors +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:10:11 + | +LL | #[rustc_splat] a1: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:14:11 + | +LL | #[rustc_splat(invalid)] a4: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error[E0565]: malformed `rustc_splat` attribute input + --> $DIR/attrs-on-params.rs:14:11 + | +LL | #[rustc_splat(invalid)] a4: u32, + | ^^^^^^^^^^^--------- + | | + | didn't expect any arguments here + | +help: must be of the form + | +LL - #[rustc_splat(invalid)] a4: u32, +LL + #[rustc_splat] a4: u32, + | + +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:21:7 + | +LL | #[rustc_splat] a1: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:27:11 + | +LL | #[rustc_splat] a1: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error: aborting due to 7 previous errors +Some errors have detailed explanations: E0565, E0658. +For more information about an error, try `rustc --explain E0565`. diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs index bb6e7705a29d6..7f1d5c849ebe6 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs @@ -8,10 +8,14 @@ extern "C" { //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted /// Baz //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted ); } @@ -24,10 +28,14 @@ type FnType = fn( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted /// Baz //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted ); pub fn foo( diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr index cee602a274bb3..db2d8f161dba0 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr @@ -5,55 +5,55 @@ LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:21:7 + --> $DIR/param-attrs-builtin-attrs.rs:25:7 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:36:7 + --> $DIR/param-attrs-builtin-attrs.rs:44:7 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:60:11 + --> $DIR/param-attrs-builtin-attrs.rs:68:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:79:11 + --> $DIR/param-attrs-builtin-attrs.rs:87:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:104:11 + --> $DIR/param-attrs-builtin-attrs.rs:112:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:127:11 + --> $DIR/param-attrs-builtin-attrs.rs:135:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:146:11 + --> $DIR/param-attrs-builtin-attrs.rs:154:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:170:11 + --> $DIR/param-attrs-builtin-attrs.rs:178:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:191:11 + --> $DIR/param-attrs-builtin-attrs.rs:199:11 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute @@ -77,313 +77,313 @@ LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:11:9 + --> $DIR/param-attrs-builtin-attrs.rs:13:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:13:9 + --> $DIR/param-attrs-builtin-attrs.rs:15:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:19:5 + --> $DIR/param-attrs-builtin-attrs.rs:23:5 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:23:5 + --> $DIR/param-attrs-builtin-attrs.rs:27:5 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:25:5 + --> $DIR/param-attrs-builtin-attrs.rs:29:5 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:27:5 + --> $DIR/param-attrs-builtin-attrs.rs:33:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:29:5 + --> $DIR/param-attrs-builtin-attrs.rs:35:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:34:5 + --> $DIR/param-attrs-builtin-attrs.rs:42:5 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:38:5 + --> $DIR/param-attrs-builtin-attrs.rs:46:5 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:40:5 + --> $DIR/param-attrs-builtin-attrs.rs:48:5 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:44:5 + --> $DIR/param-attrs-builtin-attrs.rs:52:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:46:5 + --> $DIR/param-attrs-builtin-attrs.rs:54:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:55:9 + --> $DIR/param-attrs-builtin-attrs.rs:63:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:58:9 + --> $DIR/param-attrs-builtin-attrs.rs:66:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:62:9 + --> $DIR/param-attrs-builtin-attrs.rs:70:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:64:9 + --> $DIR/param-attrs-builtin-attrs.rs:72:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:68:9 + --> $DIR/param-attrs-builtin-attrs.rs:76:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:70:9 + --> $DIR/param-attrs-builtin-attrs.rs:78:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:77:9 + --> $DIR/param-attrs-builtin-attrs.rs:85:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:81:9 + --> $DIR/param-attrs-builtin-attrs.rs:89:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:83:9 + --> $DIR/param-attrs-builtin-attrs.rs:91:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:87:9 + --> $DIR/param-attrs-builtin-attrs.rs:95:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:89:9 + --> $DIR/param-attrs-builtin-attrs.rs:97:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:99:9 + --> $DIR/param-attrs-builtin-attrs.rs:107:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:102:9 + --> $DIR/param-attrs-builtin-attrs.rs:110:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:106:9 + --> $DIR/param-attrs-builtin-attrs.rs:114:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:108:9 + --> $DIR/param-attrs-builtin-attrs.rs:116:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:112:9 + --> $DIR/param-attrs-builtin-attrs.rs:120:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:114:9 + --> $DIR/param-attrs-builtin-attrs.rs:122:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:122:9 + --> $DIR/param-attrs-builtin-attrs.rs:130:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:125:9 + --> $DIR/param-attrs-builtin-attrs.rs:133:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:129:9 + --> $DIR/param-attrs-builtin-attrs.rs:137:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:131:9 + --> $DIR/param-attrs-builtin-attrs.rs:139:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:135:9 + --> $DIR/param-attrs-builtin-attrs.rs:143:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:137:9 + --> $DIR/param-attrs-builtin-attrs.rs:145:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:144:9 + --> $DIR/param-attrs-builtin-attrs.rs:152:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:148:9 + --> $DIR/param-attrs-builtin-attrs.rs:156:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:150:9 + --> $DIR/param-attrs-builtin-attrs.rs:158:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:154:9 + --> $DIR/param-attrs-builtin-attrs.rs:162:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:156:9 + --> $DIR/param-attrs-builtin-attrs.rs:164:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:165:9 + --> $DIR/param-attrs-builtin-attrs.rs:173:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:168:9 + --> $DIR/param-attrs-builtin-attrs.rs:176:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:172:9 + --> $DIR/param-attrs-builtin-attrs.rs:180:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:174:9 + --> $DIR/param-attrs-builtin-attrs.rs:182:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:178:9 + --> $DIR/param-attrs-builtin-attrs.rs:186:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:180:9 + --> $DIR/param-attrs-builtin-attrs.rs:188:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:189:9 + --> $DIR/param-attrs-builtin-attrs.rs:197:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:193:9 + --> $DIR/param-attrs-builtin-attrs.rs:201:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:195:9 + --> $DIR/param-attrs-builtin-attrs.rs:203:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:199:9 + --> $DIR/param-attrs-builtin-attrs.rs:207:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:201:9 + --> $DIR/param-attrs-builtin-attrs.rs:209:9 | LL | #[no_mangle] b: i32 | ^^^^^^^^^^^^ warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:40:7 + --> $DIR/param-attrs-builtin-attrs.rs:29:7 | LL | #[must_use] | ^^^^^^^^ @@ -393,7 +393,25 @@ LL | #[must_use] = note: requested on the command line with `-W unused-attributes` warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:46:7 + --> $DIR/param-attrs-builtin-attrs.rs:35:7 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^ + | + = help: the `no_mangle` attribute can be applied to functions and statics + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `must_use` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:48:7 + | +LL | #[must_use] + | ^^^^^^^^ + | + = help: the `must_use` attribute can be applied to data types, functions, and traits + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `no_mangle` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:54:7 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -402,7 +420,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:195:11 + --> $DIR/param-attrs-builtin-attrs.rs:203:11 | LL | #[must_use] | ^^^^^^^^ @@ -411,7 +429,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:201:11 + --> $DIR/param-attrs-builtin-attrs.rs:209:11 | LL | #[no_mangle] b: i32 | ^^^^^^^^^ @@ -420,7 +438,25 @@ LL | #[no_mangle] b: i32 = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:131:11 + --> $DIR/param-attrs-builtin-attrs.rs:139:11 + | +LL | #[must_use] + | ^^^^^^^^ + | + = help: the `must_use` attribute can be applied to data types, functions, and traits + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `no_mangle` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:145:11 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^ + | + = help: the `no_mangle` attribute can be applied to functions and statics + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `must_use` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:158:11 | LL | #[must_use] | ^^^^^^^^ @@ -429,7 +465,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:137:11 + --> $DIR/param-attrs-builtin-attrs.rs:164:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -438,7 +474,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:150:11 + --> $DIR/param-attrs-builtin-attrs.rs:72:11 | LL | #[must_use] | ^^^^^^^^ @@ -447,7 +483,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:156:11 + --> $DIR/param-attrs-builtin-attrs.rs:78:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -456,7 +492,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:64:11 + --> $DIR/param-attrs-builtin-attrs.rs:91:11 | LL | #[must_use] | ^^^^^^^^ @@ -465,7 +501,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:70:11 + --> $DIR/param-attrs-builtin-attrs.rs:97:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -474,7 +510,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:83:11 + --> $DIR/param-attrs-builtin-attrs.rs:116:11 | LL | #[must_use] | ^^^^^^^^ @@ -483,7 +519,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:89:11 + --> $DIR/param-attrs-builtin-attrs.rs:122:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -492,7 +528,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:108:11 + --> $DIR/param-attrs-builtin-attrs.rs:182:11 | LL | #[must_use] | ^^^^^^^^ @@ -501,7 +537,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:114:11 + --> $DIR/param-attrs-builtin-attrs.rs:188:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -510,7 +546,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:174:11 + --> $DIR/param-attrs-builtin-attrs.rs:9:11 | LL | #[must_use] | ^^^^^^^^ @@ -519,7 +555,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:180:11 + --> $DIR/param-attrs-builtin-attrs.rs:15:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -527,5 +563,5 @@ LL | #[no_mangle] b: i32, = help: the `no_mangle` attribute can be applied to functions and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: aborting due to 64 previous errors; 16 warnings emitted +error: aborting due to 64 previous errors; 20 warnings emitted diff --git a/tests/ui/splat/splat-invalid.rs b/tests/ui/splat/splat-invalid.rs index 9a0101636a8b0..e30ac4a9af276 100644 --- a/tests/ui/splat/splat-invalid.rs +++ b/tests/ui/splat/splat-invalid.rs @@ -69,12 +69,14 @@ fn main() { let multisplat_arg_bad_: fn( #[rustc_splat] #[rustc_splat] + //~^ ERROR multiple `rustc_splat` attributes (u32, i8), ) = multisplat_arg_bad; let multisplat_arg_fn_bad_: fn( #[rustc_splat] //~^ ERROR multiple `#[rustc_splat]`s are not allowed in the same function argument list #[rustc_splat] + //~^ ERROR multiple `rustc_splat` attributes (u32, i8), #[rustc_splat] (u32, i8), ) = multisplat_arg_fn_bad; diff --git a/tests/ui/splat/splat-invalid.stderr b/tests/ui/splat/splat-invalid.stderr index f1c492bd3e37e..8681084a3c594 100644 --- a/tests/ui/splat/splat-invalid.stderr +++ b/tests/ui/splat/splat-invalid.stderr @@ -96,21 +96,21 @@ LL | fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multisplat = help: remove `#[rustc_splat]` from all but one argument error: multiple `#[rustc_splat]`s are not allowed in the same function argument list - --> $DIR/splat-invalid.rs:75:9 + --> $DIR/splat-invalid.rs:76:9 | LL | #[rustc_splat] | ^^^^^^^^^^^^^^ LL | LL | #[rustc_splat] | ^^^^^^^^^^^^^^ -LL | (u32, i8), +... LL | #[rustc_splat] (u32, i8), | ^^^^^^^^^^^^^^ | = help: remove `#[rustc_splat]` from all but one argument error: `...` and `#[rustc_splat]` are not allowed in the same function argument list - --> $DIR/splat-invalid.rs:82:47 + --> $DIR/splat-invalid.rs:84:47 | LL | let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; | ^^^^^^^^^^^^^^ ^^^ @@ -118,13 +118,13 @@ LL | let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ... = help: remove `#[rustc_splat]` or remove `...` error: `...` must be the last argument of a C-variadic function - --> $DIR/splat-invalid.rs:84:48 + --> $DIR/splat-invalid.rs:86:48 | LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; | ^^^ error: `...` and `#[rustc_splat]` are not allowed in the same function argument list - --> $DIR/splat-invalid.rs:84:48 + --> $DIR/splat-invalid.rs:86:48 | LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; | ^^^ ^^^^^^^^^^^^^^ @@ -155,6 +155,30 @@ note: attribute also specified here LL | #[rustc_splat] | ^^^^^^^^^^^^^^ +error: multiple `rustc_splat` attributes + --> $DIR/splat-invalid.rs:71:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/splat-invalid.rs:70:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ + +error: multiple `rustc_splat` attributes + --> $DIR/splat-invalid.rs:78:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/splat-invalid.rs:76:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ + error[E0053]: method `has_splat` has an incompatible type for trait --> $DIR/splat-invalid.rs:59:5 | @@ -183,6 +207,6 @@ LL | fn no_splat(_: (u32, f64)); = note: expected signature `fn((_, _))` found signature `fn(#[rustc_splat] (_, _))` -error: aborting due to 19 previous errors +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0053`.