From 8b1f85caede44808e62542cfdff04787d70f8f7f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 26 Apr 2022 00:13:24 +0100 Subject: [PATCH 01/23] Windows: Iterative `remove_dir_all` This will allow better strategies for use of memory and File handles. However, fully taking advantage of that is left to future work. --- library/std/src/sys/windows/fs.rs | 144 ++++++++++++++---------------- 1 file changed, 67 insertions(+), 77 deletions(-) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 95903899297b6..618cbbb1817ec 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -680,7 +680,7 @@ impl<'a> DirBuffIter<'a> { } } impl<'a> Iterator for DirBuffIter<'a> { - type Item = &'a [u16]; + type Item = (&'a [u16], bool); fn next(&mut self) -> Option { use crate::mem::size_of; let buffer = &self.buffer?[self.cursor..]; @@ -689,14 +689,16 @@ impl<'a> Iterator for DirBuffIter<'a> { // SAFETY: The buffer contains a `FILE_ID_BOTH_DIR_INFO` struct but the // last field (the file name) is unsized. So an offset has to be // used to get the file name slice. - let (name, next_entry) = unsafe { + let (name, is_directory, next_entry) = unsafe { let info = buffer.as_ptr().cast::(); let next_entry = (*info).NextEntryOffset as usize; let name = crate::slice::from_raw_parts( (*info).FileName.as_ptr().cast::(), (*info).FileNameLength as usize / size_of::(), ); - (name, next_entry) + let is_directory = ((*info).FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) != 0; + + (name, is_directory, next_entry) }; if next_entry == 0 { @@ -709,7 +711,7 @@ impl<'a> Iterator for DirBuffIter<'a> { const DOT: u16 = b'.' as u16; match name { [DOT] | [DOT, DOT] => self.next(), - _ => Some(name), + _ => Some((name, is_directory)), } } } @@ -994,89 +996,77 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 { return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _)); } - let mut delete: fn(&File) -> io::Result<()> = File::posix_delete; - let result = match delete(&file) { - Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => { - match remove_dir_all_recursive(&file, delete) { - // Return unexpected errors. - Err(e) if e.kind() != io::ErrorKind::DirectoryNotEmpty => return Err(e), - result => result, - } - } - // If POSIX delete is not supported for this filesystem then fallback to win32 delete. - Err(e) - if e.raw_os_error() == Some(c::ERROR_NOT_SUPPORTED as i32) - || e.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) => - { - delete = File::win32_delete; - Err(e) - } - result => result, - }; - if result.is_ok() { - Ok(()) - } else { - // This is a fallback to make sure the directory is actually deleted. - // Otherwise this function is prone to failing with `DirectoryNotEmpty` - // due to possible delays between marking a file for deletion and the - // file actually being deleted from the filesystem. - // - // So we retry a few times before giving up. - for _ in 0..5 { - match remove_dir_all_recursive(&file, delete) { - Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {} - result => return result, + + match remove_dir_all_iterative(&file, File::posix_delete) { + Err(e) => { + if let Some(code) = e.raw_os_error() { + match code as u32 { + // If POSIX delete is not supported for this filesystem then fallback to win32 delete. + c::ERROR_NOT_SUPPORTED + | c::ERROR_INVALID_FUNCTION + | c::ERROR_INVALID_PARAMETER => { + remove_dir_all_iterative(&file, File::win32_delete) + } + _ => Err(e), + } + } else { + Err(e) } } - // Try one last time. - delete(&file) + ok => ok, } } -fn remove_dir_all_recursive(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> { +fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> { let mut buffer = DirBuff::new(); - let mut restart = true; - // Fill the buffer and iterate the entries. - while f.fill_dir_buff(&mut buffer, restart)? { - for name in buffer.iter() { - // Open the file without following symlinks and try deleting it. - // We try opening will all needed permissions and if that is denied - // fallback to opening without `FILE_LIST_DIRECTORY` permission. - // Note `SYNCHRONIZE` permission is needed for synchronous access. - let mut result = - open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY); - if matches!(&result, Err(e) if e.kind() == io::ErrorKind::PermissionDenied) { - result = open_link_no_reparse(&f, name, c::SYNCHRONIZE | c::DELETE); - } - match result { - Ok(file) => match delete(&file) { - Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => { - // Iterate the directory's files. - // Ignore `DirectoryNotEmpty` errors here. They will be - // caught when `remove_dir_all` tries to delete the top - // level directory. It can then decide if to retry or not. - match remove_dir_all_recursive(&file, delete) { - Err(e) if e.kind() == io::ErrorKind::DirectoryNotEmpty => {} - result => result?, - } + let mut dirlist = vec![f.duplicate()?]; + + // FIXME: This is a hack so we can push to the dirlist vec after borrowing from it. + fn copy_handle(f: &File) -> mem::ManuallyDrop { + unsafe { mem::ManuallyDrop::new(File::from_raw_handle(f.as_raw_handle())) } + } + + while let Some(dir) = dirlist.last() { + let dir = copy_handle(dir); + + // Fill the buffer and iterate the entries. + let more_data = dir.fill_dir_buff(&mut buffer, false)?; + for (name, is_directory) in buffer.iter() { + if is_directory { + let child_dir = open_link_no_reparse( + &dir, + name, + c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY, + )?; + dirlist.push(child_dir); + } else { + const MAX_RETRIES: u32 = 10; + for i in 1..=MAX_RETRIES { + let result = open_link_no_reparse(&dir, name, c::SYNCHRONIZE | c::DELETE); + match result { + Ok(f) => delete(&f)?, + // Already deleted, so skip. + Err(e) if e.kind() == io::ErrorKind::NotFound => break, + // Retry a few times if the file is locked or a delete is already in progress. + Err(e) + if i < MAX_RETRIES + && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) + || e.raw_os_error() + == Some(c::ERROR_SHARING_VIOLATION as _)) => {} + // Otherwise return the error. + Err(e) => return Err(e), } - result => result?, - }, - // Ignore error if a delete is already in progress or the file - // has already been deleted. It also ignores sharing violations - // (where a file is locked by another process) as these are - // usually temporary. - Err(e) - if e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) - || e.kind() == io::ErrorKind::NotFound - || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {} - Err(e) => return Err(e), + } + } + } + // If there were no more files then delete the directory. + if !more_data { + if let Some(dir) = dirlist.pop() { + delete(&dir)?; } } - // Continue reading directory entries without restarting from the beginning, - restart = false; } - delete(&f) + Ok(()) } pub fn readlink(path: &Path) -> io::Result { From 8dc4696b3b8e048ddbc4a25953cccb567b27570c Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 26 Apr 2022 01:08:46 +0100 Subject: [PATCH 02/23] Retry deleting a directory It's possible that a file in the directory is pending deletion. In that case we might succeed after a few attempts. --- library/std/src/sys/windows/fs.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 618cbbb1817ec..e6f0f0f302391 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1018,6 +1018,10 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { } fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> { + // When deleting files we may loop this many times when certain error conditions occur. + // This allows remove_dir_all to succeed when the error is temporary. + const MAX_RETRIES: u32 = 10; + let mut buffer = DirBuff::new(); let mut dirlist = vec![f.duplicate()?]; @@ -1040,7 +1044,6 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io )?; dirlist.push(child_dir); } else { - const MAX_RETRIES: u32 = 10; for i in 1..=MAX_RETRIES { let result = open_link_no_reparse(&dir, name, c::SYNCHRONIZE | c::DELETE); match result { @@ -1062,7 +1065,17 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io // If there were no more files then delete the directory. if !more_data { if let Some(dir) = dirlist.pop() { - delete(&dir)?; + // Retry deleting a few times in case we need to wait for a file to be deleted. + for i in 1..=MAX_RETRIES { + let result = delete(&dir); + if let Err(e) = result { + if i == MAX_RETRIES || e.kind() != io::ErrorKind::DirectoryNotEmpty { + return Err(e); + } + } else { + break; + } + } } } } From d579665bd1e1649c9597cdaf3da3c2ca7f54e793 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 28 Apr 2022 18:46:33 +0100 Subject: [PATCH 03/23] Yield the thread when waiting to delete a file --- library/std/src/sys/windows/fs.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index e6f0f0f302391..5e055307c291e 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -14,6 +14,7 @@ use crate::sys::handle::Handle; use crate::sys::time::SystemTime; use crate::sys::{c, cvt}; use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::thread; use super::path::maybe_verbatim; use super::to_u16s; @@ -1059,6 +1060,7 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io // Otherwise return the error. Err(e) => return Err(e), } + thread::yield_now(); } } } @@ -1072,6 +1074,7 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io if i == MAX_RETRIES || e.kind() != io::ErrorKind::DirectoryNotEmpty { return Err(e); } + thread::yield_now(); } else { break; } From ab3a2a024fb58d5ad3e893f1d5694468b187b2d3 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Tue, 29 Mar 2022 15:31:42 +0200 Subject: [PATCH 04/23] Unify copying data from enclave to userspace --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 3792a3820a534..9a64b7e4b150c 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -225,13 +225,9 @@ where /// Copies `val` into freshly allocated space in user memory. pub fn new_from_enclave(val: &T) -> Self { unsafe { - let ret = Self::new_uninit_bytes(mem::size_of_val(val)); - ptr::copy( - val as *const T as *const u8, - ret.0.as_ptr() as *mut u8, - mem::size_of_val(val), - ); - ret + let mut user = Self::new_uninit_bytes(mem::size_of_val(val)); + user.copy_from_enclave(val); + user } } From 531752f39ab662a73e7ab580bf8a06c6bfeef486 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Mon, 28 Mar 2022 14:34:16 +0200 Subject: [PATCH 05/23] Mitigate MMIO stale data vulnerabilities Intel Security Advisory: https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html --- .../std/src/sys/sgx/abi/usercalls/alloc.rs | 100 +++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 9a64b7e4b150c..b37e9b257edb4 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -1,13 +1,15 @@ #![allow(unused)] +use crate::arch::asm; use crate::cell::UnsafeCell; +use crate::convert::TryInto; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; use crate::ptr::{self, NonNull}; use crate::slice; use crate::slice::SliceIndex; -use super::super::mem::is_user_range; +use super::super::mem::{is_enclave_range, is_user_range}; use fortanix_sgx_abi::*; /// A type that can be safely read from or written to userspace. @@ -300,6 +302,100 @@ where } } +/// Copies `len` bytes of data from enclave pointer `src` to userspace `dst` +/// +/// This function mitigates stale data vulnerabilities +/// https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html +/// +/// # Panics +/// This function panics if: +/// +/// * The `src` pointer is null +/// * The `dst` pointer is null +/// * The `src` memory range is not in enclave memory +/// * The `dst` memory range is not in user memory +unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) { + unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) { + unsafe { + let seg_sel: u16 = 0; + for off in 0..len { + asm!(" + mov %ds, ({seg_sel}) + verw ({seg_sel}) + movb {val}, ({dst}) + mfence + lfence + ", + val = in(reg_byte) *src.offset(off as isize), + dst = in(reg) dst.offset(off as isize), + seg_sel = in(reg) &seg_sel, + options(nostack, att_syntax) + ); + } + } + } + + unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) { + unsafe { + asm!( + "rep movsq (%rsi), (%rdi)", + inout("rcx") len / 8 => _, + inout("rdi") dst => _, + inout("rsi") src => _, + options(att_syntax, nostack, preserves_flags) + ); + } + } + assert!(!src.is_null()); + assert!(!dst.is_null()); + assert!(is_enclave_range(src, len)); + assert!(is_user_range(dst, len)); + assert!(len < isize::MAX as usize); + assert!(!(src as usize).overflowing_add(len).1); + assert!(!(dst as usize).overflowing_add(len).1); + + if len < 8 { + // Can't align on 8 byte boundary: copy safely byte per byte + unsafe { + copy_bytewise_to_userspace(src, dst, len); + } + } else if len % 8 == 0 && dst as usize % 8 == 0 { + // Copying 8-byte aligned quadwords: copy quad word per quad word + unsafe { + copy_aligned_quadwords_to_userspace(src, dst, len); + } + } else { + // Split copies into three parts: + // +--------+ + // | small0 | Chunk smaller than 8 bytes + // +--------+ + // | big | Chunk 8-byte aligned, and size a multiple of 8 bytes + // +--------+ + // | small1 | Chunk smaller than 8 bytes + // +--------+ + + unsafe { + // Copy small0 + let small0_size = (8 - dst as usize % 8) as u8; + let small0_src = src; + let small0_dst = dst; + copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _); + + // Copy big + let small1_size = ((len - small0_size as usize) % 8) as u8; + let big_size = len - small0_size as usize - small1_size as usize; + let big_src = src.offset(small0_size as _); + let big_dst = dst.offset(small0_size as _); + copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size); + + // Copy small1 + let small1_src = src.offset(big_size as isize + small0_size as isize); + let small1_dst = dst.offset(big_size as isize + small0_size as isize); + copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _); + } + } +} + #[unstable(feature = "sgx_platform", issue = "56975")] impl UserRef where @@ -348,7 +444,7 @@ where pub fn copy_from_enclave(&mut self, val: &T) { unsafe { assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get())); - ptr::copy( + copy_to_userspace( val as *const T as *const u8, self.0.get() as *mut T as *mut u8, mem::size_of_val(val), From 6f7d1937e20edf00ea2b5d7c2c8ce2dab2830452 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 23 Mar 2022 10:03:00 +0100 Subject: [PATCH 06/23] Ensure userspace allocation is 8-byte aligned --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index b37e9b257edb4..4c1f279857f9c 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -2,6 +2,7 @@ use crate::arch::asm; use crate::cell::UnsafeCell; +use crate::cmp; use crate::convert::TryInto; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut}; @@ -212,7 +213,9 @@ where unsafe { // Mustn't call alloc with size 0. let ptr = if size > 0 { - rtunwrap!(Ok, super::alloc(size, T::align_of())) as _ + // `copy_to_userspace` is more efficient when data is 8-byte aligned + let alignment = cmp::max(T::align_of(), 8); + rtunwrap!(Ok, super::alloc(size, alignment)) as _ } else { T::align_of() as _ // dangling pointer ok for size 0 }; From a27aaceee91c1b3a7b4f9b070054290e8530e1bd Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Tue, 22 Mar 2022 17:34:44 +0100 Subject: [PATCH 07/23] Test `copy_to_userspace` function --- .../std/src/sys/sgx/abi/usercalls/alloc.rs | 2 +- library/std/src/sys/sgx/abi/usercalls/mod.rs | 2 ++ .../std/src/sys/sgx/abi/usercalls/tests.rs | 30 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 library/std/src/sys/sgx/abi/usercalls/tests.rs diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 4c1f279857f9c..4ac27e85f8ba8 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -317,7 +317,7 @@ where /// * The `dst` pointer is null /// * The `src` memory range is not in enclave memory /// * The `dst` memory range is not in user memory -unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) { +pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) { unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) { unsafe { let seg_sel: u16 = 0; diff --git a/library/std/src/sys/sgx/abi/usercalls/mod.rs b/library/std/src/sys/sgx/abi/usercalls/mod.rs index 2f99abba77667..79d1db5e1c50d 100644 --- a/library/std/src/sys/sgx/abi/usercalls/mod.rs +++ b/library/std/src/sys/sgx/abi/usercalls/mod.rs @@ -6,6 +6,8 @@ use crate::time::{Duration, Instant}; pub(crate) mod alloc; #[macro_use] pub(crate) mod raw; +#[cfg(test)] +mod tests; use self::raw::*; diff --git a/library/std/src/sys/sgx/abi/usercalls/tests.rs b/library/std/src/sys/sgx/abi/usercalls/tests.rs new file mode 100644 index 0000000000000..cbf7d7d54f7a2 --- /dev/null +++ b/library/std/src/sys/sgx/abi/usercalls/tests.rs @@ -0,0 +1,30 @@ +use super::alloc::copy_to_userspace; +use super::alloc::User; + +#[test] +fn test_copy_function() { + let mut src = [0u8; 100]; + let mut dst = User::<[u8]>::uninitialized(100); + + for i in 0..src.len() { + src[i] = i as _; + } + + for size in 0..48 { + // For all possible alignment + for offset in 0..8 { + // overwrite complete dst + dst.copy_from_enclave(&[0u8; 100]); + + // Copy src[0..size] to dst + offset + unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().offset(offset), size) }; + + // Verify copy + for byte in 0..size { + unsafe { + assert_eq!(*dst.as_ptr().offset(offset + byte as isize), src[byte as usize]); + } + } + } + } +} From d72294491c5d28449c49b884b620cc24b3cf010f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 16 Jun 2022 11:23:31 +0200 Subject: [PATCH 08/23] Leak pthreax_mutex_t when it's dropped while locked. --- .../std/src/sys/unix/locks/pthread_mutex.rs | 20 ++++++++++++++++++- library/std/src/sys_common/lazy_box.rs | 19 +++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/unix/locks/pthread_mutex.rs b/library/std/src/sys/unix/locks/pthread_mutex.rs index 916e898d8906e..98afee69ba622 100644 --- a/library/std/src/sys/unix/locks/pthread_mutex.rs +++ b/library/std/src/sys/unix/locks/pthread_mutex.rs @@ -1,5 +1,5 @@ use crate::cell::UnsafeCell; -use crate::mem::MaybeUninit; +use crate::mem::{forget, MaybeUninit}; use crate::sys::cvt_nz; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; @@ -23,6 +23,24 @@ impl LazyInit for Mutex { unsafe { mutex.init() }; mutex } + + fn destroy(mutex: Box) { + // We're not allowed to pthread_mutex_destroy a locked mutex, + // so check first if it's unlocked. + if unsafe { mutex.try_lock() } { + unsafe { mutex.unlock() }; + drop(mutex); + } else { + // The mutex is locked. This happens if a MutexGuard is leaked. + // In this case, we just leak the Mutex too. + forget(mutex); + } + } + + fn cancel_init(_: Box) { + // In this case, we can just drop it without any checks, + // since it cannot have been locked yet. + } } impl Mutex { diff --git a/library/std/src/sys_common/lazy_box.rs b/library/std/src/sys_common/lazy_box.rs index 647c13d243724..63c3316bdeb28 100644 --- a/library/std/src/sys_common/lazy_box.rs +++ b/library/std/src/sys_common/lazy_box.rs @@ -21,8 +21,21 @@ pub(crate) trait LazyInit { /// /// It might be called more than once per LazyBox, as multiple threads /// might race to initialize it concurrently, each constructing and initializing - /// their own box. (All but one of them will be destroyed right after.) + /// their own box. All but one of them will be passed to `cancel_init` right after. fn init() -> Box; + + /// Any surplus boxes from `init()` that lost the initialization race + /// are passed to this function for disposal. + /// + /// The default implementation calls destroy(). + fn cancel_init(x: Box) { + Self::destroy(x); + } + + /// This is called to destroy a used box. + /// + /// The default implementation just drops it. + fn destroy(_: Box) {} } impl LazyBox { @@ -45,7 +58,7 @@ impl LazyBox { Err(ptr) => { // Lost the race to another thread. // Drop the box we created, and use the one from the other thread instead. - drop(unsafe { Box::from_raw(new_ptr) }); + T::cancel_init(unsafe { Box::from_raw(new_ptr) }); ptr } } @@ -71,7 +84,7 @@ impl Drop for LazyBox { fn drop(&mut self) { let ptr = *self.ptr.get_mut(); if !ptr.is_null() { - drop(unsafe { Box::from_raw(ptr) }); + T::destroy(unsafe { Box::from_raw(ptr) }); } } } From e642c5987e1885a6ea9b0f1527810a72bdcdeb3f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 19 Jun 2022 12:53:12 +0200 Subject: [PATCH 09/23] Leak pthreax_rwlock_t when it's dropped while locked. --- library/std/src/sys/unix/locks/pthread_rwlock.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/std/src/sys/unix/locks/pthread_rwlock.rs b/library/std/src/sys/unix/locks/pthread_rwlock.rs index 75e5759c7879d..adfe2a88338f5 100644 --- a/library/std/src/sys/unix/locks/pthread_rwlock.rs +++ b/library/std/src/sys/unix/locks/pthread_rwlock.rs @@ -1,4 +1,5 @@ use crate::cell::UnsafeCell; +use crate::mem::forget; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; @@ -17,6 +18,21 @@ impl LazyInit for RwLock { fn init() -> Box { Box::new(Self::new()) } + + fn destroy(mut rwlock: Box) { + // We're not allowed to pthread_rwlock_destroy a locked rwlock, + // so check first if it's unlocked. + if *rwlock.write_locked.get_mut() || *rwlock.num_readers.get_mut() != 0 { + // The rwlock is locked. This happens if a RwLock{Read,Write}Guard is leaked. + // In this case, we just leak the RwLock too. + forget(rwlock); + } + } + + fn cancel_init(_: Box) { + // In this case, we can just drop it without any checks, + // since it cannot have been locked yet. + } } impl RwLock { From 6ac6866bec092e0c2a3e0fc4aaf14b015b859a57 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 20 Jun 2022 21:10:43 +0100 Subject: [PATCH 10/23] Reverse folder hierarchy #91318 introduced a trait for infallible folders distinct from the fallible version. For some reason (completely unfathomable to me now that I look at it with fresh eyes), the infallible trait was a supertrait of the fallible one: that is, all fallible folders were required to also be infallible. Moreover the `Error` associated type was defined on the infallible trait! It's so absurd that it has me questioning whether I was entirely sane. This trait reverses the hierarchy, so that the fallible trait is a supertrait of the infallible one: all infallible folders are required to also be fallible (which is a trivial blanket implementation). This of course makes much more sense! It also enables the `Error` associated type to sit on the fallible trait, where it sensibly belongs. There is one downside however: folders expose a `tcx` accessor method. Since the blanket fallible implementation for infallible folders only has access to a generic `F: TypeFolder`, we need that trait to expose such an accessor to which we can delegate. Alternatively it's possible to extract that accessor into a separate `HasTcx` trait (or similar) that would then be a supertrait of both the fallible and infallible folder traits: this would ensure that there's only one unambiguous `tcx` method, at the cost of a little additional boilerplate. If desired, I can submit that as a separate PR. r? @jackh726 --- compiler/rustc_infer/src/infer/resolve.rs | 6 +-- compiler/rustc_middle/src/ty/fold.rs | 49 +++++++------------ .../src/ty/normalize_erasing_regions.rs | 4 +- compiler/rustc_middle/src/ty/subst.rs | 2 +- .../src/traits/query/normalize.rs | 6 +-- 5 files changed, 25 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index d830000b65f69..1f3cb401314d6 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -92,7 +92,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { .borrow_mut() .unwrap_region_constraints() .opportunistic_resolve_var(rid); - self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved)) + TypeFolder::tcx(self).reuse_or_mk_region(r, ty::ReVar(resolved)) } _ => r, } @@ -179,15 +179,13 @@ struct FullTypeResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, } -impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { +impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { type Error = FixupError<'tcx>; fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } -} -impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { if !t.needs_infer() { Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 31b8fa1ce956f..71445603e2f15 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -241,58 +241,37 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { /// a blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. -pub trait TypeFolder<'tcx>: Sized { - type Error = !; - +pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, - Self: TypeFolder<'tcx, Error = !>, { t.super_fold_with(self) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> - where - Self: TypeFolder<'tcx, Error = !>, - { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { t.super_fold_with(self) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> - where - Self: TypeFolder<'tcx, Error = !>, - { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { r.super_fold_with(self) } - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> - where - Self: TypeFolder<'tcx, Error = !>, - { + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { c.super_fold_with(self) } - fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> - where - Self: TypeFolder<'tcx, Error = !>, - { + fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { uv.super_fold_with(self) } - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> - where - Self: TypeFolder<'tcx, Error = !>, - { + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { p.super_fold_with(self) } - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> - where - Self: TypeFolder<'tcx, Error = !>, - { + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { bug!("most type folders should not be folding MIR datastructures: {:?}", c) } } @@ -304,7 +283,11 @@ pub trait TypeFolder<'tcx>: Sized { /// A blanket implementation of this trait (that defers to the relevant /// method of [`TypeFolder`]) is provided for all infallible folders in /// order to ensure the two APIs are coherent. -pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> { +pub trait FallibleTypeFolder<'tcx>: Sized { + type Error; + + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> where T: TypeFoldable<'tcx>, @@ -350,8 +333,14 @@ pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> { // delegates to infallible methods to ensure coherence. impl<'tcx, F> FallibleTypeFolder<'tcx> for F where - F: TypeFolder<'tcx, Error = !>, + F: TypeFolder<'tcx>, { + type Error = !; + + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + TypeFolder::tcx(self) + } + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> where T: TypeFoldable<'tcx>, diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 9bbbd7e2f7c5e..66a0a192a87c1 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -228,15 +228,13 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { } } -impl<'tcx> TypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { +impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { type Error = NormalizationError<'tcx>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } -} -impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { match self.try_normalize_generic_arg_after_erasing_regions(ty.into()) { Ok(t) => Ok(t.expect_ty()), diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index ad2898ccd67ba..1417c8a511c24 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -705,7 +705,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> { return val; } - let result = ty::fold::shift_vars(self.tcx(), val, self.binders_passed); + let result = ty::fold::shift_vars(TypeFolder::tcx(self), val, self.binders_passed); debug!("shift_vars: shifted result = {:?}", result); result diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index b80a27eb07d06..7f15b683fda3e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; use rustc_middle::mir; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; @@ -162,15 +162,13 @@ struct QueryNormalizer<'cx, 'tcx> { universes: Vec>, } -impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { +impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { type Error = NoSolution; fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { self.infcx.tcx } -} -impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { fn try_fold_binder>( &mut self, t: ty::Binder<'tcx, T>, From 75203eef19268d1fbef23cc1fa9c74fecfcb1405 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 21 Jun 2022 12:15:05 +0100 Subject: [PATCH 11/23] Remove unecessary references to TypeFolder::Error --- compiler/rustc_middle/src/ty/fold.rs | 36 ++++++++++++---------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 71445603e2f15..b1b8bc13e2f13 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -86,7 +86,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { /// A convenient alternative to `try_fold_with` for use with infallible /// folders. Do not override this method, to ensure coherence with /// `try_fold_with`. - fn fold_with>(self, folder: &mut F) -> Self { + fn fold_with>(self, folder: &mut F) -> Self { self.try_fold_with(folder).into_ok() } @@ -216,7 +216,7 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { /// A convenient alternative to `try_super_fold_with` for use with /// infallible folders. Do not override this method, to ensure coherence /// with `try_super_fold_with`. - fn super_fold_with>(self, folder: &mut F) -> Self { + fn super_fold_with>(self, folder: &mut F) -> Self { self.try_super_fold_with(folder).into_ok() } @@ -229,16 +229,13 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; } -/// This trait is implemented for every folding traversal. There is a fold -/// method defined for every type of interest. Each such method has a default -/// that does an "identity" fold. Implementations of these methods often fall -/// back to a `super_fold_with` method if the primary argument doesn't -/// satisfy a particular condition. +/// This trait is implemented for every infallible folding traversal. There is +/// a fold method defined for every type of interest. Each such method has a +/// default that does an "identity" fold. Implementations of these methods +/// often fall back to a `super_fold_with` method if the primary argument +/// doesn't satisfy a particular condition. /// -/// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`] -/// associated type is something other than the default `!`) then -/// [`FallibleTypeFolder`] should be implemented manually. Otherwise, -/// a blanket implementation of [`FallibleTypeFolder`] will defer to +/// A blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { @@ -341,43 +338,40 @@ where TypeFolder::tcx(self) } - fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, !> where T: TypeFoldable<'tcx>, { Ok(self.fold_binder(t)) } - fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { Ok(self.fold_ty(t)) } - fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { Ok(self.fold_region(r)) } - fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, Self::Error> { + fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, !> { Ok(self.fold_const(c)) } fn try_fold_unevaluated( &mut self, c: ty::Unevaluated<'tcx>, - ) -> Result, Self::Error> { + ) -> Result, !> { Ok(self.fold_unevaluated(c)) } - fn try_fold_predicate( - &mut self, - p: ty::Predicate<'tcx>, - ) -> Result, Self::Error> { + fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result, !> { Ok(self.fold_predicate(p)) } fn try_fold_mir_const( &mut self, c: mir::ConstantKind<'tcx>, - ) -> Result, Self::Error> { + ) -> Result, !> { Ok(self.fold_mir_const(c)) } } From 402dceba99bed5efa5774d6238c13dfce4670db1 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 21 Jun 2022 00:43:20 +0900 Subject: [PATCH 12/23] point to type param definition when not finding variant, method and assoc type use `def_ident_span` , `body_owner_def_id` instead of `in_progress_typeck_results`, `guess_head_span` use `body_id.owner` directly add description to label --- .../rustc_typeck/src/check/method/suggest.rs | 36 +++++++++++-------- .../associated-item-enum.stderr | 6 ++-- .../ui/async-await/pin-needed-to-poll.stderr | 2 +- src/test/ui/bogus-tag.stderr | 2 +- .../issue-18343.stderr | 2 +- .../issue-2392.stderr | 22 ++++++------ .../issue-32128.stderr | 2 +- .../private-field.stderr | 2 +- .../generic_const_exprs/issue-69654.stderr | 2 +- .../generic_const_exprs/issue-80742.stderr | 18 ++++------ .../invalid-const-arg-for-type-param.stderr | 2 +- .../const-needs_drop-monomorphic.stderr | 2 +- src/test/ui/copy-a-resource.stderr | 2 +- .../derives/derive-assoc-type-not-impl.stderr | 4 +-- src/test/ui/derives/issue-91492.stderr | 2 +- src/test/ui/derives/issue-91550.stderr | 6 ++-- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- .../dont-suggest-private-trait-method.stderr | 2 +- src/test/ui/error-codes/E0599.stderr | 2 +- ...hod-unsatified-assoc-type-predicate.stderr | 4 +-- src/test/ui/hrtb/issue-30786.stderr | 8 ++--- ...e-21659-show-relevant-trait-impls-3.stderr | 2 +- .../ui/impl-trait/issues/issue-62742.stderr | 2 +- .../method-suggestion-no-duplication.stderr | 2 +- .../no-method-suggested-traits.stderr | 6 ++-- .../ui/infinite/infinite-autoderef.stderr | 2 +- src/test/ui/issues/issue-19692.stderr | 2 +- src/test/ui/issues/issue-22933-2.stderr | 2 +- src/test/ui/issues/issue-23173.stderr | 8 ++--- src/test/ui/issues/issue-23217.stderr | 2 +- src/test/ui/issues/issue-2823.stderr | 2 +- src/test/ui/issues/issue-28971.stderr | 2 +- src/test/ui/issues/issue-38919.stderr | 2 ++ src/test/ui/issues/issue-41880.stderr | 2 +- src/test/ui/issues/issue-64430.stderr | 2 +- src/test/ui/issues/issue-7950.stderr | 2 +- src/test/ui/lexical-scopes.stderr | 2 ++ .../ui/methods/method-call-err-msg.stderr | 4 +-- ...ethod-not-found-generic-arg-elision.stderr | 14 ++++---- src/test/ui/noncopyable-class.stderr | 2 +- src/test/ui/parser/emoji-identifiers.stderr | 2 +- .../uniform-paths/issue-87932.stderr | 2 +- ...point-at-arbitrary-self-type-method.stderr | 2 +- ...at-arbitrary-self-type-trait-method.stderr | 2 +- src/test/ui/span/issue-7575.stderr | 4 ++- ...pecialization-trait-not-implemented.stderr | 4 +-- .../derive-trait-for-method-call.stderr | 6 ++-- .../dont-wrap-ambiguous-receivers.stderr | 2 +- .../ui/suggestions/field-has-method.stderr | 2 +- ...it-with-missing-trait-bounds-in-arg.stderr | 2 ++ src/test/ui/suggestions/issue-21673.stderr | 2 ++ ...uggest-assoc-fn-call-with-turbofish.stderr | 2 +- .../ui/suggestions/suggest-methods.stderr | 2 +- .../ui/suggestions/suggest-variants.stderr | 6 ++-- .../suggestions/use-placement-typeck.stderr | 2 +- src/test/ui/traits/issue-3973.stderr | 2 +- ...e-65284-suggest-generic-trait-bound.stderr | 2 ++ src/test/ui/traits/issue-95898.stderr | 2 ++ src/test/ui/traits/item-privacy.stderr | 12 +++---- ...licitly-unimplemented-error-message.stderr | 4 +-- .../point-at-type-parameter-definition.rs | 17 +++++++++ .../point-at-type-parameter-definition.stderr | 12 +++++++ .../union-derive-clone.mirunsafeck.stderr | 4 +-- .../union-derive-clone.thirunsafeck.stderr | 4 +-- 64 files changed, 168 insertions(+), 125 deletions(-) create mode 100644 src/test/ui/typeck/point-at-type-parameter-definition.rs create mode 100644 src/test/ui/typeck/point-at-type-parameter-definition.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 8880049371e58..5684979eab777 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -346,19 +346,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if let Some(def) = actual.ty_adt_def() { - if let Some(full_sp) = tcx.hir().span_if_local(def.did()) { - let def_sp = tcx.sess.source_map().guess_head_span(full_sp); - err.span_label( - def_sp, - format!( - "{} `{}` not found {}", - item_kind, - item_name, - if def.is_enum() && !is_method { "here" } else { "for this" } - ), - ); + let ty_span = match actual.kind() { + ty::Param(param_type) => { + let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); + let type_param = generics.type_param(param_type, self.tcx); + Some(self.tcx.def_span(type_param.def_id)) + } + ty::Adt(def, _) if def.did().is_local() => { + tcx.def_ident_span(def.did()).map(|span| span) } + _ => None, + }; + + if let Some(span) = ty_span { + err.span_label( + span, + format!( + "{item_kind} `{item_name}` not found for this {}", + actual.prefix_string(self.tcx) + ), + ); } if self.is_fn_ty(rcvr_ty, span) { @@ -1951,9 +1958,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }; // Obtain the span for `param` and use it for a structured suggestion. - if let (Some(param), Some(table)) = (param_type, self.in_progress_typeck_results) { - let table_owner = table.borrow().hir_owner; - let generics = self.tcx.generics_of(table_owner.to_def_id()); + if let Some(param) = param_type { + let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); let type_param = generics.type_param(param, self.tcx); let hir = self.tcx.hir(); if let Some(def_id) = type_param.def_id.as_local() { diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr index d52b2b36c7bcc..a09b64aa2f5a5 100644 --- a/src/test/ui/associated-item/associated-item-enum.stderr +++ b/src/test/ui/associated-item/associated-item-enum.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `mispellable` found for enum ` --> $DIR/associated-item-enum.rs:17:11 | LL | enum Enum { Variant } - | --------- variant or associated item `mispellable` not found here + | ---- variant or associated item `mispellable` not found for this enum ... LL | Enum::mispellable(); | ^^^^^^^^^^^ @@ -14,7 +14,7 @@ error[E0599]: no variant or associated item named `mispellable_trait` found for --> $DIR/associated-item-enum.rs:18:11 | LL | enum Enum { Variant } - | --------- variant or associated item `mispellable_trait` not found here + | ---- variant or associated item `mispellable_trait` not found for this enum ... LL | Enum::mispellable_trait(); | ^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ error[E0599]: no variant or associated item named `MISPELLABLE` found for enum ` --> $DIR/associated-item-enum.rs:19:11 | LL | enum Enum { Variant } - | --------- variant or associated item `MISPELLABLE` not found here + | ---- variant or associated item `MISPELLABLE` not found for this enum ... LL | Enum::MISPELLABLE; | ^^^^^^^^^^^ diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr index c47ec5dddb6e2..ba22b7aaf9828 100644 --- a/src/test/ui/async-await/pin-needed-to-poll.stderr +++ b/src/test/ui/async-await/pin-needed-to-poll.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `poll` found for struct `Sleep` in the current sco --> $DIR/pin-needed-to-poll.rs:42:20 | LL | struct Sleep; - | ------------- method `poll` not found for this + | ----- method `poll` not found for this struct ... LL | self.sleep.poll(cx) | ^^^^ method not found in `Sleep` diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr index cb3199e7c886e..b215adfa593bd 100644 --- a/src/test/ui/bogus-tag.stderr +++ b/src/test/ui/bogus-tag.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Hsl` found for enum `Color` i --> $DIR/bogus-tag.rs:7:16 | LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } - | ---------- variant or associated item `Hsl` not found here + | ----- variant or associated item `Hsl` not found for this enum ... LL | Color::Hsl(h, s, l) => { println!("hsl"); } | ^^^ variant or associated item not found in `Color` diff --git a/src/test/ui/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr index 2f67c11ad1f5d..a6d4e80a50c05 100644 --- a/src/test/ui/confuse-field-and-method/issue-18343.stderr +++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-18343.rs:7:7 | LL | struct Obj where F: FnMut() -> u32 { - | ------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | o.closure(); | ^^^^^^^ field, not a method diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr index a37e132d36429..795d0e286b3d3 100644 --- a/src/test/ui/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:36:15 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | o_closure.closure(); | ^^^^^^^ field, not a method @@ -16,7 +16,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren --> $DIR/issue-2392.rs:38:15 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `not_closure` not found for this + | --- method `not_closure` not found for this struct ... LL | o_closure.not_closure(); | ^^^^^^^^^^^-- help: remove the arguments @@ -27,7 +27,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:42:12 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | o_func.closure(); | ^^^^^^^ field, not a method @@ -41,7 +41,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the --> $DIR/issue-2392.rs:45:14 | LL | struct BoxedObj { - | --------------- method `boxed_closure` not found for this + | -------- method `boxed_closure` not found for this struct ... LL | boxed_fn.boxed_closure(); | ^^^^^^^^^^^^^ field, not a method @@ -55,7 +55,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the --> $DIR/issue-2392.rs:48:19 | LL | struct BoxedObj { - | --------------- method `boxed_closure` not found for this + | -------- method `boxed_closure` not found for this struct ... LL | boxed_closure.boxed_closure(); | ^^^^^^^^^^^^^ field, not a method @@ -69,7 +69,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:53:12 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | w.wrap.closure(); | ^^^^^^^ field, not a method @@ -83,7 +83,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren --> $DIR/issue-2392.rs:55:12 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `not_closure` not found for this + | --- method `not_closure` not found for this struct ... LL | w.wrap.not_closure(); | ^^^^^^^^^^^-- help: remove the arguments @@ -94,7 +94,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:58:24 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | check_expression().closure(); | ^^^^^^^ field, not a method @@ -108,7 +108,7 @@ error[E0599]: no method named `f1` found for struct `FuncContainer` in the curre --> $DIR/issue-2392.rs:64:31 | LL | struct FuncContainer { - | -------------------- method `f1` not found for this + | ------------- method `f1` not found for this struct ... LL | (*self.container).f1(1); | ^^ field, not a method @@ -122,7 +122,7 @@ error[E0599]: no method named `f2` found for struct `FuncContainer` in the curre --> $DIR/issue-2392.rs:65:31 | LL | struct FuncContainer { - | -------------------- method `f2` not found for this + | ------------- method `f2` not found for this struct ... LL | (*self.container).f2(1); | ^^ field, not a method @@ -136,7 +136,7 @@ error[E0599]: no method named `f3` found for struct `FuncContainer` in the curre --> $DIR/issue-2392.rs:66:31 | LL | struct FuncContainer { - | -------------------- method `f3` not found for this + | ------------- method `f3` not found for this struct ... LL | (*self.container).f3(1); | ^^ field, not a method diff --git a/src/test/ui/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr index 50c6fe1e83308..cad2697b52e92 100644 --- a/src/test/ui/confuse-field-and-method/issue-32128.stderr +++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `example` found for struct `Example` in the curren --> $DIR/issue-32128.rs:12:10 | LL | struct Example { - | -------------- method `example` not found for this + | ------- method `example` not found for this struct ... LL | demo.example(1); | ^^^^^^^ field, not a method diff --git a/src/test/ui/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr index fd98a864742ee..9e2f245597a45 100644 --- a/src/test/ui/confuse-field-and-method/private-field.stderr +++ b/src/test/ui/confuse-field-and-method/private-field.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `dog_age` found for struct `Dog` in the current sc --> $DIR/private-field.rs:16:23 | LL | pub struct Dog { - | -------------- method `dog_age` not found for this + | --- method `dog_age` not found for this struct ... LL | let dog_age = dog.dog_age(); | ^^^^^^^ private field, not a method diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr index 0ce7640f68577..576d037f3393d 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -8,7 +8,7 @@ error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: u --> $DIR/issue-69654.rs:17:10 | LL | struct Foo {} - | -------------------------- function or associated item `foo` not found for this + | --- function or associated item `foo` not found for this struct ... LL | Foo::foo(); | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr index 56cb11bacbe6b..7bfc09387b8a7 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -15,22 +15,16 @@ LL | [u8; size_of::() + 1]: , error[E0599]: the function or associated item `new` exists for struct `Inline`, but its trait bounds were not satisfied --> $DIR/issue-80742.rs:30:36 | -LL | / struct Inline -LL | | where -LL | | [u8; size_of::() + 1]: , -LL | | { -LL | | _phantom: PhantomData, -LL | | buf: [u8; size_of::() + 1], -LL | | } - | |_- function or associated item `new` not found for this +LL | struct Inline + | ------ function or associated item `new` not found for this struct ... -LL | let dst = Inline::::new(0); - | ^^^ function or associated item cannot be called on `Inline` due to unsatisfied trait bounds +LL | let dst = Inline::::new(0); + | ^^^ function or associated item cannot be called on `Inline` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL | -LL | pub trait Debug { - | --------------- doesn't satisfy `dyn Debug: Sized` +LL | pub trait Debug { + | --------------- doesn't satisfy `dyn Debug: Sized` | = note: the following trait bounds were not satisfied: `dyn Debug: Sized` diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr index aa5cebd873e31..ab53d6cf09a74 100644 --- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr +++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr @@ -16,7 +16,7 @@ error[E0599]: no method named `f` found for struct `S` in the current scope --> $DIR/invalid-const-arg-for-type-param.rs:9:7 | LL | struct S; - | --------- method `f` not found for this + | - method `f` not found for this struct ... LL | S.f::<0>(); | ^ method not found in `S` diff --git a/src/test/ui/consts/const-needs_drop-monomorphic.stderr b/src/test/ui/consts/const-needs_drop-monomorphic.stderr index 6e56d20c39d7f..4399db1166562 100644 --- a/src/test/ui/consts/const-needs_drop-monomorphic.stderr +++ b/src/test/ui/consts/const-needs_drop-monomorphic.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `assert` found for struct `Bo --> $DIR/const-needs_drop-monomorphic.rs:11:46 | LL | struct Bool {} - | -------------------------- function or associated item `assert` not found for this + | ---- function or associated item `assert` not found for this struct ... LL | Bool::<{ std::mem::needs_drop::() }>::assert(); | ^^^^^^ function or associated item cannot be called on `Bool<{ std::mem::needs_drop::() }>` due to unsatisfied trait bounds diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr index 79095452f9d02..3909862ff1c8b 100644 --- a/src/test/ui/copy-a-resource.stderr +++ b/src/test/ui/copy-a-resource.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `Foo` in the current scop --> $DIR/copy-a-resource.rs:18:16 | LL | struct Foo { - | ---------- method `clone` not found for this + | --- method `clone` not found for this struct ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 72dd9c153ab0d..592cc0ae90f7c 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `clone` exists for struct `Bar`, but its trai | LL | struct Bar { | ------------------ - | | - | method `clone` not found for this + | | | + | | method `clone` not found for this struct | doesn't satisfy `Bar: Clone` ... LL | struct NotClone; diff --git a/src/test/ui/derives/issue-91492.stderr b/src/test/ui/derives/issue-91492.stderr index 73c91154a7bda..e479b539fec2d 100644 --- a/src/test/ui/derives/issue-91492.stderr +++ b/src/test/ui/derives/issue-91492.stderr @@ -37,7 +37,7 @@ LL | pub struct NoDerives; | --------------------- doesn't satisfy `NoDerives: Clone` ... LL | struct Object(T, A); - | -------------------------- method `use_clone` not found for this + | ------ method `use_clone` not found for this struct ... LL | foo.use_clone(); | ^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds diff --git a/src/test/ui/derives/issue-91550.stderr b/src/test/ui/derives/issue-91550.stderr index 1b26d7549844b..e92036c99917e 100644 --- a/src/test/ui/derives/issue-91550.stderr +++ b/src/test/ui/derives/issue-91550.stderr @@ -25,7 +25,7 @@ LL | pub struct NoDerives; | --------------------- doesn't satisfy `NoDerives: Eq` LL | LL | struct Object(T); - | -------------------- method `use_eq` not found for this + | ------ method `use_eq` not found for this struct ... LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds @@ -44,7 +44,7 @@ LL | pub struct NoDerives; | --------------------- doesn't satisfy `NoDerives: Ord` LL | LL | struct Object(T); - | -------------------- method `use_ord` not found for this + | ------ method `use_ord` not found for this struct ... LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds @@ -66,7 +66,7 @@ LL | pub struct NoDerives; | doesn't satisfy `NoDerives: PartialOrd` LL | LL | struct Object(T); - | -------------------- method `use_ord_and_partial_ord` not found for this + | ------ method `use_ord_and_partial_ord` not found for this struct ... LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index d5e16e1ff273d..bd5b9f4b49ee3 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -88,7 +88,7 @@ error[E0599]: no method named `hello_method` found for struct `S` in the current --> $DIR/issue-40006.rs:38:7 | LL | struct S; - | --------- method `hello_method` not found for this + | - method `hello_method` not found for this struct ... LL | S.hello_method(); | ^^^^^^^^^^^^ method not found in `S` diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr index fd7fdb4f7226c..d85fd526d52b0 100644 --- a/src/test/ui/dont-suggest-private-trait-method.stderr +++ b/src/test/ui/dont-suggest-private-trait-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `new` found for struct `T` in --> $DIR/dont-suggest-private-trait-method.rs:4:8 | LL | struct T; - | --------- function or associated item `new` not found for this + | - function or associated item `new` not found for this struct ... LL | T::new(); | ^^^ function or associated item not found in `T` diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr index a78a003661d6f..49ca1d6353d15 100644 --- a/src/test/ui/error-codes/E0599.stderr +++ b/src/test/ui/error-codes/E0599.stderr @@ -2,7 +2,7 @@ error[E0599]: no associated item named `NotEvenReal` found for struct `Foo` in t --> $DIR/E0599.rs:4:20 | LL | struct Foo; - | ----------- associated item `NotEvenReal` not found for this + | --- associated item `NotEvenReal` not found for this struct ... LL | || if let Foo::NotEvenReal() = Foo {}; | ^^^^^^^^^^^ associated item not found in `Foo` diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr index 9eeebd80afecb..1322914797b18 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were no | LL | struct S; | --------- - | | - | method `f` not found for this + | | | + | | method `f` not found for this struct | doesn't satisfy `::Y = i32` | doesn't satisfy `S: M` ... diff --git a/src/test/ui/hrtb/issue-30786.stderr b/src/test/ui/hrtb/issue-30786.stderr index 1ee549e54a908..5a10a38d08ecd 100644 --- a/src/test/ui/hrtb/issue-30786.stderr +++ b/src/test/ui/hrtb/issue-30786.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `filterx` exists for struct `Map { | -------------------- - | | - | method `filterx` not found for this + | | | + | | method `filterx` not found for this struct | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); @@ -28,8 +28,8 @@ error[E0599]: the method `countx` exists for struct `Filter | LL | pub struct Filter { | ----------------------- - | | - | method `countx` not found for this + | | | + | | method `countx` not found for this struct | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 64cce056a2688..8b671e7dbb3a7 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | LL | struct Bar; - | ----------- method `foo` not found for this + | --- method `foo` not found for this struct ... LL | f1.foo(1usize); | ^^^ method not found in `Bar` diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr index 70d693b8bee95..44d775b695ee8 100644 --- a/src/test/ui/impl-trait/issues/issue-62742.stderr +++ b/src/test/ui/impl-trait/issues/issue-62742.stderr @@ -21,7 +21,7 @@ LL | pub struct RawImpl(PhantomData); | -------------------------------------- doesn't satisfy `RawImpl<()>: Raw<()>` ... LL | pub struct SafeImpl>(PhantomData<(A, T)>); - | --------------------------------------------------------------- function or associated item `foo` not found for this + | -------- function or associated item `foo` not found for this struct | = note: the following trait bounds were not satisfied: `RawImpl<()>: Raw<()>` diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index f6bb52bf6387c..abd57d12d9e50 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `is_empty` found for struct `Foo` in the current s --> $DIR/method-suggestion-no-duplication.rs:7:15 | LL | struct Foo; - | ----------- method `is_empty` not found for this + | --- method `is_empty` not found for this struct ... LL | foo(|s| s.is_empty()); | ^^^^^^^^ method not found in `Foo` diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index c8ebed3bfd9ae..1d24f428fb1e1 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -94,7 +94,7 @@ error[E0599]: no method named `method` found for struct `Foo` in the current sco --> $DIR/no-method-suggested-traits.rs:40:9 | LL | struct Foo; - | ----------- method `method` not found for this + | --- method `method` not found for this struct ... LL | Foo.method(); | ^^^^^^ method not found in `Foo` @@ -201,7 +201,7 @@ error[E0599]: no method named `method3` found for struct `Foo` in the current sc --> $DIR/no-method-suggested-traits.rs:59:9 | LL | struct Foo; - | ----------- method `method3` not found for this + | --- method `method3` not found for this struct ... LL | Foo.method3(); | ^^^^^^^ method not found in `Foo` @@ -224,7 +224,7 @@ error[E0599]: no method named `method3` found for enum `Bar` in the current scop --> $DIR/no-method-suggested-traits.rs:63:12 | LL | enum Bar { X } - | -------- method `method3` not found for this + | --- method `method3` not found for this enum ... LL | Bar::X.method3(); | ^^^^^^^ method not found in `Bar` diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index 2e950dbb8c7f9..edf8a44b7e4a1 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -43,7 +43,7 @@ error[E0599]: no method named `bar` found for struct `Foo` in the current scope --> $DIR/infinite-autoderef.rs:25:9 | LL | struct Foo; - | ----------- method `bar` not found for this + | --- method `bar` not found for this struct ... LL | Foo.bar(); | ^^^ method not found in `Foo` diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr index b412d7bc70436..7a72a5ff11a45 100644 --- a/src/test/ui/issues/issue-19692.stderr +++ b/src/test/ui/issues/issue-19692.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `kaname` found for struct `Homura` in the current --> $DIR/issue-19692.rs:4:40 | LL | struct Homura; - | -------------- method `kaname` not found for this + | ------ method `kaname` not found for this struct ... LL | let Some(ref madoka) = Some(homura.kaname()); | ^^^^^^ method not found in `Homura` diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr index 0bfbf538486de..648912a9690f4 100644 --- a/src/test/ui/issues/issue-22933-2.stderr +++ b/src/test/ui/issues/issue-22933-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `PIE` found for enum `Deliciou --> $DIR/issue-22933-2.rs:4:55 | LL | enum Delicious { - | -------------- variant or associated item `PIE` not found here + | --------- variant or associated item `PIE` not found for this enum ... LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, | ^^^ diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr index 89f70fda786ea..052ccd07d411b 100644 --- a/src/test/ui/issues/issue-23173.stderr +++ b/src/test/ui/issues/issue-23173.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Homura` found for enum `Token --> $DIR/issue-23173.rs:9:23 | LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ } - | ---------- variant or associated item `Homura` not found here + | ----- variant or associated item `Homura` not found for this enum ... LL | use_token(&Token::Homura); | ^^^^^^ variant or associated item not found in `Token` @@ -11,7 +11,7 @@ error[E0599]: no function or associated item named `method` found for struct `St --> $DIR/issue-23173.rs:10:13 | LL | struct Struct { - | ------------- function or associated item `method` not found for this + | ------ function or associated item `method` not found for this struct ... LL | Struct::method(); | ^^^^^^ function or associated item not found in `Struct` @@ -20,7 +20,7 @@ error[E0599]: no function or associated item named `method` found for struct `St --> $DIR/issue-23173.rs:11:13 | LL | struct Struct { - | ------------- function or associated item `method` not found for this + | ------ function or associated item `method` not found for this struct ... LL | Struct::method; | ^^^^^^ function or associated item not found in `Struct` @@ -29,7 +29,7 @@ error[E0599]: no associated item named `Assoc` found for struct `Struct` in the --> $DIR/issue-23173.rs:12:13 | LL | struct Struct { - | ------------- associated item `Assoc` not found for this + | ------ associated item `Assoc` not found for this struct ... LL | Struct::Assoc; | ^^^^^ associated item not found in `Struct` diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr index a81b459a34cbe..c5906b8805dfe 100644 --- a/src/test/ui/issues/issue-23217.stderr +++ b/src/test/ui/issues/issue-23217.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `A` found for enum `SomeEnum` --> $DIR/issue-23217.rs:2:19 | LL | pub enum SomeEnum { - | ----------------- variant or associated item `A` not found here + | -------- variant or associated item `A` not found for this enum LL | B = SomeEnum::A, | ^ | | diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr index b3bc946292f70..fcc007a4a8848 100644 --- a/src/test/ui/issues/issue-2823.stderr +++ b/src/test/ui/issues/issue-2823.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `C` in the current scope --> $DIR/issue-2823.rs:13:16 | LL | struct C { - | -------- method `clone` not found for this + | - method `clone` not found for this struct ... LL | let _d = c.clone(); | ^^^^^ method not found in `C` diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr index 2736ee881d564..e0a65e33c445e 100644 --- a/src/test/ui/issues/issue-28971.stderr +++ b/src/test/ui/issues/issue-28971.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Baz` found for enum `Foo` in --> $DIR/issue-28971.rs:7:18 | LL | enum Foo { - | -------- variant or associated item `Baz` not found here + | --- variant or associated item `Baz` not found for this enum ... LL | Foo::Baz(..) => (), | ^^^ diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr index 0022065a32c3d..f9ab8a5150716 100644 --- a/src/test/ui/issues/issue-38919.stderr +++ b/src/test/ui/issues/issue-38919.stderr @@ -1,6 +1,8 @@ error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope --> $DIR/issue-38919.rs:2:8 | +LL | fn foo() { + | - associated item `Item` not found for this type parameter LL | T::Item; | ^^^^ associated item not found in `T` diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr index 017dd831f712a..a52dc0c9af0c6 100644 --- a/src/test/ui/issues/issue-41880.stderr +++ b/src/test/ui/issues/issue-41880.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `iter` found for struct `Iterate` in the current s --> $DIR/issue-41880.rs:27:24 | LL | pub struct Iterate { - | ------------------------ method `iter` not found for this + | ------- method `iter` not found for this struct ... LL | println!("{:?}", a.iter().take(10).collect::>()); | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr index e7a244e9df576..a25b6b8802a9c 100644 --- a/src/test/ui/issues/issue-64430.stderr +++ b/src/test/ui/issues/issue-64430.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `bar` found for struct `Foo` in the current scope --> $DIR/issue-64430.rs:7:9 | LL | pub struct Foo; - | --------------- method `bar` not found for this + | --- method `bar` not found for this struct ... LL | Foo.bar() | ^^^ method not found in `Foo` diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr index 73e13c65cf37f..2a683c2d55a35 100644 --- a/src/test/ui/issues/issue-7950.stderr +++ b/src/test/ui/issues/issue-7950.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `bar` found for struct `Foo` --> $DIR/issue-7950.rs:6:10 | LL | struct Foo; - | ----------- function or associated item `bar` not found for this + | --- function or associated item `bar` not found for this struct ... LL | Foo::bar(); | ^^^ function or associated item not found in `Foo` diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index 1e6a35ed479f6..3b2a062c1c254 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -7,6 +7,8 @@ LL | let t = T { i: 0 }; error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope --> $DIR/lexical-scopes.rs:10:10 | +LL | fn g() { + | --- function or associated item `f` not found for this type parameter LL | Foo::f(); | ^ function or associated item not found in `Foo` diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 53e582f7f13a4..03ad6eb03ab53 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -51,8 +51,8 @@ error[E0599]: `Foo` is not an iterator | LL | pub struct Foo; | --------------- - | | - | method `take` not found for this + | | | + | | method `take` not found for this struct | doesn't satisfy `Foo: Iterator` ... LL | .take() diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr index 1671e5e5e64c8..492d480e13e86 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `distance` found for struct `Point` in the cu --> $DIR/method-not-found-generic-arg-elision.rs:82:23 | LL | struct Point { - | --------------- method `distance` not found for this + | ----- method `distance` not found for this struct ... LL | let d = point_i32.distance(); | ^^^^^^^^ method not found in `Point` @@ -14,7 +14,7 @@ error[E0599]: no method named `other` found for struct `Point` in the current sc --> $DIR/method-not-found-generic-arg-elision.rs:84:23 | LL | struct Point { - | --------------- method `other` not found for this + | ----- method `other` not found for this struct ... LL | let d = point_i32.other(); | ^^^^^ method not found in `Point` @@ -29,7 +29,7 @@ error[E0599]: no method named `method` found for struct `Wrapper` in the c --> $DIR/method-not-found-generic-arg-elision.rs:90:13 | LL | struct Wrapper(T); - | --------------------- method `method` not found for this + | ------- method `method` not found for this struct ... LL | wrapper.method(); | ^^^^^^ method not found in `Wrapper` @@ -45,7 +45,7 @@ error[E0599]: no method named `other` found for struct `Wrapper` in the current --> $DIR/method-not-found-generic-arg-elision.rs:92:13 | LL | struct Wrapper(T); - | --------------------- method `other` not found for this + | ------- method `other` not found for this struct ... LL | wrapper.other(); | ^^^^^ method not found in `Wrapper` @@ -54,7 +54,7 @@ error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3_us --> $DIR/method-not-found-generic-arg-elision.rs:96:13 | LL | struct Wrapper2<'a, T, const C: usize> { - | -------------------------------------- method `method` not found for this + | -------- method `method` not found for this struct ... LL | wrapper.method(); | ^^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` @@ -68,7 +68,7 @@ error[E0599]: no method named `other` found for struct `Wrapper2` in the current --> $DIR/method-not-found-generic-arg-elision.rs:98:13 | LL | struct Wrapper2<'a, T, const C: usize> { - | -------------------------------------- method `other` not found for this + | -------- method `other` not found for this struct ... LL | wrapper.other(); | ^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` @@ -83,7 +83,7 @@ error[E0599]: the method `method` exists for struct `Struct`, but its trait --> $DIR/method-not-found-generic-arg-elision.rs:104:7 | LL | struct Struct{ - | ---------------- method `method` not found for this + | ------ method `method` not found for this struct ... LL | s.method(); | ^^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr index 4674c16eb433a..88e9cd6a9c088 100644 --- a/src/test/ui/noncopyable-class.stderr +++ b/src/test/ui/noncopyable-class.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `Foo` in the current scop --> $DIR/noncopyable-class.rs:34:16 | LL | struct Foo { - | ---------- method `clone` not found for this + | --- method `clone` not found for this struct ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr index 7dc589e556386..40a85f7f74ca8 100644 --- a/src/test/ui/parser/emoji-identifiers.stderr +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -77,7 +77,7 @@ error[E0599]: no function or associated item named `full_of✨` found for struct --> $DIR/emoji-identifiers.rs:9:8 | LL | struct 👀; - | ---------- function or associated item `full_of✨` not found for this + | -- function or associated item `full_of✨` not found for this struct ... LL | 👀::full_of✨() | ^^^^^^^^^ diff --git a/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr index 53272abccbbf0..edbea330a04b6 100644 --- a/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr +++ b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `deserialize` found for struc --> $DIR/issue-87932.rs:13:8 | LL | pub struct A {} - | ------------ function or associated item `deserialize` not found for this + | - function or associated item `deserialize` not found for this struct ... LL | A::deserialize(); | ^^^^^^^^^^^ function or associated item not found in `A` diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr index a0ef7e3f2cbab..06ccc5b1afeea 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-method.rs:8:7 | LL | struct A; - | --------- method `foo` not found for this + | - method `foo` not found for this struct ... LL | fn foo(self: Box) {} | --- the method is available for `Box` here diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 440676482835c..bd77f67fb4e9b 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -6,7 +6,7 @@ LL | trait B { fn foo(self: Box); } | | | the method is available for `Box` here LL | struct A; - | --------- method `foo` not found for this + | - method `foo` not found for this struct ... LL | A.foo() | ^^^ method not found in `A` diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 783f5aca41746..912618555f4db 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -42,7 +42,7 @@ error[E0599]: no method named `fff` found for struct `Myisize` in the current sc --> $DIR/issue-7575.rs:62:30 | LL | struct Myisize(isize); - | ---------------------- method `fff` not found for this + | ------- method `fff` not found for this struct ... LL | u.f8(42) + u.f9(342) + m.fff(42) | --^^^ @@ -60,6 +60,8 @@ LL | fn fff(i: isize) -> isize { error[E0599]: no method named `is_str` found for type parameter `T` in the current scope --> $DIR/issue-7575.rs:70:7 | +LL | fn param_bound(t: T) -> bool { + | - method `is_str` not found for this type parameter LL | t.is_str() | ^^^^^^ this is an associated function, not a method | diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 9894ecc64b518..d2350bc7e4f91 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -13,8 +13,8 @@ error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait b | LL | struct MyStruct; | ---------------- - | | - | method `foo_one` not found for this + | | | + | | method `foo_one` not found for this struct | doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr index 2af3ba1d5bb9c..65167ce4a29e0 100644 --- a/src/test/ui/suggestions/derive-trait-for-method-call.stderr +++ b/src/test/ui/suggestions/derive-trait-for-method-call.stderr @@ -11,7 +11,7 @@ LL | enum CloneEnum { | -------------- doesn't satisfy `CloneEnum: Default` ... LL | struct Foo (X, Y); - | ------------------------ method `test` not found for this + | --- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds @@ -49,7 +49,7 @@ LL | struct CloneStruct { | ------------------ doesn't satisfy `CloneStruct: Default` ... LL | struct Foo (X, Y); - | ------------------------ method `test` not found for this + | --- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds @@ -71,7 +71,7 @@ error[E0599]: the method `test` exists for struct `Foo, Instant>`, but --> $DIR/derive-trait-for-method-call.rs:40:15 | LL | struct Foo (X, Y); - | ------------------------ method `test` not found for this + | --- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds diff --git a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr index 8fcadbf4c75f4..d5af89e3547a1 100644 --- a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr +++ b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `pick` found for struct `Chaenomeles` in the curre --> $DIR/dont-wrap-ambiguous-receivers.rs:18:25 | LL | pub struct Chaenomeles; - | ----------------------- method `pick` not found for this + | ----------- method `pick` not found for this struct ... LL | banana::Chaenomeles.pick() | ^^^^ method not found in `Chaenomeles` diff --git a/src/test/ui/suggestions/field-has-method.stderr b/src/test/ui/suggestions/field-has-method.stderr index 3a57436f200ba..34b6230e19be2 100644 --- a/src/test/ui/suggestions/field-has-method.stderr +++ b/src/test/ui/suggestions/field-has-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `kind` found for struct `InferOk` in the current s --> $DIR/field-has-method.rs:19:15 | LL | struct InferOk { - | ----------------- method `kind` not found for this + | ------- method `kind` not found for this struct ... LL | let k = i.kind(); | ^^^^ method not found in `InferOk` diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr index 8ec7b7bf49658..20f8e65f769a4 100644 --- a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -1,6 +1,8 @@ error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 | +LL | fn test(foo: impl Foo) { + | -------- method `hello` not found for this type parameter LL | foo.hello(); | ^^^^^ method not found in `impl Foo` | diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr index 0a4aaa61bc784..523d7a7ccd29c 100644 --- a/src/test/ui/suggestions/issue-21673.stderr +++ b/src/test/ui/suggestions/issue-21673.stderr @@ -13,6 +13,8 @@ LL | fn call_method(x: &T) { error[E0599]: no method named `method` found for type parameter `T` in the current scope --> $DIR/issue-21673.rs:10:7 | +LL | fn call_method_2(x: T) { + | - method `method` not found for this type parameter LL | x.method() | ^^^^^^ method not found in `T` | diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index f1c0cd6b543e4..3497c31826c5c 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `default_hello` found for struct `GenericAssocMeth --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 | LL | struct GenericAssocMethod(T); - | -------------------------------- method `default_hello` not found for this + | ------------------ method `default_hello` not found for this struct ... LL | x.default_hello(); | --^^^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index 9079e8f2ce7a4..dd9010e32955e 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `bat` found for struct `Foo` in the current scope --> $DIR/suggest-methods.rs:18:7 | LL | struct Foo; - | ----------- method `bat` not found for this + | --- method `bat` not found for this struct ... LL | f.bat(1.0); | ^^^ help: there is an associated function with a similar name: `bar` diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr index 9227baa3e1a5c..cccf9378d4dae 100644 --- a/src/test/ui/suggestions/suggest-variants.stderr +++ b/src/test/ui/suggestions/suggest-variants.stderr @@ -29,7 +29,7 @@ error[E0599]: no variant or associated item named `Squareee` found for enum `Sha --> $DIR/suggest-variants.rs:15:12 | LL | enum Shape { - | ---------- variant or associated item `Squareee` not found here + | ----- variant or associated item `Squareee` not found for this enum ... LL | Shape::Squareee; | ^^^^^^^^ @@ -41,7 +41,7 @@ error[E0599]: no variant or associated item named `Circl` found for enum `Shape` --> $DIR/suggest-variants.rs:16:12 | LL | enum Shape { - | ---------- variant or associated item `Circl` not found here + | ----- variant or associated item `Circl` not found for this enum ... LL | Shape::Circl; | ^^^^^ @@ -53,7 +53,7 @@ error[E0599]: no variant or associated item named `Rombus` found for enum `Shape --> $DIR/suggest-variants.rs:17:12 | LL | enum Shape { - | ---------- variant or associated item `Rombus` not found here + | ----- variant or associated item `Rombus` not found for this enum ... LL | Shape::Rombus; | ^^^^^^ variant or associated item not found in `Shape` diff --git a/src/test/ui/suggestions/use-placement-typeck.stderr b/src/test/ui/suggestions/use-placement-typeck.stderr index 21f22dade2c22..aa9880a60b67c 100644 --- a/src/test/ui/suggestions/use-placement-typeck.stderr +++ b/src/test/ui/suggestions/use-placement-typeck.stderr @@ -8,7 +8,7 @@ LL | fn abc(&self) {} | --- the method is available for `S` here LL | } LL | pub struct S; - | ------------- method `abc` not found for this + | - method `abc` not found for this struct | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/traits/issue-3973.stderr b/src/test/ui/traits/issue-3973.stderr index 63282e8d86d7b..188125d248d18 100644 --- a/src/test/ui/traits/issue-3973.stderr +++ b/src/test/ui/traits/issue-3973.stderr @@ -11,7 +11,7 @@ error[E0599]: no function or associated item named `new` found for struct `Point --> $DIR/issue-3973.rs:22:20 | LL | struct Point { - | ------------ function or associated item `new` not found for this + | ----- function or associated item `new` not found for this struct ... LL | let p = Point::new(0.0, 0.0); | ^^^ function or associated item not found in `Point` diff --git a/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr index 35d41c6266761..ae33e61d83b7a 100644 --- a/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr +++ b/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr @@ -1,6 +1,8 @@ error[E0599]: no method named `foo` found for type parameter `T` in the current scope --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7 | +LL | fn do_stuff(t : T) { + | - method `foo` not found for this type parameter LL | t.foo() | ^^^ method not found in `T` | diff --git a/src/test/ui/traits/issue-95898.stderr b/src/test/ui/traits/issue-95898.stderr index 0a58ad4b663eb..ca7bacdbf41ba 100644 --- a/src/test/ui/traits/issue-95898.stderr +++ b/src/test/ui/traits/issue-95898.stderr @@ -1,6 +1,8 @@ error[E0599]: no method named `clone` found for type parameter `T` in the current scope --> $DIR/issue-95898.rs:5:7 | +LL | fn foo(t: T) { + | - method `clone` not found for this type parameter LL | t.clone(); | ^^^^^ method not found in `T` | diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index ef5d5cdff8f4b..a7954f7b24595 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `a` found for struct `S` in the current scope --> $DIR/item-privacy.rs:67:7 | LL | struct S; - | --------- method `a` not found for this + | - method `a` not found for this struct ... LL | S.a(); | ^ method not found in `S` @@ -18,7 +18,7 @@ error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/item-privacy.rs:68:7 | LL | struct S; - | --------- method `b` not found for this + | - method `b` not found for this struct ... LL | fn b(&self) { } | - the method is available for `S` here @@ -45,7 +45,7 @@ error[E0599]: no function or associated item named `a` found for struct `S` in t --> $DIR/item-privacy.rs:78:8 | LL | struct S; - | --------- function or associated item `a` not found for this + | - function or associated item `a` not found for this struct ... LL | S::a(&S); | ^ function or associated item not found in `S` @@ -61,7 +61,7 @@ error[E0599]: no function or associated item named `b` found for struct `S` in t --> $DIR/item-privacy.rs:80:8 | LL | struct S; - | --------- function or associated item `b` not found for this + | - function or associated item `b` not found for this struct ... LL | S::b(&S); | ^ function or associated item not found in `S` @@ -85,7 +85,7 @@ error[E0599]: no associated item named `A` found for struct `S` in the current s --> $DIR/item-privacy.rs:97:8 | LL | struct S; - | --------- associated item `A` not found for this + | - associated item `A` not found for this struct ... LL | S::A; | ^ associated item not found in `S` @@ -101,7 +101,7 @@ error[E0599]: no associated item named `B` found for struct `S` in the current s --> $DIR/item-privacy.rs:98:8 | LL | struct S; - | --------- associated item `B` not found for this + | - associated item `B` not found for this struct ... LL | S::B; | ^ associated item not found in `S` diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr index c18abf95083da..d8f2f8761ff94 100644 --- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr +++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `Qux` in the current scop --> $DIR/explicitly-unimplemented-error-message.rs:34:9 | LL | struct Qux; - | ----------- method `clone` not found for this + | --- method `clone` not found for this struct ... LL | Qux.clone(); | ^^^^^ method not found in `Qux` @@ -23,7 +23,7 @@ error[E0599]: no method named `foo` found for struct `Qux` in the current scope --> $DIR/explicitly-unimplemented-error-message.rs:44:9 | LL | struct Qux; - | ----------- method `foo` not found for this + | --- method `foo` not found for this struct ... LL | Qux.foo(); | ^^^ method not found in `Qux` diff --git a/src/test/ui/typeck/point-at-type-parameter-definition.rs b/src/test/ui/typeck/point-at-type-parameter-definition.rs new file mode 100644 index 0000000000000..856c0db08f79c --- /dev/null +++ b/src/test/ui/typeck/point-at-type-parameter-definition.rs @@ -0,0 +1,17 @@ +trait Trait { + fn do_stuff(&self); +} + +struct Hello; + +impl Hello { + fn method(&self) {} +} + +impl Trait for Vec { + fn do_stuff(&self) { + self[0].method(); //~ ERROR no method named `method` found for type parameter `Hello` in the current scope + } +} + +fn main() {} diff --git a/src/test/ui/typeck/point-at-type-parameter-definition.stderr b/src/test/ui/typeck/point-at-type-parameter-definition.stderr new file mode 100644 index 0000000000000..8a6ab61100d24 --- /dev/null +++ b/src/test/ui/typeck/point-at-type-parameter-definition.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `method` found for type parameter `Hello` in the current scope + --> $DIR/point-at-type-parameter-definition.rs:13:17 + | +LL | impl Trait for Vec { + | ----- method `method` not found for this type parameter +LL | fn do_stuff(&self) { +LL | self[0].method(); + | ^^^^^^ method not found in `Hello` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index c242a7de7abfb..b5c72aa524779 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `clone` exists for union `U5`, but its tra | LL | union U5 { | ----------- - | | - | method `clone` not found for this + | | | + | | method `clone` not found for this union | doesn't satisfy `U5: Clone` ... LL | struct CloneNoCopy; diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index c242a7de7abfb..b5c72aa524779 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `clone` exists for union `U5`, but its tra | LL | union U5 { | ----------- - | | - | method `clone` not found for this + | | | + | | method `clone` not found for this union | doesn't satisfy `U5: Clone` ... LL | struct CloneNoCopy; From 6a6910e5a9bb8d00f9798dea93dcbe61df4c073d Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 22 Jun 2022 13:47:32 +0200 Subject: [PATCH 13/23] Address reviewer comments --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 4ac27e85f8ba8..ea24fedd0eb3d 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -307,8 +307,9 @@ where /// Copies `len` bytes of data from enclave pointer `src` to userspace `dst` /// -/// This function mitigates stale data vulnerabilities -/// https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html +/// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either: +/// - preceded by the VERW instruction and followed by the MFENCE; LFENCE instruction sequence +/// - or are in multiples of 8 bytes, aligned to an 8-byte boundary /// /// # Panics /// This function panics if: @@ -317,10 +318,14 @@ where /// * The `dst` pointer is null /// * The `src` memory range is not in enclave memory /// * The `dst` memory range is not in user memory +/// +/// # References +/// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html +/// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/processor-mmio-stale-data-vulnerabilities.html#inpage-nav-3-2-2 pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) { unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) { unsafe { - let seg_sel: u16 = 0; + let mut seg_sel: u16 = 0; for off in 0..len { asm!(" mov %ds, ({seg_sel}) @@ -328,10 +333,10 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) movb {val}, ({dst}) mfence lfence - ", + ", val = in(reg_byte) *src.offset(off as isize), dst = in(reg) dst.offset(off as isize), - seg_sel = in(reg) &seg_sel, + seg_sel = in(reg) &mut seg_sel, options(nostack, att_syntax) ); } From d23eea59f88de2b1b41812862da57bce76b651e0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 22 Jun 2022 11:42:24 -0700 Subject: [PATCH 14/23] Add tracking issues to `--extern` option docs. --- src/doc/unstable-book/src/compiler-flags/extern-options.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/doc/unstable-book/src/compiler-flags/extern-options.md b/src/doc/unstable-book/src/compiler-flags/extern-options.md index 858eee5d2c283..dfc1de77be4e4 100644 --- a/src/doc/unstable-book/src/compiler-flags/extern-options.md +++ b/src/doc/unstable-book/src/compiler-flags/extern-options.md @@ -1,5 +1,10 @@ # `--extern` Options +* Tracking issue for `--extern` crate modifiers: [#98405](https://github.com/rust-lang/rust/issues/98405) +* Tracking issue for `noprelude`: [#98398](https://github.com/rust-lang/rust/issues/98398) +* Tracking issue for `priv`: [#98399](https://github.com/rust-lang/rust/issues/98399) +* Tracking issue for `nounused`: [#98400](https://github.com/rust-lang/rust/issues/98400) + The behavior of the `--extern` flag can be modified with `noprelude`, `priv` or `nounused` options. This is unstable feature, so you have to provide `-Zunstable-options` to enable it. From 3c7f1f16016d8a19a549f2c34a05cfdf8f79968b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Jun 2022 20:33:40 +0400 Subject: [PATCH 15/23] Suggest defining variable as mutable on `&mut _` type mismatch in pats --- compiler/rustc_typeck/src/check/pat.rs | 51 ++++++++++ .../ref-pat-suggestions.fixed | 13 +++ .../mismatched_types/ref-pat-suggestions.rs | 13 +++ .../ref-pat-suggestions.stderr | 92 ++++++++++++++++++- src/test/ui/pattern/for-loop-bad-item.stderr | 5 + 5 files changed, 173 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index f45b94bcdff45..58fd11200c901 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -663,6 +663,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ast::Mutability::Not => "", }; + let mut_var_suggestion = 'block: { + if !matches!(mutbl, ast::Mutability::Mut) { + break 'block None; + } + + let ident_kind = match binding_parent { + hir::Node::Param(_) => Some("parameter"), + hir::Node::Local(_) => Some("variable"), + hir::Node::Arm(_) => Some("binding"), + + // Provide diagnostics only if the parent pattern is struct-like, + // i.e. where `mut binding` makes sense + hir::Node::Pat(Pat { kind, .. }) => match kind { + PatKind::Struct(..) + | PatKind::TupleStruct(..) + | PatKind::Or(..) + | PatKind::Tuple(..) + | PatKind::Slice(..) => Some("binding"), + + PatKind::Wild + | PatKind::Binding(..) + | PatKind::Path(..) + | PatKind::Box(..) + | PatKind::Ref(..) + | PatKind::Lit(..) + | PatKind::Range(..) => None, + }, + + // Don't provide suggestions in other cases + _ => None, + }; + + ident_kind.map(|thing| ( + pat.span, + format!("to declare a mutable {thing} use `mut variable_name`"), + format!("mut {binding}"), + )) + + }; + match binding_parent { // Check that there is explicit type (ie this is not a closure param with inferred type) // so we don't suggest moving something to the type that does not exist @@ -675,6 +715,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ], Applicability::MachineApplicable ); + + if let Some((sp, msg, sugg)) = mut_var_suggestion { + err.span_note(sp, format!("{msg}: `{sugg}`")); + } } hir::Node::Param(_) | hir::Node::Arm(_) | hir::Node::Pat(_) => { // rely on match ergonomics or it might be nested `&&pat` @@ -684,6 +728,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "", Applicability::MaybeIncorrect, ); + + if let Some((sp, msg, sugg)) = mut_var_suggestion { + err.span_note(sp, format!("{msg}: `{sugg}`")); + } + } + _ if let Some((sp, msg, sugg)) = mut_var_suggestion => { + err.span_suggestion(sp, msg, sugg, Applicability::MachineApplicable); } _ => {} // don't provide suggestions in other cases #55175 } diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed index ab8483eef49fa..d50acd1ac62d2 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.fixed +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.fixed @@ -21,4 +21,17 @@ fn main() { let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types let _ = |&_a: &u32| (); //~ ERROR mismatched types let _ = |&mut _a: &mut u32| (); //~ ERROR mismatched types + + #[allow(unused_mut)] + { + struct S(u8); + + let mut _a = 0; //~ ERROR mismatched types + let S(_b) = S(0); //~ ERROR mismatched types + let (_c,) = (0,); //~ ERROR mismatched types + + match 0 { + _d => {} //~ ERROR mismatched types + } + } } diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.rs b/src/test/ui/mismatched_types/ref-pat-suggestions.rs index 7e55539aa3d1b..1a77f68769224 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.rs +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.rs @@ -21,4 +21,17 @@ fn main() { let _ = |&mut &_a: &mut u32| (); //~ ERROR mismatched types let _ = |&&mut _a: &u32| (); //~ ERROR mismatched types let _ = |&mut &mut _a: &mut u32| (); //~ ERROR mismatched types + + #[allow(unused_mut)] + { + struct S(u8); + + let &mut _a = 0; //~ ERROR mismatched types + let S(&mut _b) = S(0); //~ ERROR mismatched types + let (&mut _c,) = (0,); //~ ERROR mismatched types + + match 0 { + &mut _d => {} //~ ERROR mismatched types + } + } } diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr index 0e8f8853fb751..cd86bb532abda 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr @@ -24,6 +24,11 @@ LL | fn _f1(&mut _a: u32) {} | = note: expected type `u32` found mutable reference `&mut _` +note: to declare a mutable parameter use `mut variable_name`: `mut _a` + --> $DIR/ref-pat-suggestions.rs:4:8 + | +LL | fn _f1(&mut _a: u32) {} + | ^^^^^^^ help: to take parameter `_a` by reference, move `&mut` to the type | LL - fn _f1(&mut _a: u32) {} @@ -122,6 +127,11 @@ LL | let _: fn(u32) = |&mut _a| (); | = note: expected type `u32` found mutable reference `&mut _` +note: to declare a mutable parameter use `mut variable_name`: `mut _a` + --> $DIR/ref-pat-suggestions.rs:12:23 + | +LL | let _: fn(u32) = |&mut _a| (); + | ^^^^^^^ help: consider removing `&mut` from the pattern | LL - let _: fn(u32) = |&mut _a| (); @@ -222,6 +232,11 @@ LL | let _ = |&mut _a: u32| (); | = note: expected type `u32` found mutable reference `&mut _` +note: to declare a mutable parameter use `mut variable_name`: `mut _a` + --> $DIR/ref-pat-suggestions.rs:19:14 + | +LL | let _ = |&mut _a: u32| (); + | ^^^^^^^ help: to take parameter `_a` by reference, move `&mut` to the type | LL - let _ = |&mut _a: u32| (); @@ -292,6 +307,81 @@ LL - let _ = |&mut &mut _a: &mut u32| (); LL + let _ = |&mut _a: &mut u32| (); | -error: aborting due to 18 previous errors +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:29:13 + | +LL | let &mut _a = 0; + | ^^^^^^^ - this expression has type `{integer}` + | | + | expected integer, found `&mut _` + | help: to declare a mutable variable use `mut variable_name`: `mut _a` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:30:15 + | +LL | let S(&mut _b) = S(0); + | ^^^^^^^ ---- this expression has type `S` + | | + | expected `u8`, found `&mut _` + | + = note: expected type `u8` + found mutable reference `&mut _` +note: to declare a mutable binding use `mut variable_name`: `mut _b` + --> $DIR/ref-pat-suggestions.rs:30:15 + | +LL | let S(&mut _b) = S(0); + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let S(&mut _b) = S(0); +LL + let S(_b) = S(0); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:31:14 + | +LL | let (&mut _c,) = (0,); + | ^^^^^^^ ---- this expression has type `({integer},)` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use `mut variable_name`: `mut _c` + --> $DIR/ref-pat-suggestions.rs:31:14 + | +LL | let (&mut _c,) = (0,); + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let (&mut _c,) = (0,); +LL + let (_c,) = (0,); + | + +error[E0308]: mismatched types + --> $DIR/ref-pat-suggestions.rs:34:13 + | +LL | match 0 { + | - this expression has type `{integer}` +LL | &mut _d => {} + | ^^^^^^^ expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use `mut variable_name`: `mut _d` + --> $DIR/ref-pat-suggestions.rs:34:13 + | +LL | &mut _d => {} + | ^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - &mut _d => {} +LL + _d => {} + | + +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/for-loop-bad-item.stderr b/src/test/ui/pattern/for-loop-bad-item.stderr index ad737f7bd15e1..212d66f649763 100644 --- a/src/test/ui/pattern/for-loop-bad-item.stderr +++ b/src/test/ui/pattern/for-loop-bad-item.stderr @@ -8,6 +8,11 @@ LL | for ((_, _), (&mut c, _)) in &mut map { | = note: expected type `char` found mutable reference `&mut _` +note: to declare a mutable binding use `mut variable_name`: `mut c` + --> $DIR/for-loop-bad-item.rs:7:19 + | +LL | for ((_, _), (&mut c, _)) in &mut map { + | ^^^^^^ help: consider removing `&mut` from the pattern | LL - for ((_, _), (&mut c, _)) in &mut map { From 4c4fb7152bf73dcbdd0066e65ec3d034d42589c5 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 23 Jun 2022 17:34:34 +0200 Subject: [PATCH 16/23] add test --- src/test/ui/const-generics/issues/issue-97634.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-97634.rs diff --git a/src/test/ui/const-generics/issues/issue-97634.rs b/src/test/ui/const-generics/issues/issue-97634.rs new file mode 100644 index 0000000000000..a04036d0647ad --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-97634.rs @@ -0,0 +1,10 @@ +//build-pass + +pub enum Register { + Field0 = 40, + Field1, +} + +fn main() { + let _b = Register::<0>::Field1 as u16; +} From 2e3221a927ed77e81652fafa5256335212755e60 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 23 Jun 2022 17:34:17 +0200 Subject: [PATCH 17/23] use correct substs in enum discriminant hack --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index fb2f5861c6f03..38c4f94ed12cf 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -650,6 +650,9 @@ impl<'tcx> Cx<'tcx> { } else { None }; + debug!(?var); + let substs = self.typeck_results.node_substs(source.hir_id); + debug!(?substs); let source = if let Some((did, offset, var_ty)) = var { let param_env_ty = self.param_env.and(var_ty); @@ -671,7 +674,7 @@ impl<'tcx> Cx<'tcx> { Some(did) => { // in case we are offsetting from a computed discriminant // and not the beginning of discriminants (which is always `0`) - let substs = InternalSubsts::identity_for_item(tcx, did); + let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None }; let lhs = self.thir.exprs.push(Expr { From 38814fc03900c2adceb021472027aed28b5714ed Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 24 Jun 2022 13:19:23 +0200 Subject: [PATCH 18/23] small refactor --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 191 ++++++++++--------- 1 file changed, 96 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 38c4f94ed12cf..3f854554f4d04 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1,3 +1,4 @@ +use crate::thir::cx::region::Scope; use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -158,6 +159,100 @@ impl<'tcx> Cx<'tcx> { Expr { temp_lifetime, ty: adjustment.target, span, kind } } + fn mirror_expr_cast( + &mut self, + source: &'tcx hir::Expr<'tcx>, + temp_lifetime: Option, + span: Span, + ) -> ExprKind<'tcx> { + let tcx = self.tcx; + + // Check to see if this cast is a "coercion cast", where the cast is actually done + // using a coercion (or is a no-op). + if self.typeck_results().is_coercion_cast(source.hir_id) { + // Convert the lexpr to a vexpr. + ExprKind::Use { source: self.mirror_expr(source) } + } else if self.typeck_results().expr_ty(source).is_region_ptr() { + // Special cased so that we can type check that the element + // type of the source matches the pointed to type of the + // destination. + ExprKind::Pointer { + source: self.mirror_expr(source), + cast: PointerCast::ArrayToPointer, + } + } else { + // check whether this is casting an enum variant discriminant + // to prevent cycles, we refer to the discriminant initializer + // which is always an integer and thus doesn't need to know the + // enum's layout (or its tag type) to compute it during const eval + // Example: + // enum Foo { + // A, + // B = A as isize + 4, + // } + // The correct solution would be to add symbolic computations to miri, + // so we wouldn't have to compute and store the actual value + + let hir::ExprKind::Path(ref qpath) = source.kind else { + return ExprKind::Cast { source: self.mirror_expr(source)}; + }; + + let res = self.typeck_results().qpath_res(qpath, source.hir_id); + let (discr_did, discr_offset, discr_ty, substs) = { + let ty = self.typeck_results().node_type(source.hir_id); + let ty::Adt(adt_def, substs) = ty.kind() else { + return ExprKind::Cast { source: self.mirror_expr(source)}; + }; + let Res::Def( + DefKind::Ctor(CtorOf::Variant, CtorKind::Const), + variant_ctor_id, + ) = res else { + return ExprKind::Cast { source: self.mirror_expr(source)}; + }; + + let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); + let (d, o) = adt_def.discriminant_def_for_variant(idx); + use rustc_middle::ty::util::IntTypeExt; + let ty = adt_def.repr().discr_type(); + let ty = ty.to_ty(tcx); + (d, o, ty, substs) + }; + + let param_env_ty = self.param_env.and(discr_ty); + let size = tcx + .layout_of(param_env_ty) + .unwrap_or_else(|e| { + panic!("could not compute layout for {:?}: {:?}", param_env_ty, e) + }) + .size; + + let lit = ScalarInt::try_from_uint(discr_offset as u128, size).unwrap(); + let kind = ExprKind::NonHirLiteral { lit, user_ty: None }; + let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); + + let source = match discr_did { + Some(did) => { + // in case we are offsetting from a computed discriminant + // and not the beginning of discriminants (which is always `0`) + + let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None }; + let lhs = + self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); + let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; + self.thir.exprs.push(Expr { + temp_lifetime, + ty: discr_ty, + span: span, + kind: bin, + }) + } + None => offset, + }; + + ExprKind::Cast { source } + } + } + fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let tcx = self.tcx; let expr_ty = self.typeck_results().expr_ty(expr); @@ -604,101 +699,7 @@ impl<'tcx> Cx<'tcx> { expr, cast_ty.hir_id, user_ty, ); - // Check to see if this cast is a "coercion cast", where the cast is actually done - // using a coercion (or is a no-op). - let cast = if self.typeck_results().is_coercion_cast(source.hir_id) { - // Convert the lexpr to a vexpr. - ExprKind::Use { source: self.mirror_expr(source) } - } else if self.typeck_results().expr_ty(source).is_region_ptr() { - // Special cased so that we can type check that the element - // type of the source matches the pointed to type of the - // destination. - ExprKind::Pointer { - source: self.mirror_expr(source), - cast: PointerCast::ArrayToPointer, - } - } else { - // check whether this is casting an enum variant discriminant - // to prevent cycles, we refer to the discriminant initializer - // which is always an integer and thus doesn't need to know the - // enum's layout (or its tag type) to compute it during const eval - // Example: - // enum Foo { - // A, - // B = A as isize + 4, - // } - // The correct solution would be to add symbolic computations to miri, - // so we wouldn't have to compute and store the actual value - let var = if let hir::ExprKind::Path(ref qpath) = source.kind { - let res = self.typeck_results().qpath_res(qpath, source.hir_id); - self.typeck_results().node_type(source.hir_id).ty_adt_def().and_then( - |adt_def| match res { - Res::Def( - DefKind::Ctor(CtorOf::Variant, CtorKind::Const), - variant_ctor_id, - ) => { - let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); - let (d, o) = adt_def.discriminant_def_for_variant(idx); - use rustc_middle::ty::util::IntTypeExt; - let ty = adt_def.repr().discr_type(); - let ty = ty.to_ty(tcx); - Some((d, o, ty)) - } - _ => None, - }, - ) - } else { - None - }; - debug!(?var); - let substs = self.typeck_results.node_substs(source.hir_id); - debug!(?substs); - - let source = if let Some((did, offset, var_ty)) = var { - let param_env_ty = self.param_env.and(var_ty); - let size = tcx - .layout_of(param_env_ty) - .unwrap_or_else(|e| { - panic!("could not compute layout for {:?}: {:?}", param_env_ty, e) - }) - .size; - let lit = ScalarInt::try_from_uint(offset as u128, size).unwrap(); - let kind = ExprKind::NonHirLiteral { lit, user_ty: None }; - let offset = self.thir.exprs.push(Expr { - temp_lifetime, - ty: var_ty, - span: expr.span, - kind, - }); - match did { - Some(did) => { - // in case we are offsetting from a computed discriminant - // and not the beginning of discriminants (which is always `0`) - - let kind = - ExprKind::NamedConst { def_id: did, substs, user_ty: None }; - let lhs = self.thir.exprs.push(Expr { - temp_lifetime, - ty: var_ty, - span: expr.span, - kind, - }); - let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; - self.thir.exprs.push(Expr { - temp_lifetime, - ty: var_ty, - span: expr.span, - kind: bin, - }) - } - None => offset, - } - } else { - self.mirror_expr(source) - }; - - ExprKind::Cast { source: source } - }; + let cast = self.mirror_expr_cast(*source, temp_lifetime, expr.span); if let Some(user_ty) = user_ty { // NOTE: Creating a new Expr and wrapping a Cast inside of it may be From f39c0d6b0a7b80959956a6e006dfc3406f8141e3 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 24 Jun 2022 13:43:56 +0200 Subject: [PATCH 19/23] address review --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 3f854554f4d04..b127b264b834f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -159,6 +159,9 @@ impl<'tcx> Cx<'tcx> { Expr { temp_lifetime, ty: adjustment.target, span, kind } } + /// Lowers a cast expression. + /// + /// Dealing with user type annotations is left to the caller. fn mirror_expr_cast( &mut self, source: &'tcx hir::Expr<'tcx>, @@ -198,25 +201,23 @@ impl<'tcx> Cx<'tcx> { }; let res = self.typeck_results().qpath_res(qpath, source.hir_id); - let (discr_did, discr_offset, discr_ty, substs) = { - let ty = self.typeck_results().node_type(source.hir_id); - let ty::Adt(adt_def, substs) = ty.kind() else { + let ty = self.typeck_results().node_type(source.hir_id); + let ty::Adt(adt_def, substs) = ty.kind() else { return ExprKind::Cast { source: self.mirror_expr(source)}; }; - let Res::Def( + let Res::Def( DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id, ) = res else { return ExprKind::Cast { source: self.mirror_expr(source)}; }; - let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); - let (d, o) = adt_def.discriminant_def_for_variant(idx); - use rustc_middle::ty::util::IntTypeExt; - let ty = adt_def.repr().discr_type(); - let ty = ty.to_ty(tcx); - (d, o, ty, substs) - }; + let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); + let (discr_did, discr_offset) = adt_def.discriminant_def_for_variant(idx); + + use rustc_middle::ty::util::IntTypeExt; + let ty = adt_def.repr().discr_type(); + let discr_ty = ty.to_ty(tcx); let param_env_ty = self.param_env.and(discr_ty); let size = tcx @@ -231,10 +232,9 @@ impl<'tcx> Cx<'tcx> { let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); let source = match discr_did { + // in case we are offsetting from a computed discriminant + // and not the beginning of discriminants (which is always `0`) Some(did) => { - // in case we are offsetting from a computed discriminant - // and not the beginning of discriminants (which is always `0`) - let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None }; let lhs = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); From ada2accf8e659900c02e1f9a5f4015ae6d68f33e Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jun 2022 14:49:48 -0700 Subject: [PATCH 20/23] Set relocation_model to Pic on emscripten target --- compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index f1087db09d132..1b94c59b55f09 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -1,5 +1,5 @@ use super::{cvs, wasm_base}; -use super::{LinkArgs, LinkerFlavor, PanicStrategy, Target, TargetOptions}; +use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let mut options = wasm_base::options(); @@ -26,6 +26,7 @@ pub fn target() -> Target { // functionality, and a .wasm file. exe_suffix: ".js".into(), linker: None, + relocation_model: RelocModel::Pic, panic_strategy: PanicStrategy::Unwind, no_default_libraries: false, post_link_args, From bf48b622a5ff7efc16ac099bbe8d272445a49d70 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 24 Jun 2022 16:43:38 +0200 Subject: [PATCH 21/23] fmt --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 14 ++++++-------- src/test/ui/const-generics/issues/issue-97634.rs | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b127b264b834f..a0878c97e883f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -203,14 +203,12 @@ impl<'tcx> Cx<'tcx> { let res = self.typeck_results().qpath_res(qpath, source.hir_id); let ty = self.typeck_results().node_type(source.hir_id); let ty::Adt(adt_def, substs) = ty.kind() else { - return ExprKind::Cast { source: self.mirror_expr(source)}; - }; - let Res::Def( - DefKind::Ctor(CtorOf::Variant, CtorKind::Const), - variant_ctor_id, - ) = res else { - return ExprKind::Cast { source: self.mirror_expr(source)}; - }; + return ExprKind::Cast { source: self.mirror_expr(source)}; + }; + + let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res else { + return ExprKind::Cast { source: self.mirror_expr(source)}; + }; let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); let (discr_did, discr_offset) = adt_def.discriminant_def_for_variant(idx); diff --git a/src/test/ui/const-generics/issues/issue-97634.rs b/src/test/ui/const-generics/issues/issue-97634.rs index a04036d0647ad..422e8de685645 100644 --- a/src/test/ui/const-generics/issues/issue-97634.rs +++ b/src/test/ui/const-generics/issues/issue-97634.rs @@ -1,4 +1,4 @@ -//build-pass +// build-pass pub enum Register { Field0 = 40, From e25129b055cae83e1a005d84c8119b74416f94ad Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Fri, 24 Jun 2022 21:05:02 +0400 Subject: [PATCH 22/23] take advantage of a labelled block Co-authored-by: Michael Goulet --- compiler/rustc_typeck/src/check/pat.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 58fd11200c901..5d40f05834355 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -669,9 +669,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let ident_kind = match binding_parent { - hir::Node::Param(_) => Some("parameter"), - hir::Node::Local(_) => Some("variable"), - hir::Node::Arm(_) => Some("binding"), + hir::Node::Param(_) => "parameter", + hir::Node::Local(_) => "variable", + hir::Node::Arm(_) => "binding", // Provide diagnostics only if the parent pattern is struct-like, // i.e. where `mut binding` makes sense @@ -680,7 +680,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::TupleStruct(..) | PatKind::Or(..) | PatKind::Tuple(..) - | PatKind::Slice(..) => Some("binding"), + | PatKind::Slice(..) => "binding", PatKind::Wild | PatKind::Binding(..) @@ -688,16 +688,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Box(..) | PatKind::Ref(..) | PatKind::Lit(..) - | PatKind::Range(..) => None, + | PatKind::Range(..) => break 'block None, }, // Don't provide suggestions in other cases - _ => None, + _ => break 'block None, }; - ident_kind.map(|thing| ( + Some(( pat.span, - format!("to declare a mutable {thing} use `mut variable_name`"), + format!("to declare a mutable {ident_kind} use `mut variable_name`"), format!("mut {binding}"), )) From 1dfb53b7dad1d5f68466a68b068b8030d216ce3f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 24 Jun 2022 21:18:26 +0400 Subject: [PATCH 23/23] improve wording of a suggestion --- compiler/rustc_typeck/src/check/pat.rs | 2 +- .../ui/mismatched_types/ref-pat-suggestions.stderr | 14 +++++++------- src/test/ui/pattern/for-loop-bad-item.stderr | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5d40f05834355..e1ec9f13cd166 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -697,7 +697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(( pat.span, - format!("to declare a mutable {ident_kind} use `mut variable_name`"), + format!("to declare a mutable {ident_kind} use"), format!("mut {binding}"), )) diff --git a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr index cd86bb532abda..d9501a9bbc61e 100644 --- a/src/test/ui/mismatched_types/ref-pat-suggestions.stderr +++ b/src/test/ui/mismatched_types/ref-pat-suggestions.stderr @@ -24,7 +24,7 @@ LL | fn _f1(&mut _a: u32) {} | = note: expected type `u32` found mutable reference `&mut _` -note: to declare a mutable parameter use `mut variable_name`: `mut _a` +note: to declare a mutable parameter use: `mut _a` --> $DIR/ref-pat-suggestions.rs:4:8 | LL | fn _f1(&mut _a: u32) {} @@ -127,7 +127,7 @@ LL | let _: fn(u32) = |&mut _a| (); | = note: expected type `u32` found mutable reference `&mut _` -note: to declare a mutable parameter use `mut variable_name`: `mut _a` +note: to declare a mutable parameter use: `mut _a` --> $DIR/ref-pat-suggestions.rs:12:23 | LL | let _: fn(u32) = |&mut _a| (); @@ -232,7 +232,7 @@ LL | let _ = |&mut _a: u32| (); | = note: expected type `u32` found mutable reference `&mut _` -note: to declare a mutable parameter use `mut variable_name`: `mut _a` +note: to declare a mutable parameter use: `mut _a` --> $DIR/ref-pat-suggestions.rs:19:14 | LL | let _ = |&mut _a: u32| (); @@ -314,7 +314,7 @@ LL | let &mut _a = 0; | ^^^^^^^ - this expression has type `{integer}` | | | expected integer, found `&mut _` - | help: to declare a mutable variable use `mut variable_name`: `mut _a` + | help: to declare a mutable variable use: `mut _a` | = note: expected type `{integer}` found mutable reference `&mut _` @@ -329,7 +329,7 @@ LL | let S(&mut _b) = S(0); | = note: expected type `u8` found mutable reference `&mut _` -note: to declare a mutable binding use `mut variable_name`: `mut _b` +note: to declare a mutable binding use: `mut _b` --> $DIR/ref-pat-suggestions.rs:30:15 | LL | let S(&mut _b) = S(0); @@ -350,7 +350,7 @@ LL | let (&mut _c,) = (0,); | = note: expected type `{integer}` found mutable reference `&mut _` -note: to declare a mutable binding use `mut variable_name`: `mut _c` +note: to declare a mutable binding use: `mut _c` --> $DIR/ref-pat-suggestions.rs:31:14 | LL | let (&mut _c,) = (0,); @@ -371,7 +371,7 @@ LL | &mut _d => {} | = note: expected type `{integer}` found mutable reference `&mut _` -note: to declare a mutable binding use `mut variable_name`: `mut _d` +note: to declare a mutable binding use: `mut _d` --> $DIR/ref-pat-suggestions.rs:34:13 | LL | &mut _d => {} diff --git a/src/test/ui/pattern/for-loop-bad-item.stderr b/src/test/ui/pattern/for-loop-bad-item.stderr index 212d66f649763..f064a25a9c9a4 100644 --- a/src/test/ui/pattern/for-loop-bad-item.stderr +++ b/src/test/ui/pattern/for-loop-bad-item.stderr @@ -8,7 +8,7 @@ LL | for ((_, _), (&mut c, _)) in &mut map { | = note: expected type `char` found mutable reference `&mut _` -note: to declare a mutable binding use `mut variable_name`: `mut c` +note: to declare a mutable binding use: `mut c` --> $DIR/for-loop-bad-item.rs:7:19 | LL | for ((_, _), (&mut c, _)) in &mut map {