From 8b1f85caede44808e62542cfdff04787d70f8f7f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 26 Apr 2022 00:13:24 +0100 Subject: [PATCH 01/25] 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/25] 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/25] 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 edb6c4b092f7b85bdddad7e2fefb259ffc41bd9d Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 16 May 2022 17:54:12 +0200 Subject: [PATCH 04/25] Add a test for issue #33172 --- src/test/debuginfo/no_mangle-info.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/debuginfo/no_mangle-info.rs diff --git a/src/test/debuginfo/no_mangle-info.rs b/src/test/debuginfo/no_mangle-info.rs new file mode 100644 index 0000000000000..c34de43768c41 --- /dev/null +++ b/src/test/debuginfo/no_mangle-info.rs @@ -0,0 +1,26 @@ +// compile-flags:-g + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:whatis TEST +// gdb-check:type = u64 + +// === LLDB TESTS ================================================================================== + +// lldb-command:run +// lldb-command:expr TEST +// lldb-check: (unsigned long) $0 = 3735928559 + +// === CDB TESTS ================================================================================== +// cdb-command: g + +// cdb-command: dx a!no_mangle_info::TEST +// cdb-check: a!no_mangle_info::TEST : 0xdeadbeef [Type: unsigned __int64] + +#[no_mangle] +pub static TEST: u64 = 0xdeadbeef; + +pub fn main() { + println!("TEST: {}", TEST); // #break +} From f30c76a18abdf79c0e12114f04f2a075236fdd28 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 20 Jun 2022 15:38:22 +0200 Subject: [PATCH 05/25] Turn off cdb test for now, link to issue --- src/test/debuginfo/no_mangle-info.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/debuginfo/no_mangle-info.rs b/src/test/debuginfo/no_mangle-info.rs index c34de43768c41..7bedcaf2110e8 100644 --- a/src/test/debuginfo/no_mangle-info.rs +++ b/src/test/debuginfo/no_mangle-info.rs @@ -1,22 +1,21 @@ // compile-flags:-g // === GDB TESTS =================================================================================== - // gdb-command:run // gdb-command:whatis TEST // gdb-check:type = u64 // === LLDB TESTS ================================================================================== - // lldb-command:run // lldb-command:expr TEST // lldb-check: (unsigned long) $0 = 3735928559 // === CDB TESTS ================================================================================== -// cdb-command: g - -// cdb-command: dx a!no_mangle_info::TEST -// cdb-check: a!no_mangle_info::TEST : 0xdeadbeef [Type: unsigned __int64] +// FIXME: This does not currently work due to a bug in LLVM +// The fix for this is being tracked in rust-lang/rust#98295 +// // cdb-command: g +// // cdb-command: dx a!no_mangle_info::TEST +// // cdb-check: a!no_mangle_info::TEST : 0xdeadbeef [Type: unsigned __int64] #[no_mangle] pub static TEST: u64 = 0xdeadbeef; From 3ea686f599d2972f0c2f0b21bc20c986450b4948 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 20 Jun 2022 18:45:08 +0200 Subject: [PATCH 06/25] Turn CDB test back on and all clarifying test --- src/test/debuginfo/no_mangle-info.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/test/debuginfo/no_mangle-info.rs b/src/test/debuginfo/no_mangle-info.rs index 7bedcaf2110e8..1e182eb7cc06f 100644 --- a/src/test/debuginfo/no_mangle-info.rs +++ b/src/test/debuginfo/no_mangle-info.rs @@ -4,22 +4,34 @@ // gdb-command:run // gdb-command:whatis TEST // gdb-check:type = u64 +// gdb-command:whatis no_mangle_info::namespace::OTHER_TEST +// gdb-check:type = u64 // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:expr TEST // lldb-check: (unsigned long) $0 = 3735928559 +// lldb-command:expr no_mangle_test::namespace::OTHER_TEST +// lldb-check: (unsigned long) $0 = 42 // === CDB TESTS ================================================================================== -// FIXME: This does not currently work due to a bug in LLVM -// The fix for this is being tracked in rust-lang/rust#98295 -// // cdb-command: g -// // cdb-command: dx a!no_mangle_info::TEST -// // cdb-check: a!no_mangle_info::TEST : 0xdeadbeef [Type: unsigned __int64] +// cdb-command: g +// Note: LLDB and GDB allow referring to items that are in the same namespace of the symbol +// we currently have a breakpoint on in an unqualified way. CDB does not, and thus we need to +// refer to it in a fully qualified way. +// cdb-command: dx a!no_mangle_info::TEST +// cdb-check: a!no_mangle_info::TEST : 0xdeadbeef [Type: unsigned __int64] +// cdb-command: dx a!no_mangle_info::namespace::OTHER_TEST +// cdb-check: a!no_mangle_info::namespace::OTHER_TEST : 0x2a [Type: unsigned __int64] #[no_mangle] pub static TEST: u64 = 0xdeadbeef; +pub mod namespace { + pub static OTHER_TEST: u64 = 42; +} + pub fn main() { - println!("TEST: {}", TEST); // #break + println!("TEST: {}", TEST); + println!("OTHER TEST: {}", namespace::OTHER_TEST); // #break } From e5402e4a22dc9bc2b26e8fea06b9fb7412d81e03 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 21 Jun 2022 14:53:55 +0200 Subject: [PATCH 07/25] Fix linux tests --- src/test/debuginfo/no_mangle-info.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/debuginfo/no_mangle-info.rs b/src/test/debuginfo/no_mangle-info.rs index 1e182eb7cc06f..fc40f130fcbf6 100644 --- a/src/test/debuginfo/no_mangle-info.rs +++ b/src/test/debuginfo/no_mangle-info.rs @@ -2,17 +2,17 @@ // === GDB TESTS =================================================================================== // gdb-command:run -// gdb-command:whatis TEST -// gdb-check:type = u64 -// gdb-command:whatis no_mangle_info::namespace::OTHER_TEST -// gdb-check:type = u64 +// gdb-command:p TEST +// gdb-check:$1 = 3735928559 +// gdb-command:p no_mangle_info::namespace::OTHER_TEST +// gdb-check:$2 = 42 // === LLDB TESTS ================================================================================== // lldb-command:run -// lldb-command:expr TEST +// lldb-command:p TEST // lldb-check: (unsigned long) $0 = 3735928559 -// lldb-command:expr no_mangle_test::namespace::OTHER_TEST -// lldb-check: (unsigned long) $0 = 42 +// lldb-command:p OTHER_TEST +// lldb-check: (unsigned long) $1 = 42 // === CDB TESTS ================================================================================== // cdb-command: g From 1a25ac9d2240d745b8ec66a480f6241fa2b1d32a Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Tue, 21 Jun 2022 17:10:46 +0200 Subject: [PATCH 08/25] Add comment about issue caused with multiple statics --- src/test/debuginfo/no_mangle-info.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/debuginfo/no_mangle-info.rs b/src/test/debuginfo/no_mangle-info.rs index fc40f130fcbf6..0b058b0827e3a 100644 --- a/src/test/debuginfo/no_mangle-info.rs +++ b/src/test/debuginfo/no_mangle-info.rs @@ -27,6 +27,8 @@ #[no_mangle] pub static TEST: u64 = 0xdeadbeef; +// FIXME: uncommenting this namespace breaks the test, and we're not sure why +// pub static OTHER_TEST: u64 = 43; pub mod namespace { pub static OTHER_TEST: u64 = 42; } From 6ac6866bec092e0c2a3e0fc4aaf14b015b859a57 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 20 Jun 2022 21:10:43 +0100 Subject: [PATCH 09/25] 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 10/25] 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 aa917163de30198227f2ddd4b5208b7143bed9bf Mon Sep 17 00:00:00 2001 From: ouz-a Date: Mon, 13 Jun 2022 16:37:41 +0300 Subject: [PATCH 11/25] add new rval, pull deref early --- compiler/rustc_borrowck/src/invalidation.rs | 4 +++ compiler/rustc_borrowck/src/lib.rs | 17 +++++++++ compiler/rustc_borrowck/src/type_check/mod.rs | 5 +++ compiler/rustc_codegen_cranelift/src/base.rs | 5 +++ compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 6 ++++ .../rustc_const_eval/src/interpret/step.rs | 5 +++ .../src/transform/check_consts/check.rs | 1 + .../src/transform/check_consts/qualifs.rs | 2 ++ .../src/transform/check_consts/resolver.rs | 1 + .../src/transform/promote_consts.rs | 4 +++ compiler/rustc_middle/src/mir/mod.rs | 26 ++++++++++++-- compiler/rustc_middle/src/mir/tcx.rs | 1 + .../rustc_middle/src/mir/type_foldable.rs | 2 ++ compiler/rustc_middle/src/mir/visit.rs | 7 ++++ .../src/impls/borrowed_locals.rs | 3 +- compiler/rustc_mir_dataflow/src/lib.rs | 1 + .../src/move_paths/builder.rs | 28 ++++++++++++++- compiler/rustc_mir_dataflow/src/un_derefer.rs | 31 ++++++++++++++++ compiler/rustc_mir_transform/src/add_retag.rs | 13 +------ .../rustc_mir_transform/src/const_prop.rs | 1 + .../src/const_prop_lint.rs | 1 + .../src/deref_separator.rs | 3 +- .../src/elaborate_drops.rs | 36 +++++++++++++++---- compiler/rustc_mir_transform/src/lib.rs | 2 +- .../src/separate_const_switch.rs | 2 ++ .../derefer_complex_case.main.Derefer.diff | 10 +++--- .../derefer_inline_test.main.Derefer.diff | 20 ++++------- .../derefer_terminator_test.main.Derefer.diff | 14 ++++---- .../mir-opt/derefer_test.main.Derefer.diff | 12 +++---- .../derefer_test_multiple.main.Derefer.diff | 20 +++++------ ...re-SimplifyConstCondition-final.after.diff | 26 +++++++------- ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 26 +++++++------- ...ness.no_downcast.EarlyOtherwiseBranch.diff | 2 +- ...line_closure_captures.foo.Inline.after.mir | 4 +-- .../inline/inline_generator.main.Inline.diff | 6 ++-- ...67_inline_as_ref_as_mut.b.Inline.after.mir | 2 +- ...67_inline_as_ref_as_mut.d.Inline.after.mir | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 1 + 38 files changed, 251 insertions(+), 101 deletions(-) create mode 100644 compiler/rustc_mir_dataflow/src/un_derefer.rs diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 0425c53d9dc3c..8317206c69adb 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -289,6 +289,10 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => { self.consume_operand(location, operand) } + Rvalue::VirtualRef(ref place) => { + let op = &Operand::Copy(*place); + self.consume_operand(location, op); + } Rvalue::Len(place) | Rvalue::Discriminant(place) => { let af = match *rvalue { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8ef2974c37232..9d8c5fe6d41d2 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1224,6 +1224,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => { self.consume_operand(location, (operand, span), flow_state) } + Rvalue::VirtualRef(place) => { + self.access_place( + location, + (place, span), + (Deep, Read(ReadKind::Copy)), + LocalMutationIsAllowed::No, + flow_state, + ); + + // Finally, check if path was already moved. + self.check_if_path_or_subpath_is_moved( + location, + InitializationRequiringAction::Use, + (place.as_ref(), span), + flow_state, + ); + } Rvalue::Len(place) | Rvalue::Discriminant(place) => { let af = match *rvalue { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index ae6b8e0ae30f7..678f7c1b730aa 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2274,6 +2274,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => { self.check_operand(operand, location); } + Rvalue::VirtualRef(place) => { + let op = &Operand::Copy(*place); + self.check_operand(op, location); + } Rvalue::BinaryOp(_, box (left, right)) | Rvalue::CheckedBinaryOp(_, box (left, right)) => { @@ -2304,6 +2308,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::BinaryOp(..) | Rvalue::CheckedBinaryOp(..) | Rvalue::NullaryOp(..) + | Rvalue::VirtualRef(..) | Rvalue::UnaryOp(..) | Rvalue::Discriminant(..) => None, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index fbe830b2b1030..9f40b5264576c 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -503,6 +503,11 @@ fn codegen_stmt<'tcx>( let val = codegen_operand(fx, operand); lval.write_cvalue(fx, val); } + Rvalue::VirtualRef(place) => { + let cplace = codegen_place(fx, place); + let val = cplace.to_cvalue(fx); + lval.write_cvalue(fx, val) + } Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { let place = codegen_place(fx, place); let ref_ = place.place_ref(fx, lval.layout()); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 81c1897694ce6..30fc4db6e89bf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -8,6 +8,7 @@ use crate::traits::*; use crate::MemFlags; use rustc_middle::mir; +use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; @@ -401,6 +402,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_place_to_pointer(bx, place, mk_ref) } + mir::Rvalue::VirtualRef(place) => { + let operand = self.codegen_operand(&mut bx, &Operand::Copy(place)); + (bx, operand) + } mir::Rvalue::AddressOf(mutability, place) => { let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| { tcx.mk_ptr(ty::TypeAndMut { ty, mutbl: mutability }) @@ -755,6 +760,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Ref(..) | + mir::Rvalue::VirtualRef(..) | mir::Rvalue::AddressOf(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 98f69456e49aa..06a2f40daef4f 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -172,6 +172,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.copy_op(&op, &dest)?; } + VirtualRef(ref place) => { + let op = self.eval_place_to_op(*place, Some(dest.layout))?; + self.copy_op(&op, &dest)?; + } + BinaryOp(bin_op, box (ref left, ref right)) => { let layout = binop_left_homogeneous(bin_op).then_some(dest.layout); let left = self.read_immediate(&self.eval_operand(left, layout)?)?; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 069fbed36ee3a..d216cde9d2886 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -445,6 +445,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess), Rvalue::Use(_) + | Rvalue::VirtualRef(..) | Rvalue::Repeat(..) | Rvalue::Discriminant(..) | Rvalue::Len(_) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 6e5a0c813ac20..84eddbb355cfa 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -260,6 +260,8 @@ where in_place::(cx, in_local, place.as_ref()) } + Rvalue::VirtualRef(place) => in_place::(cx, in_local, place.as_ref()), + Rvalue::Use(operand) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_, operand) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index fd7febc17a3a7..e6c9f57e0d8c8 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -199,6 +199,7 @@ where mir::Rvalue::Cast(..) | mir::Rvalue::ShallowInitBox(..) | mir::Rvalue::Use(..) + | mir::Rvalue::VirtualRef(..) | mir::Rvalue::ThreadLocalRef(..) | mir::Rvalue::Repeat(..) | mir::Rvalue::Len(..) diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 3595a488d0c5b..2b4bdf5b5f28a 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -494,6 +494,10 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::Use(operand) | Rvalue::Repeat(operand, _) => { self.validate_operand(operand)?; } + Rvalue::VirtualRef(place) => { + let op = &Operand::Copy(*place); + self.validate_operand(op)? + } Rvalue::Discriminant(place) | Rvalue::Len(place) => { self.validate_place(place.as_ref())? diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4265559cd3197..dd69a0fafecf2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -159,6 +159,8 @@ pub enum MirPhase { /// of the `mir_promoted` query), these promoted elements are available in the `promoted_mir` /// query. ConstsPromoted = 2, + /// After this projections may only contain deref projections as the first element. + Derefered = 3, /// Beginning with this phase, the following variants are disallowed: /// * [`TerminatorKind::DropAndReplace`](terminator::TerminatorKind::DropAndReplace) /// * [`TerminatorKind::FalseUnwind`](terminator::TerminatorKind::FalseUnwind) @@ -173,9 +175,7 @@ pub enum MirPhase { /// Furthermore, `Drop` now uses explicit drop flags visible in the MIR and reaching a `Drop` /// terminator means that the auto-generated drop glue will be invoked. Also, `Copy` operands /// are allowed for non-`Copy` types. - DropsLowered = 3, - /// After this projections may only contain deref projections as the first element. - Derefered = 4, + DropsLowered = 4, /// Beginning with this phase, the following variant is disallowed: /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` /// @@ -1174,6 +1174,15 @@ impl<'tcx> LocalDecl<'tcx> { } } + /// Returns `true` if this is a DerefTemp + pub fn is_deref_temp(&self) -> bool { + match self.local_info { + Some(box LocalInfo::DerefTemp) => return true, + _ => (), + } + return false; + } + /// Returns `true` is the local is from a compiler desugaring, e.g., /// `__next` from a `for` loop. #[inline] @@ -2602,6 +2611,15 @@ pub enum Rvalue<'tcx> { /// initialized but its content as uninitialized. Like other pointer casts, this in general /// affects alias analysis. ShallowInitBox(Operand<'tcx>, Ty<'tcx>), + + /// A virtual ref is equivalent to a read from a reference/pointer at the + /// codegen level, but is treated specially by drop elaboration. When such a read happens, it + /// is guaranteed that the only use of the returned value is a deref operation, immediately + /// followed by one or more projections. Drop elaboration treats this virtual ref as if the + /// read never happened and just projects further. This allows simplifying various MIR + /// optimizations and codegen backends that previously had to handle deref operations anywhere + /// in a place. + VirtualRef(Place<'tcx>), } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -2618,6 +2636,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false, Rvalue::Use(_) + | Rvalue::VirtualRef(_) | Rvalue::Repeat(_, _) | Rvalue::Ref(_, _, _) | Rvalue::ThreadLocalRef(_) @@ -2795,6 +2814,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; write!(fmt, "&{}{}{:?}", region, kind_str, place) } + VirtualRef(ref place) => write!(fmt, "virt {:#?}", place), AddressOf(mutability, ref place) => { let kind_str = match mutability { diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index c93b7a9550229..8ec04e61a2e0b 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -211,6 +211,7 @@ impl<'tcx> Rvalue<'tcx> { } }, Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty), + Rvalue::VirtualRef(ref place) => place.ty(local_decls, tcx).ty, } } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 4201b2d11ce2a..f20c0101d9fd5 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -184,6 +184,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Ref(region, bk, place) => { Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?) } + VirtualRef(place) => VirtualRef(place.try_fold_with(folder)?), AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?), Len(place) => Len(place.try_fold_with(folder)?), Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?), @@ -235,6 +236,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { region.visit_with(visitor)?; place.visit_with(visitor) } + VirtualRef(ref place) => place.visit_with(visitor), AddressOf(_, ref place) => place.visit_with(visitor), Len(ref place) => place.visit_with(visitor), Cast(_, ref op, ty) => { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 5ce92d127f3db..9aea4ae61d44a 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -670,6 +670,13 @@ macro_rules! make_mir_visitor { }; self.visit_place(path, ctx, location); } + Rvalue::VirtualRef(place) => { + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); + } Rvalue::AddressOf(m, path) => { let ctx = match m { diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 627fe3f7f576b..4681f942f92ff 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -102,7 +102,8 @@ where | mir::Rvalue::NullaryOp(..) | mir::Rvalue::UnaryOp(..) | mir::Rvalue::Discriminant(..) - | mir::Rvalue::Aggregate(..) => {} + | mir::Rvalue::Aggregate(..) + | mir::Rvalue::VirtualRef(..) => {} } } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index e4c130f0807dd..5793a286bd03d 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -38,6 +38,7 @@ pub mod impls; pub mod move_paths; pub mod rustc_peek; pub mod storage; +pub mod un_derefer; pub(crate) mod indexes { pub(crate) use super::move_paths::MovePathIndex; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index b08cb50f77aed..75b0a68e65802 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -1,3 +1,4 @@ +use crate::un_derefer::UnDerefer; use rustc_index::vec::IndexVec; use rustc_middle::mir::tcx::RvalueInitializationState; use rustc_middle::mir::*; @@ -19,6 +20,7 @@ struct MoveDataBuilder<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, data: MoveData<'tcx>, errors: Vec<(Place<'tcx>, MoveError<'tcx>)>, + un_derefer: UnDerefer<'tcx>, } impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { @@ -32,6 +34,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { tcx, param_env, errors: Vec::new(), + un_derefer: UnDerefer { tcx: tcx, derefer_sidetable: Default::default() }, data: MoveData { moves: IndexVec::new(), loc_map: LocationMap::new(body), @@ -94,6 +97,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { /// /// Maybe we should have separate "borrowck" and "moveck" modes. fn move_path_for(&mut self, place: Place<'tcx>) -> Result> { + if let Some(new_place) = self.builder.un_derefer.derefer(place.as_ref()) { + return self.move_path_for(new_place); + } + debug!("lookup({:?})", place); let mut base = self.builder.data.rev_lookup.locals[place.local]; @@ -224,6 +231,8 @@ pub(super) fn gather_moves<'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> Result, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> { let mut builder = MoveDataBuilder::new(body, tcx, param_env); + let mut un_derefer = UnDerefer { tcx: tcx, derefer_sidetable: Default::default() }; + un_derefer.ref_finder(body); builder.gather_args(); @@ -276,6 +285,10 @@ struct Gatherer<'b, 'a, 'tcx> { impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_statement(&mut self, stmt: &Statement<'tcx>) { match &stmt.kind { + StatementKind::Assign(box (place, Rvalue::VirtualRef(reffed))) => { + assert!(place.projection.is_empty()); + self.builder.un_derefer.derefer_sidetable.insert(place.local, *reffed); + } StatementKind::Assign(box (place, rval)) => { self.create_move_path(*place); if let RvalueInitializationState::Shallow = rval.initialization_state() { @@ -294,7 +307,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } StatementKind::StorageLive(_) => {} StatementKind::StorageDead(local) => { - self.gather_move(Place::from(*local)); + // DerefTemp locals (results of VirtualRef) don't actually move anything. + if !self.builder.un_derefer.derefer_sidetable.contains_key(&local) { + self.gather_move(Place::from(*local)); + } } StatementKind::SetDiscriminant { .. } | StatementKind::Deinit(..) => { span_bug!( @@ -328,6 +344,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_operand(operand); } } + Rvalue::VirtualRef(..) => unreachable!(), Rvalue::Ref(..) | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) @@ -439,6 +456,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_move(&mut self, place: Place<'tcx>) { debug!("gather_move({:?}, {:?})", self.loc, place); + if let Some(new_place) = self.builder.un_derefer.derefer(place.as_ref()) { + self.gather_move(new_place); + return; + } if let [ref base @ .., ProjectionElem::Subslice { from, to, from_end: false }] = **place.projection @@ -494,6 +515,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) { debug!("gather_init({:?}, {:?})", self.loc, place); + if let Some(new_place) = self.builder.un_derefer.derefer(place) { + self.gather_init(new_place.as_ref(), kind); + return; + } + let mut place = place; // Check if we are assigning into a field of a union, if so, lookup the place diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs new file mode 100644 index 0000000000000..4c45d385707b1 --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/un_derefer.rs @@ -0,0 +1,31 @@ +use rustc_data_structures::stable_map::FxHashMap; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +/// Used for reverting changes made by `DerefSeparator` +pub struct UnDerefer<'tcx> { + pub tcx: TyCtxt<'tcx>, + pub derefer_sidetable: FxHashMap>, +} + +impl<'tcx> UnDerefer<'tcx> { + pub fn derefer(&self, place: PlaceRef<'tcx>) -> Option> { + let reffed = self.derefer_sidetable.get(&place.local)?; + + let new_place = reffed.project_deeper(place.projection, self.tcx); + Some(new_place) + } + + pub fn ref_finder(&mut self, body: &Body<'tcx>) { + for (_bb, data) in body.basic_blocks().iter_enumerated() { + for stmt in data.statements.iter() { + match stmt.kind { + StatementKind::Assign(box (place, Rvalue::VirtualRef(reffed))) => { + self.derefer_sidetable.insert(place.local, reffed); + } + _ => (), + } + } + } + } +} diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 0495439385bee..000abbee51e38 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -57,17 +57,6 @@ fn may_be_reference(ty: Ty<'_>) -> bool { } } -/// Determines whether or not this LocalDecl is temp, if not it needs retagging. -fn is_not_temp<'tcx>(local_decl: &LocalDecl<'tcx>) -> bool { - if let Some(local_info) = &local_decl.local_info { - match local_info.as_ref() { - LocalInfo::DerefTemp => return false, - _ => (), - }; - } - return true; -} - impl<'tcx> MirPass<'tcx> for AddRetag { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.opts.debugging_opts.mir_emit_retag @@ -84,7 +73,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // a temporary and retag on that. is_stable(place.as_ref()) && may_be_reference(place.ty(&*local_decls, tcx).ty) - && is_not_temp(&local_decls[place.local]) + && !local_decls[place.local].is_deref_temp() }; let place_base_raw = |place: &Place<'tcx>| { // If this is a `Deref`, get the type of what we are deref'ing. diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 412a5b4fc9104..8b17b70e196f8 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -616,6 +616,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // There's no other checking to do at this time. Rvalue::Aggregate(..) | Rvalue::Use(..) + | Rvalue::VirtualRef(..) | Rvalue::Repeat(..) | Rvalue::Len(..) | Rvalue::Cast(..) diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 15ad13009e59a..b29440f17e45f 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -683,6 +683,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // There's no other checking to do at this time. Rvalue::Aggregate(..) | Rvalue::Use(..) + | Rvalue::VirtualRef(..) | Rvalue::Repeat(..) | Rvalue::Len(..) | Rvalue::Cast(..) diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index bfb3ad1be2734..badb092fb25db 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -35,6 +35,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> { last_deref_idx = idx; } } + for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() { if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref { let ty = p_ref.ty(&self.local_decls, self.tcx).ty; @@ -54,7 +55,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> { self.patcher.add_assign( loc, Place::from(temp), - Rvalue::Use(Operand::Move(deref_place)), + Rvalue::VirtualRef(deref_place), ); place_local = temp; last_len = p_ref.projection.len(); diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index e0e27c53f1822..d11f514ee1ae2 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -1,3 +1,4 @@ +use crate::deref_separator::deref_finder; use crate::MirPass; use rustc_data_structures::fx::FxHashMap; use rustc_index::bit_set::BitSet; @@ -9,6 +10,7 @@ use rustc_mir_dataflow::elaborate_drops::{DropElaborator, DropFlagMode, DropStyl use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::on_lookup_result_bits; +use rustc_mir_dataflow::un_derefer::UnDerefer; use rustc_mir_dataflow::MoveDataParamEnv; use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits}; use rustc_mir_dataflow::{Analysis, ResultsCursor}; @@ -26,6 +28,8 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); + let mut un_derefer = UnDerefer { tcx: tcx, derefer_sidetable: Default::default() }; + un_derefer.ref_finder(body); let def_id = body.source.def_id(); let param_env = tcx.param_env_reveal_all_normalized(def_id); let move_data = match MoveData::gather_moves(body, tcx, param_env) { @@ -41,7 +45,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { let elaborate_patch = { let body = &*body; let env = MoveDataParamEnv { move_data, param_env }; - let dead_unwinds = find_dead_unwinds(tcx, body, &env); + let dead_unwinds = find_dead_unwinds(tcx, body, &env, &un_derefer); let inits = MaybeInitializedPlaces::new(tcx, body, &env) .into_engine(tcx, body) @@ -65,10 +69,12 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { init_data: InitializationData { inits, uninits }, drop_flags: Default::default(), patch: MirPatch::new(body), + un_derefer: un_derefer, } .elaborate() }; elaborate_patch.apply(body); + deref_finder(tcx, body); } } @@ -79,6 +85,7 @@ fn find_dead_unwinds<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, env: &MoveDataParamEnv<'tcx>, + und: &UnDerefer<'tcx>, ) -> BitSet { debug!("find_dead_unwinds({:?})", body.span); // We only need to do this pass once, because unwind edges can only @@ -92,7 +99,9 @@ fn find_dead_unwinds<'tcx>( for (bb, bb_data) in body.basic_blocks().iter_enumerated() { let place = match bb_data.terminator().kind { TerminatorKind::Drop { ref place, unwind: Some(_), .. } - | TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => place, + | TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => { + und.derefer(place.as_ref()).unwrap_or(*place) + } _ => continue, }; @@ -256,6 +265,7 @@ struct ElaborateDropsCtxt<'a, 'tcx> { init_data: InitializationData<'a, 'tcx>, drop_flags: FxHashMap, patch: MirPatch<'tcx>, + un_derefer: UnDerefer<'tcx>, } impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { @@ -298,7 +308,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let terminator = data.terminator(); let place = match terminator.kind { TerminatorKind::Drop { ref place, .. } - | TerminatorKind::DropAndReplace { ref place, .. } => place, + | TerminatorKind::DropAndReplace { ref place, .. } => { + self.un_derefer.derefer(place.as_ref()).unwrap_or(*place) + } _ => continue, }; @@ -312,12 +324,17 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { LookupResult::Parent(None) => continue, LookupResult::Parent(Some(parent)) => { let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent); + + if self.body.local_decls[place.local].is_deref_temp() { + continue; + } + if maybe_dead { self.tcx.sess.delay_span_bug( terminator.source_info.span, &format!( "drop of untracked, uninitialized value {:?}, place {:?} ({:?})", - bb, place, path, + bb, place, path ), ); } @@ -348,7 +365,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let resume_block = self.patch.resume_block(); match terminator.kind { - TerminatorKind::Drop { place, target, unwind } => { + TerminatorKind::Drop { mut place, target, unwind } => { + if let Some(new_place) = self.un_derefer.derefer(place.as_ref()) { + place = new_place; + } + self.init_data.seek_before(loc); match self.move_data().rev_lookup.find(place.as_ref()) { LookupResult::Exact(path) => elaborate_drop( @@ -372,9 +393,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } } } - TerminatorKind::DropAndReplace { place, ref value, target, unwind } => { + TerminatorKind::DropAndReplace { mut place, ref value, target, unwind } => { assert!(!data.is_cleanup); + if let Some(new_place) = self.un_derefer.derefer(place.as_ref()) { + place = new_place; + } self.elaborate_replace(loc, place, value, target, unwind); } _ => continue, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b7caa61ef07a7..37014497c6887 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -415,6 +415,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc &remove_noop_landing_pads::RemoveNoopLandingPads, &cleanup_post_borrowck::CleanupNonCodegenStatements, &simplify::SimplifyCfg::new("early-opt"), + &deref_separator::Derefer, // These next passes must be executed together &add_call_guards::CriticalCallEdges, &elaborate_drops::ElaborateDrops, @@ -427,7 +428,6 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc &add_moves_for_packed_drops::AddMovesForPackedDrops, // `AddRetag` needs to run after `ElaborateDrops`. Otherwise it should run fairly late, // but before optimizations begin. - &deref_separator::Derefer, &elaborate_box_derefs::ElaborateBoxDerefs, &add_retag::AddRetag, &lower_intrinsics::LowerIntrinsics, diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 33ea1c4ba2f59..ec4bff30f95cd 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -218,6 +218,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData< // These rvalues move the place to track Rvalue::Cast(_, Operand::Copy(place) | Operand::Move(place), _) | Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) + | Rvalue::VirtualRef(place) | Rvalue::UnaryOp(_, Operand::Copy(place) | Operand::Move(place)) | Rvalue::Discriminant(place) => tracked_place = place, } @@ -279,6 +280,7 @@ fn find_determining_place<'tcx>( // that may be const in the predecessor Rvalue::Use(Operand::Move(new) | Operand::Copy(new)) | Rvalue::UnaryOp(_, Operand::Copy(new) | Operand::Move(new)) + | Rvalue::VirtualRef(new) | Rvalue::Cast(_, Operand::Move(new) | Operand::Copy(new), _) | Rvalue::Repeat(Operand::Move(new) | Operand::Copy(new), _) | Rvalue::Discriminant(new) diff --git a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff index f5eabf8696796..75b301016d76e 100644 --- a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff +++ b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff @@ -69,7 +69,7 @@ StorageLive(_12); // scope 1 at $DIR/derefer_complex_case.rs:4:10: 4:13 - _12 = (*((_7 as Some).0: &i32)); // scope 1 at $DIR/derefer_complex_case.rs:4:10: 4:13 + StorageLive(_15); // scope 1 at $DIR/derefer_complex_case.rs:4:10: 4:13 -+ _15 = move ((_7 as Some).0: &i32); // scope 1 at $DIR/derefer_complex_case.rs:4:10: 4:13 ++ _15 = virt ((_7 as Some).0: &i32); // scope 1 at $DIR/derefer_complex_case.rs:4:10: 4:13 + _12 = (*_15); // scope 1 at $DIR/derefer_complex_case.rs:4:10: 4:13 + StorageDead(_15); // scope 2 at $DIR/derefer_complex_case.rs:4:34: 4:37 StorageLive(_13); // scope 2 at $DIR/derefer_complex_case.rs:4:34: 4:37 @@ -102,10 +102,10 @@ StorageDead(_6); // scope 1 at $DIR/derefer_complex_case.rs:4:39: 4:40 _5 = const (); // scope 1 at $DIR/derefer_complex_case.rs:4:5: 4:40 goto -> bb2; // scope 1 at $DIR/derefer_complex_case.rs:4:5: 4:40 - } - - bb8 (cleanup): { - resume; // scope 0 at $DIR/derefer_complex_case.rs:3:1: 5:2 ++ } ++ ++ bb8 (cleanup): { ++ resume; // scope 0 at $DIR/derefer_complex_case.rs:3:1: 5:2 } } diff --git a/src/test/mir-opt/derefer_inline_test.main.Derefer.diff b/src/test/mir-opt/derefer_inline_test.main.Derefer.diff index e131adae2b683..b9bf710d3fdf3 100644 --- a/src/test/mir-opt/derefer_inline_test.main.Derefer.diff +++ b/src/test/mir-opt/derefer_inline_test.main.Derefer.diff @@ -8,7 +8,6 @@ let mut _3: usize; // in scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 let mut _4: *mut u8; // in scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 let mut _5: std::boxed::Box>; // in scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 - let mut _6: (); // in scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 scope 1 { } @@ -25,7 +24,7 @@ bb1: { StorageLive(_5); // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 _5 = ShallowInitBox(move _4, std::boxed::Box); // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 - (*_5) = f() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/derefer_inline_test.rs:10:9: 10:12 + (*_5) = f() -> [return: bb2, unwind: bb6]; // scope 0 at $DIR/derefer_inline_test.rs:10:9: 10:12 // mir::Constant // + span: $DIR/derefer_inline_test.rs:10:9: 10:10 // + literal: Const { ty: fn() -> Box {f}, val: Value(Scalar()) } @@ -33,12 +32,12 @@ bb2: { _1 = move _5; // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 - goto -> bb3; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 + drop(_5) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 } bb3: { StorageDead(_5); // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 - drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/derefer_inline_test.rs:10:12: 10:13 + drop(_1) -> bb4; // scope 0 at $DIR/derefer_inline_test.rs:10:12: 10:13 } bb4: { @@ -48,22 +47,15 @@ } bb5 (cleanup): { - goto -> bb8; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 + drop(_1) -> bb7; // scope 0 at $DIR/derefer_inline_test.rs:10:12: 10:13 } bb6 (cleanup): { - resume; // scope 0 at $DIR/derefer_inline_test.rs:9:1: 11:2 + drop(_5) -> bb7; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 } bb7 (cleanup): { - _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 - // mir::Constant - // + span: $DIR/derefer_inline_test.rs:10:11: 10:12 - // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } - } - - bb8 (cleanup): { - goto -> bb7; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 + resume; // scope 0 at $DIR/derefer_inline_test.rs:9:1: 11:2 } } diff --git a/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff b/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff index 8b91a65bf3d7d..cfa3eb3f2d78b 100644 --- a/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff +++ b/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff @@ -56,12 +56,12 @@ _4 = &_5; // scope 2 at $DIR/derefer_terminator_test.rs:5:15: 5:22 - switchInt((*(*(*(*_4))))) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 + StorageLive(_10); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 -+ _10 = move (*_4); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 ++ _10 = virt (*_4); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 + StorageLive(_11); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 -+ _11 = move (*_10); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 ++ _11 = virt (*_10); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 + StorageDead(_10); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 + StorageLive(_12); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 -+ _12 = move (*_11); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 ++ _12 = virt (*_11); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 + StorageDead(_11); // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 + switchInt((*_12)) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:5:5: 5:22 } @@ -94,10 +94,10 @@ StorageDead(_2); // scope 1 at $DIR/derefer_terminator_test.rs:10:1: 10:2 StorageDead(_1); // scope 0 at $DIR/derefer_terminator_test.rs:10:1: 10:2 return; // scope 0 at $DIR/derefer_terminator_test.rs:10:2: 10:2 - } - - bb6 (cleanup): { - resume; // scope 0 at $DIR/derefer_terminator_test.rs:2:1: 10:2 ++ } ++ ++ bb6 (cleanup): { ++ resume; // scope 0 at $DIR/derefer_terminator_test.rs:2:1: 10:2 } } diff --git a/src/test/mir-opt/derefer_test.main.Derefer.diff b/src/test/mir-opt/derefer_test.main.Derefer.diff index 84476aeed7a6c..589fc4210fc24 100644 --- a/src/test/mir-opt/derefer_test.main.Derefer.diff +++ b/src/test/mir-opt/derefer_test.main.Derefer.diff @@ -34,13 +34,13 @@ StorageLive(_4); // scope 2 at $DIR/derefer_test.rs:5:9: 5:10 - _4 = &mut ((*(_2.1: &mut (i32, i32))).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 + StorageLive(_6); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 -+ _6 = move (_2.1: &mut (i32, i32)); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 ++ _6 = virt (_2.1: &mut (i32, i32)); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 + _4 = &mut ((*_6).0: i32); // scope 2 at $DIR/derefer_test.rs:5:13: 5:26 + StorageDead(_6); // scope 3 at $DIR/derefer_test.rs:6:9: 6:10 StorageLive(_5); // scope 3 at $DIR/derefer_test.rs:6:9: 6:10 - _5 = &mut ((*(_2.1: &mut (i32, i32))).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 + StorageLive(_7); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 -+ _7 = move (_2.1: &mut (i32, i32)); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 ++ _7 = virt (_2.1: &mut (i32, i32)); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 + _5 = &mut ((*_7).1: i32); // scope 3 at $DIR/derefer_test.rs:6:13: 6:26 + StorageDead(_7); // scope 0 at $DIR/derefer_test.rs:2:11: 7:2 _0 = const (); // scope 0 at $DIR/derefer_test.rs:2:11: 7:2 @@ -49,10 +49,10 @@ StorageDead(_2); // scope 1 at $DIR/derefer_test.rs:7:1: 7:2 StorageDead(_1); // scope 0 at $DIR/derefer_test.rs:7:1: 7:2 return; // scope 0 at $DIR/derefer_test.rs:7:2: 7:2 - } - - bb1 (cleanup): { - resume; // scope 0 at $DIR/derefer_test.rs:2:1: 7:2 ++ } ++ ++ bb1 (cleanup): { ++ resume; // scope 0 at $DIR/derefer_test.rs:2:1: 7:2 } } diff --git a/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff b/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff index b8e5a0c328f4d..79734a45dc476 100644 --- a/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff +++ b/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff @@ -58,24 +58,24 @@ StorageLive(_8); // scope 4 at $DIR/derefer_test_multiple.rs:7:9: 7:10 - _8 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + StorageLive(_10); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 -+ _10 = move (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _10 = virt (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + StorageLive(_11); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 -+ _11 = move ((*_10).1: &mut (i32, &mut (i32, i32))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _11 = virt ((*_10).1: &mut (i32, &mut (i32, i32))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + StorageDead(_10); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + StorageLive(_12); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 -+ _12 = move ((*_11).1: &mut (i32, i32)); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _12 = virt ((*_11).1: &mut (i32, i32)); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + StorageDead(_11); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + _8 = &mut ((*_12).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 + StorageDead(_12); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 StorageLive(_9); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 - _9 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + StorageLive(_13); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 -+ _13 = move (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _13 = virt (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + StorageLive(_14); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 -+ _14 = move ((*_13).1: &mut (i32, &mut (i32, i32))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _14 = virt ((*_13).1: &mut (i32, &mut (i32, i32))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + StorageDead(_13); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + StorageLive(_15); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 -+ _15 = move ((*_14).1: &mut (i32, i32)); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _15 = virt ((*_14).1: &mut (i32, i32)); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + StorageDead(_14); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + _9 = &mut ((*_15).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + StorageDead(_15); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2 @@ -87,10 +87,10 @@ StorageDead(_2); // scope 1 at $DIR/derefer_test_multiple.rs:9:1: 9:2 StorageDead(_1); // scope 0 at $DIR/derefer_test_multiple.rs:9:1: 9:2 return; // scope 0 at $DIR/derefer_test_multiple.rs:9:2: 9:2 - } - - bb1 (cleanup): { - resume; // scope 0 at $DIR/derefer_test_multiple.rs:2:1: 9:2 ++ } ++ ++ bb1 (cleanup): { ++ resume; // scope 0 at $DIR/derefer_test_multiple.rs:2:1: 9:2 } } diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff index 67ce0c2aabb1c..9cbc5a4233e93 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff @@ -93,7 +93,7 @@ - StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _34 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _34 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -101,7 +101,7 @@ bb1: { StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _35 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _35 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _7 = discriminant((*_35)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -123,7 +123,7 @@ bb3: { StorageLive(_36); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _36 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _36 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _8 = discriminant((*_36)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_36); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -131,7 +131,7 @@ bb4: { StorageLive(_37); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _37 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _37 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _9 = discriminant((*_37)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_37); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -139,7 +139,7 @@ bb5: { StorageLive(_38); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _38 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _38 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _10 = discriminant((*_38)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_38); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -149,14 +149,14 @@ - StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 StorageLive(_39); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 - _39 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + _39 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 - _12 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + _15 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 StorageDead(_39); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 - StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 StorageLive(_40); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 - _40 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + _40 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 - _13 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + _16 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 StorageDead(_40); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 @@ -195,14 +195,14 @@ - StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 StorageLive(_41); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - _41 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + _41 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - _17 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + _20 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 StorageDead(_41); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 StorageLive(_42); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - _42 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + _42 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - _18 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + _21 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 StorageDead(_42); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 @@ -241,14 +241,14 @@ - StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 StorageLive(_43); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 - _43 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + _43 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 - _22 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + _25 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 StorageDead(_43); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 - StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 StorageLive(_44); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 - _44 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + _44 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 - _23 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + _26 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 StorageDead(_44); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 @@ -287,14 +287,14 @@ - StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 StorageLive(_45); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - _45 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + _45 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - _27 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + _30 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 StorageDead(_45); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 StorageLive(_46); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - _46 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + _46 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - _28 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + _31 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 StorageDead(_46); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index c2b00f915a4eb..e52d2865179e5 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -79,7 +79,7 @@ StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _34 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _34 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _11 = discriminant((*_34)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -87,7 +87,7 @@ bb1: { StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _35 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _35 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _7 = discriminant((*_35)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -107,7 +107,7 @@ bb3: { StorageLive(_36); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _36 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _36 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _8 = discriminant((*_36)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_36); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -115,7 +115,7 @@ bb4: { StorageLive(_37); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _37 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _37 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _9 = discriminant((*_37)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_37); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -123,7 +123,7 @@ bb5: { StorageLive(_38); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 - _38 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 + _38 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 _10 = discriminant((*_38)); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 StorageDead(_38); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -132,12 +132,12 @@ bb6: { StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 StorageLive(_39); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 - _39 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 + _39 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 _12 = (((*_39) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:14: 22:17 StorageDead(_39); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 StorageLive(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 StorageLive(_40); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 - _40 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 + _40 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 _13 = (((*_40) as Vw).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:24: 22:29 StorageDead(_40); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 StorageLive(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:38: 22:49 @@ -160,12 +160,12 @@ bb7: { StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 StorageLive(_41); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - _41 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 + _41 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 _17 = (((*_41) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 StorageDead(_41); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 StorageLive(_42); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 - _42 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 + _42 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 _18 = (((*_42) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 StorageDead(_42); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 StorageLive(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:38: 23:49 @@ -188,12 +188,12 @@ bb8: { StorageLive(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 StorageLive(_43); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 - _43 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 + _43 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 _22 = (((*_43) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19 StorageDead(_43); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 StorageLive(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 StorageLive(_44); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 - _44 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 + _44 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 _23 = (((*_44) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33 StorageDead(_44); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 StorageLive(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:44: 24:55 @@ -216,12 +216,12 @@ bb9: { StorageLive(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 StorageLive(_45); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 - _45 = move (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 + _45 = virt (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 _27 = (((*_45) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19 StorageDead(_45); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 StorageLive(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 StorageLive(_46); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 - _46 = move (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 + _46 = virt (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 _28 = (((*_46) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33 StorageDead(_46); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 StorageLive(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:44: 25:55 diff --git a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff index 982dd7a27bc6b..e40ef981a4e8c 100644 --- a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff @@ -17,7 +17,7 @@ bb1: { StorageLive(_4); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31 - _4 = move (((*_1) as Some).0: &E); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31 + _4 = virt (((*_1) as Some).0: &E); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31 _2 = discriminant((*_4)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31 StorageDead(_4); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31 switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31 diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index c6b49b66dc5c0..80d8d3b1c7b96 100644 --- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -46,12 +46,12 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _9 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 StorageLive(_10); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 StorageLive(_12); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 - _12 = move ((*_6).0: &i32); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 + _12 = virt ((*_6).0: &i32); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 _10 = (*_12); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 StorageDead(_12); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 StorageLive(_11); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 StorageLive(_13); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 - _13 = move ((*_6).1: &T); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 + _13 = virt ((*_6).1: &T); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 _11 = (*_13); // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23 StorageDead(_13); // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24 Deinit(_0); // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24 diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 3e1c4a4670143..51c2688da4709 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -77,7 +77,7 @@ + StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_12); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_13); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 -+ _13 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 ++ _13 = virt (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + _12 = discriminant((*_13)); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + StorageDead(_13); // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 + switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:41 @@ -125,7 +125,7 @@ + ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + discriminant(_1) = 0; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + StorageLive(_14); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 -+ _14 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 ++ _14 = virt (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + discriminant((*_14)) = 3; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + StorageDead(_14); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39 + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39 @@ -139,7 +139,7 @@ + ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 + discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 + StorageLive(_15); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 -+ _15 = move (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 ++ _15 = virt (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41]); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 + discriminant((*_15)) = 1; // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 + StorageDead(_15); // scope 6 at $DIR/inline-generator.rs:15:41: 15:41 + goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41 diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 11a205eb41580..a0b23b43ef467 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -22,7 +22,7 @@ fn b(_1: &mut Box) -> &mut T { StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_7); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _7 = move (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _7 = virt (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _6 = &mut (*_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index b04a91d7c9590..91acf2d2c5c4e 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -16,7 +16,7 @@ fn d(_1: &Box) -> &T { StorageLive(_3); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 _3 = &(*_1); // scope 0 at $DIR/issue-58867-inline-as-ref-as-mut.rs:18:5: 18:15 StorageLive(_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _4 = move (*_3); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _4 = virt (*_3); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _5 = (((_4.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _2 = &(*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 498dcbb89006d..53fa2ccdcc138 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -124,6 +124,7 @@ fn check_rvalue<'tcx>( Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { check_place(tcx, *place, span, body) }, + Rvalue::VirtualRef(place) => check_place(tcx, *place, span, body), Rvalue::Repeat(operand, _) | Rvalue::Use(operand) | Rvalue::Cast( From cc4f804829ae56753acd2ef9c0f4bb741f5b3bae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 20 Jun 2022 16:28:52 +0200 Subject: [PATCH 12/25] Move help popup into a pocket menu as well --- src/librustdoc/html/static/css/rustdoc.css | 74 ++++---- src/librustdoc/html/static/css/settings.css | 21 --- src/librustdoc/html/static/css/themes/ayu.css | 9 +- .../html/static/css/themes/dark.css | 9 +- .../html/static/css/themes/light.css | 9 +- src/librustdoc/html/static/js/main.js | 176 +++++++++++------- src/librustdoc/html/static/js/settings.js | 30 +-- src/librustdoc/html/templates/page.html | 4 +- 8 files changed, 173 insertions(+), 159 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d0229bdb5f23c..77062770c189d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -979,42 +979,51 @@ table, font-weight: normal; } -body.blur > :not(#help) { - filter: blur(8px); - -webkit-filter: blur(8px); - opacity: .7; +.popover { + font-size: 1rem; + position: absolute; + right: 0; + z-index: 2; + display: block; + margin-top: 7px; + border-radius: 3px; + border: 1px solid; + font-size: 1rem; } -#help { - width: 100%; - height: 100vh; - position: fixed; - top: 0; - left: 0; - display: flex; - justify-content: center; - align-items: center; +/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */ +.popover::before { + content: ''; + position: absolute; + right: 11px; + border: solid; + border-width: 1px 1px 0 0; + display: inline-block; + padding: 4px; + transform: rotate(-45deg); + top: -5px; } -#help > div { - flex: 0 0 auto; - box-shadow: 0 0 6px rgba(0,0,0,.2); - width: 550px; - height: auto; - border: 1px solid; + +#help-button .popover { + max-width: 600px; } -#help dt { + +#help-button .popover::before { + right: 48px; +} + +#help-button dt { float: left; clear: left; display: block; margin-right: 0.5rem; } -#help span.top, #help span.bottom { +#help-button span.top, #help-button span.bottom { text-align: center; display: block; font-size: 1.125rem; - } -#help span.top { +#help-button span.top { text-align: center; display: block; margin: 10px 0; @@ -1022,17 +1031,17 @@ body.blur > :not(#help) { padding-bottom: 4px; margin-bottom: 6px; } -#help span.bottom { +#help-button span.bottom { clear: both; border-top: 1px solid; } -#help dd { margin: 5px 35px; } -#help .infos { padding-left: 0; } -#help h1, #help h2 { margin-top: 0; } -#help > div div { +.side-by-side { + text-align: initial; +} +.side-by-side > div { width: 50%; float: left; - padding: 0 20px 20px 17px;; + padding: 0 20px 20px 17px; } .item-info .stab { @@ -1387,7 +1396,7 @@ pre.rust { #copy-path { height: 34px; } -#settings-menu > a, #help-button, #copy-path { +#settings-menu > a, #help-button > button, #copy-path { padding: 5px; width: 33px; border: 1px solid; @@ -1397,9 +1406,8 @@ pre.rust { #settings-menu { padding: 0; } -#settings-menu > a { +#settings-menu > a, #help-button > button { padding: 5px; - width: 100%; height: 100%; display: block; } @@ -1416,7 +1424,7 @@ pre.rust { animation: rotating 2s linear infinite; } -#help-button { +#help-button > button { font-family: "Fira Sans", Arial, sans-serif; text-align: center; /* Rare exception to specifying font sizes in rem. Since this is acting diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 1cd8e39e03648..e531e6ce6bbde 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -86,27 +86,6 @@ input:checked + .slider:before { display: block; } -div#settings { - position: absolute; - right: 0; - z-index: 1; - display: block; - margin-top: 7px; - border-radius: 3px; - border: 1px solid; -} #settings .setting-line { margin: 1.2em 0.6em; } -/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */ -div#settings::before { - content: ''; - position: absolute; - right: 11px; - border: solid; - border-width: 1px 1px 0 0; - display: inline-block; - padding: 4px; - transform: rotate(-45deg); - top: -5px; -} diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 8e0521d9ad6a1..d27294657192c 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -5,7 +5,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) /* General structure and fonts */ -body, #settings-menu #settings, #settings-menu #settings::before { +body, .popover, .popover::before { background-color: #0f1419; color: #c5c5c5; } @@ -567,7 +567,7 @@ kbd { box-shadow: inset 0 -1px 0 #5c6773; } -#settings-menu > a, #help-button { +#settings-menu > a, #help-button > button { border-color: #5c6773; background-color: #0f1419; color: #fff; @@ -577,7 +577,8 @@ kbd { filter: invert(100); } -#settings-menu #settings, #settings-menu #settings::before { +.popover, .popover::before, +#help-button span.top, #help-button span.bottom { border-color: #5c6773; } @@ -592,7 +593,7 @@ kbd { } #settings-menu > a:hover, #settings-menu > a:focus, -#help-button:hover, #help-button:focus { +#help-button > button:hover, #help-button > button:focus { border-color: #e0e0e0; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 071ad006ed350..48079ea2f3041 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -1,4 +1,4 @@ -body, #settings-menu #settings, #settings-menu #settings::before { +body, .popover, .popover::before { background-color: #353535; color: #ddd; } @@ -442,18 +442,19 @@ kbd { box-shadow: inset 0 -1px 0 #c6cbd1; } -#settings-menu > a, #help-button { +#settings-menu > a, #help-button > button { border-color: #e0e0e0; background: #f0f0f0; color: #000; } #settings-menu > a:hover, #settings-menu > a:focus, -#help-button:hover, #help-button:focus { +#help-button > button:hover, #help-button > button:focus { border-color: #ffb900; } -#settings-menu #settings, #settings-menu #settings::before { +.popover, .popover::before, +#help-button span.top, #help-button span.bottom { border-color: #d2d2d2; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5c3789bf4630a..f4016be967963 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -1,6 +1,6 @@ /* General structure and fonts */ -body, #settings-menu #settings, #settings-menu #settings::before { +body, .popover, .popover::before { background-color: white; color: black; } @@ -427,17 +427,18 @@ kbd { box-shadow: inset 0 -1px 0 #c6cbd1; } -#settings-menu > a, #help-button { +#settings-menu > a, #help-button > button { border-color: #e0e0e0; background-color: #fff; } #settings-menu > a:hover, #settings-menu > a:focus, -#help-button:hover, #help-button:focus { +#help-button > button:hover, #help-button > button:focus { border-color: #717171; } -#settings-menu #settings, #settings-menu #settings::before { +.popover, .popover::before, +#help-button span.top, #help-button span.bottom { border-color: #DDDDDD; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index b320db9104612..1ea645d3e6594 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -63,6 +63,24 @@ function showMain() { removeClass(document.getElementById(MAIN_ID), "hidden"); } +function elemIsInParent(elem, parent) { + while (elem && elem !== document.body) { + if (elem === parent) { + return true; + } + elem = elem.parentElement; + } + return false; +} + +function blurHandler(event, parentElem, hideCallback) { + if (!elemIsInParent(document.activeElement, parentElem) && + !elemIsInParent(event.relatedTarget, parentElem) + ) { + hideCallback(); + } +} + (function() { window.rootPath = getVar("root-path"); window.currentCrate = getVar("current-crate"); @@ -104,11 +122,16 @@ const MAIN_ID = "main-content"; const SETTINGS_BUTTON_ID = "settings-menu"; const ALTERNATIVE_DISPLAY_ID = "alternative-display"; const NOT_DISPLAYED_ID = "not-displayed"; +const HELP_BUTTON_ID = "help-button"; function getSettingsButton() { return document.getElementById(SETTINGS_BUTTON_ID); } +function getHelpButton() { + return document.getElementById(HELP_BUTTON_ID); +} + // Returns the current URL without any query parameter or hash. function getNakedUrl() { return window.location.href.split("?")[0].split("#")[0]; @@ -381,55 +404,17 @@ function loadCss(cssFileName) { openParentDetails(document.getElementById(id)); } - function getHelpElement(build) { - if (build) { - buildHelperPopup(); - } - return document.getElementById("help"); - } - - /** - * Show the help popup. - * - * @param {boolean} display - Whether to show or hide the popup - * @param {Event} ev - The event that triggered this call - * @param {Element} [help] - The help element if it already exists - */ - function displayHelp(display, ev, help) { - if (display) { - help = help ? help : getHelpElement(true); - if (hasClass(help, "hidden")) { - ev.preventDefault(); - removeClass(help, "hidden"); - addClass(document.body, "blur"); - } - } else { - // No need to build the help popup if we want to hide it in case it hasn't been - // built yet... - help = help ? help : getHelpElement(false); - if (help && !hasClass(help, "hidden")) { - ev.preventDefault(); - addClass(help, "hidden"); - removeClass(document.body, "blur"); - } - } - } - function handleEscape(ev) { searchState.clearInputTimeout(); - const help = getHelpElement(false); - if (help && !hasClass(help, "hidden")) { - displayHelp(false, ev, help); - } else { - switchDisplayedElement(null); - if (browserSupportsHistoryApi()) { - history.replaceState(null, window.currentCrate + " - Rust", - getNakedUrl() + window.location.hash); - } - ev.preventDefault(); + switchDisplayedElement(null); + if (browserSupportsHistoryApi()) { + history.replaceState(null, window.currentCrate + " - Rust", + getNakedUrl() + window.location.hash); } + ev.preventDefault(); searchState.defocus(); window.hideSettings(); + hideHelp(); } const disableShortcuts = getSettingValue("disable-shortcuts") === "true"; @@ -453,7 +438,6 @@ function loadCss(cssFileName) { case "s": case "S": - displayHelp(false, ev); ev.preventDefault(); searchState.focus(); break; @@ -465,7 +449,7 @@ function loadCss(cssFileName) { break; case "?": - displayHelp(true, ev); + showHelp(); break; default: @@ -796,9 +780,6 @@ function loadCss(cssFileName) { elem.addEventListener("click", f); } } - handleClick("help-button", ev => { - displayHelp(true, ev); - }); handleClick(MAIN_ID, () => { hideSidebar(); }); @@ -842,24 +823,16 @@ function loadCss(cssFileName) { }); } - let buildHelperPopup = () => { - const popup = document.createElement("aside"); - addClass(popup, "hidden"); - popup.id = "help"; - - popup.addEventListener("click", ev => { - if (ev.target === popup) { - // Clicked the blurred zone outside the help popup; dismiss help. - displayHelp(false, ev); - } - }); + function helpBlurHandler(event) { + blurHandler(event, getHelpButton(), hideHelp); + } + function buildHelpMenu() { const book_info = document.createElement("span"); book_info.className = "top"; book_info.innerHTML = "You can find more information in \ the rustdoc book."; - const container = document.createElement("div"); const shortcuts = [ ["?", "Show this help dialog"], ["S", "Focus the search field"], @@ -895,23 +868,86 @@ function loadCss(cssFileName) { addClass(div_infos, "infos"); div_infos.innerHTML = "

Search Tricks

" + infos; - container.appendChild(book_info); - container.appendChild(div_shortcuts); - container.appendChild(div_infos); - const rustdoc_version = document.createElement("span"); rustdoc_version.className = "bottom"; const rustdoc_version_code = document.createElement("code"); rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version"); rustdoc_version.appendChild(rustdoc_version_code); + const container = document.createElement("div"); + container.className = "popover"; + container.style.display = "none"; + + const side_by_side = document.createElement("div"); + side_by_side.className = "side-by-side"; + side_by_side.appendChild(div_shortcuts); + side_by_side.appendChild(div_infos); + + container.appendChild(book_info); + container.appendChild(side_by_side); container.appendChild(rustdoc_version); - popup.appendChild(container); - insertAfter(popup, document.querySelector("main")); - // So that it's only built once and then it'll do nothing when called! - buildHelperPopup = () => {}; - }; + const help_button = getHelpButton(); + help_button.appendChild(container); + + container.onblur = helpBlurHandler; + container.onclick = event => { + event.preventDefault(); + }; + help_button.onblur = helpBlurHandler; + help_button.children[0].onblur = helpBlurHandler; + + return container; + } + + /** + * Returns the help menu element (not the button). + * + * @param {boolean} buildNeeded - If this argument is `false`, the help menu element won't be + * built if it doesn't exist. + * + * @return {HTMLElement} + */ + function getHelpMenu(buildNeeded) { + let menu = getHelpButton().querySelector(".popover"); + if (!menu && buildNeeded) { + menu = buildHelpMenu(); + } + return menu; + } + + /** + * Show the help popup menu. + */ + function showHelp() { + const menu = getHelpMenu(true); + if (menu.style.display === "none") { + menu.style.display = ""; + } + } + + /** + * Hide the help popup menu. + */ + function hideHelp() { + const menu = getHelpMenu(false); + if (menu && menu.style.display !== "none") { + menu.style.display = "none"; + } + } + + document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => { + const target = event.target; + if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) { + return; + } + const menu = getHelpMenu(true); + if (menu.style.display !== "none") { + hideHelp(); + } else { + showHelp(); + } + }); setMobileTopbar(); addSidebarItems(); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 41bf0ec895580..2445773a96542 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -1,6 +1,6 @@ // Local js definitions: /* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */ -/* global addClass, removeClass, onEach, onEachLazy */ +/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */ /* global MAIN_ID, getVar, getSettingsButton */ "use strict"; @@ -209,6 +209,7 @@ const innerHTML = `
${buildSettingsPageSections(settings)}
`; const el = document.createElement(elementKind); el.id = "settings"; + el.className = "popover"; el.innerHTML = innerHTML; if (isSettingsPage) { @@ -226,23 +227,8 @@ settingsMenu.style.display = ""; } - function elemIsInParent(elem, parent) { - while (elem && elem !== document.body) { - if (elem === parent) { - return true; - } - elem = elem.parentElement; - } - return false; - } - - function blurHandler(event) { - const settingsButton = getSettingsButton(); - if (!elemIsInParent(document.activeElement, settingsButton) && - !elemIsInParent(event.relatedTarget, settingsButton) - ) { - window.hideSettings(); - } + function settingsBlurHandler(event) { + blurHandler(event, getSettingsButton(), window.hideSettings); } if (isSettingsPage) { @@ -268,12 +254,12 @@ displaySettings(); } }; - settingsButton.onblur = blurHandler; - settingsButton.querySelector("a").onblur = blurHandler; + settingsButton.onblur = settingsBlurHandler; + settingsButton.querySelector("a").onblur = settingsBlurHandler; onEachLazy(settingsMenu.querySelectorAll("input"), el => { - el.onblur = blurHandler; + el.onblur = settingsBlurHandler; }); - settingsMenu.onblur = blurHandler; + settingsMenu.onblur = settingsBlurHandler; } // We now wait a bit for the web browser to end re-computing the DOM... diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index c4999e2c74fce..dfb3e4e6a2ccd 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -119,7 +119,9 @@

spellcheck="false" {# -#} placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#} type="search"> {#- -#} - {#- -#} +
{#- -#} + {#- -#} +
{#- -#}
{#- -#} Change settings Date: Mon, 20 Jun 2022 16:29:16 +0200 Subject: [PATCH 13/25] Add/update GUI tests for help pocket menu --- src/test/rustdoc-gui/escape-key.goml | 12 ----- src/test/rustdoc-gui/pocket-menu.goml | 72 +++++++++++++++++++++++++++ src/test/rustdoc-gui/shortcuts.goml | 5 +- 3 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 src/test/rustdoc-gui/pocket-menu.goml diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml index 8713bf65c8432..d083b0ae0c931 100644 --- a/src/test/rustdoc-gui/escape-key.goml +++ b/src/test/rustdoc-gui/escape-key.goml @@ -21,17 +21,6 @@ wait-for: "#alternative-display #search" assert-attribute: ("#main-content", {"class": "content hidden"}) assert-document-property: ({"URL": "index.html?search=test"}, ENDS_WITH) -// Now let's check that when the help popup is displayed and we press Escape, it doesn't -// hide the search results too. -click: "#help-button" -assert-document-property: ({"URL": "index.html?search=test"}, [ENDS_WITH]) -assert-attribute: ("#help", {"class": ""}) -press-key: "Escape" -wait-for: "#alternative-display #search" -assert-attribute: ("#help", {"class": "hidden"}) -assert-attribute: ("#main-content", {"class": "content hidden"}) -assert-document-property: ({"URL": "index.html?search=test"}, [ENDS_WITH]) - // Check that Escape hides the search results when a search result is focused. focus: ".search-input" assert: ".search-input:focus" @@ -39,7 +28,6 @@ press-key: "ArrowDown" assert-false: ".search-input:focus" assert: "#results a:focus" press-key: "Escape" -assert-attribute: ("#help", {"class": "hidden"}) wait-for: "#not-displayed #search" assert-false: "#alternative-display #search" assert-attribute: ("#main-content", {"class": "content"}) diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml new file mode 100644 index 0000000000000..ba2986e969a35 --- /dev/null +++ b/src/test/rustdoc-gui/pocket-menu.goml @@ -0,0 +1,72 @@ +// This test ensures that the "pocket menus" are working as expected. +goto: file://|DOC_PATH|/test_docs/index.html +// First we check that the help menu doesn't exist yet. +assert-false: "#help-button .popover" +// Then we display the help menu. +click: "#help-button" +assert: "#help-button .popover" +assert-css: ("#help-button .popover", {"display": "block"}) + +// Now we click somewhere else on the page to ensure it is handling the blur event +// correctly. +click: ".sidebar" +assert-css: ("#help-button .popover", {"display": "none"}) + +// Now we will check that we cannot have two "pocket menus" displayed at the same time. +click: "#help-button" +assert-css: ("#help-button .popover", {"display": "block"}) +click: "#settings-menu" +assert-css: ("#help-button .popover", {"display": "none"}) +assert-css: ("#settings-menu .popover", {"display": "block"}) + +// Now the other way. +click: "#help-button" +assert-css: ("#help-button .popover", {"display": "block"}) +assert-css: ("#settings-menu .popover", {"display": "none"}) + +// We check the borders color now: + +// Ayu theme +local-storage: { + "rustdoc-theme": "ayu", + "rustdoc-use-system-theme": "false", +} +reload: + +click: "#help-button" +assert-css: ( + "#help-button .popover", + {"display": "block", "border-color": "rgb(92, 103, 115)"}, +) +compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) +compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) + +// Dark theme +local-storage: { + "rustdoc-theme": "dark", + "rustdoc-use-system-theme": "false", +} +reload: + +click: "#help-button" +assert-css: ( + "#help-button .popover", + {"display": "block", "border-color": "rgb(210, 210, 210)"}, +) +compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) +compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) + +// Light theme +local-storage: { + "rustdoc-theme": "light", + "rustdoc-use-system-theme": "false", +} +reload: + +click: "#help-button" +assert-css: ( + "#help-button .popover", + {"display": "block", "border-color": "rgb(221, 221, 221)"}, +) +compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"]) +compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"]) diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml index 37a7c1662949d..1f20a0eaa9982 100644 --- a/src/test/rustdoc-gui/shortcuts.goml +++ b/src/test/rustdoc-gui/shortcuts.goml @@ -8,7 +8,6 @@ press-key: "Escape" assert-false: "input.search-input:focus" // We now check for the help popup. press-key: "?" -assert-css: ("#help", {"display": "flex"}) -assert-false: "#help.hidden" +assert-css: ("#help-button .popover", {"display": "block"}) press-key: "Escape" -assert-css: ("#help.hidden", {"display": "none"}) +assert-css: ("#help-button .popover", {"display": "none"}) From e4b2b41290f6b49441b5b9c8e013458bc23caeeb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jun 2022 20:49:26 +0200 Subject: [PATCH 14/25] Merge all popover hide functions into one --- src/librustdoc/html/static/js/main.js | 33 +++++++++-------------- src/librustdoc/html/static/js/settings.js | 12 ++++----- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 1ea645d3e6594..70dbfd4442540 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -137,10 +137,6 @@ function getNakedUrl() { return window.location.href.split("?")[0].split("#")[0]; } -window.hideSettings = () => { - // Does nothing by default. -}; - /** * This function inserts `newNode` after `referenceNode`. It doesn't work if `referenceNode` * doesn't have a parent node. @@ -413,8 +409,7 @@ function loadCss(cssFileName) { } ev.preventDefault(); searchState.defocus(); - window.hideSettings(); - hideHelp(); + window.hidePopoverMenus(); } const disableShortcuts = getSettingValue("disable-shortcuts") === "true"; @@ -824,7 +819,7 @@ function loadCss(cssFileName) { } function helpBlurHandler(event) { - blurHandler(event, getHelpButton(), hideHelp); + blurHandler(event, getHelpButton(), window.hidePopoverMenus); } function buildHelpMenu() { @@ -900,6 +895,15 @@ function loadCss(cssFileName) { return container; } + /** + * Hide all the popover menus. + */ + window.hidePopoverMenus = function() { + onEachLazy(document.querySelectorAll(".search-container .popover"), elem => { + elem.style.display = "none"; + }); + }; + /** * Returns the help menu element (not the button). * @@ -926,25 +930,14 @@ function loadCss(cssFileName) { } } - /** - * Hide the help popup menu. - */ - function hideHelp() { - const menu = getHelpMenu(false); - if (menu && menu.style.display !== "none") { - menu.style.display = "none"; - } - } - document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => { const target = event.target; if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) { return; } const menu = getHelpMenu(true); - if (menu.style.display !== "none") { - hideHelp(); - } else { + const shouldShowHelp = menu.style.display === "none"; + if (shouldShowHelp) { showHelp(); } }); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 2445773a96542..797b931afc643 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -228,7 +228,7 @@ } function settingsBlurHandler(event) { - blurHandler(event, getSettingsButton(), window.hideSettings); + blurHandler(event, getSettingsButton(), window.hidePopoverMenus); } if (isSettingsPage) { @@ -240,17 +240,15 @@ // We replace the existing "onclick" callback. const settingsButton = getSettingsButton(); const settingsMenu = document.getElementById("settings"); - window.hideSettings = function() { - settingsMenu.style.display = "none"; - }; settingsButton.onclick = function(event) { if (elemIsInParent(event.target, settingsMenu)) { return; } event.preventDefault(); - if (settingsMenu.style.display !== "none") { - window.hideSettings(); - } else { + const shouldDisplaySettings = settingsMenu.style.display === "none"; + + window.hidePopoverMenus(); + if (shouldDisplaySettings) { displaySettings(); } }; From 23d325ed0d27f2b31c5442ce5d6ff26195c72025 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Thu, 23 Jun 2022 12:02:07 +0200 Subject: [PATCH 15/25] Update FIXME comment Co-authored-by: Wesley Wiser --- src/test/debuginfo/no_mangle-info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/debuginfo/no_mangle-info.rs b/src/test/debuginfo/no_mangle-info.rs index 0b058b0827e3a..3a261e197aa5d 100644 --- a/src/test/debuginfo/no_mangle-info.rs +++ b/src/test/debuginfo/no_mangle-info.rs @@ -27,7 +27,7 @@ #[no_mangle] pub static TEST: u64 = 0xdeadbeef; -// FIXME: uncommenting this namespace breaks the test, and we're not sure why +// FIXME(rylev, wesleywiser): uncommenting this item breaks the test, and we're not sure why // pub static OTHER_TEST: u64 = 43; pub mod namespace { pub static OTHER_TEST: u64 = 42; From 4c4fb7152bf73dcbdd0066e65ec3d034d42589c5 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 23 Jun 2022 17:34:34 +0200 Subject: [PATCH 16/25] 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/25] 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/25] 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/25] 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/25] 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/25] 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 20cea3ebb468df74447ed3aa5e646f741208bea8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Jun 2022 21:27:15 -0700 Subject: [PATCH 22/25] Fix printing impl trait under binders --- compiler/rustc_middle/src/ty/print/pretty.rs | 246 ++++++++++-------- src/test/ui/impl-trait/printing-binder.rs | 14 + src/test/ui/impl-trait/printing-binder.stderr | 31 +++ 3 files changed, 178 insertions(+), 113 deletions(-) create mode 100644 src/test/ui/impl-trait/printing-binder.rs create mode 100644 src/test/ui/impl-trait/printing-binder.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 200253d575599..d0f53f8f74b26 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -226,7 +226,7 @@ pub trait PrettyPrinter<'tcx>: value.as_ref().skip_binder().print(self) } - fn wrap_binder Result>( + fn wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: F, @@ -773,18 +773,18 @@ pub trait PrettyPrinter<'tcx>: def_id: DefId, substs: &'tcx ty::List>, ) -> Result { - define_scoped_cx!(self); + let tcx = self.tcx(); // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx().bound_explicit_item_bounds(def_id); + let bounds = tcx.bound_explicit_item_bounds(def_id); let mut traits = FxIndexMap::default(); let mut fn_traits = FxIndexMap::default(); let mut is_sized = false; for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { - let predicate = predicate.subst(self.tcx(), substs); + let predicate = predicate.subst(tcx, substs); let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { @@ -792,7 +792,7 @@ pub trait PrettyPrinter<'tcx>: let trait_ref = bound_predicate.rebind(pred.trait_ref); // Don't print + Sized, but rather + ?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { + if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() { is_sized = true; continue; } @@ -801,7 +801,7 @@ pub trait PrettyPrinter<'tcx>: } ty::PredicateKind::Projection(pred) => { let proj_ref = bound_predicate.rebind(pred); - let trait_ref = proj_ref.required_poly_trait_ref(self.tcx()); + let trait_ref = proj_ref.required_poly_trait_ref(tcx); // Projection type entry -- the def-id for naming, and the ty. let proj_ty = (proj_ref.projection_def_id(), proj_ref.term()); @@ -817,148 +817,168 @@ pub trait PrettyPrinter<'tcx>: } } + { + define_scoped_cx!(self); + p!("impl "); + } + let mut first = true; // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized; - p!("impl"); - for (fn_once_trait_ref, entry) in fn_traits { - // Get the (single) generic ty (the args) of this FnOnce trait ref. - let generics = self.tcx().generics_of(fn_once_trait_ref.def_id()); - let args = - generics.own_substs_no_defaults(self.tcx(), fn_once_trait_ref.skip_binder().substs); - - match (entry.return_ty, args[0].expect_ty()) { - // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded - // a return type. - (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { - let name = if entry.fn_trait_ref.is_some() { - "Fn" - } else if entry.fn_mut_trait_ref.is_some() { - "FnMut" - } else { - "FnOnce" - }; + { + define_scoped_cx!(self); + p!( + write("{}", if first { "" } else { " + " }), + write("{}", if paren_needed { "(" } else { "" }) + ); + } + + self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut self_| { + // Get the (single) generic ty (the args) of this FnOnce trait ref. + let generics = tcx.generics_of(trait_ref.def_id); + let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); + + match (entry.return_ty, args[0].expect_ty()) { + // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded + // a return type. + (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { + let name = if entry.fn_trait_ref.is_some() { + "Fn" + } else if entry.fn_mut_trait_ref.is_some() { + "FnMut" + } else { + "FnOnce" + }; - p!( - write("{}", if first { " " } else { " + " }), - write("{}{}(", if paren_needed { "(" } else { "" }, name) - ); + define_scoped_cx!(self_); + p!(write("{}(", name)); - for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { - if idx > 0 { - p!(", "); + for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { + if idx > 0 { + p!(", "); + } + p!(print(ty)); } - p!(print(ty)); - } - p!(")"); - if let Term::Ty(ty) = return_ty.skip_binder() { - if !ty.is_unit() { - p!(" -> ", print(return_ty)); + p!(")"); + if let Term::Ty(ty) = return_ty.skip_binder() { + if !ty.is_unit() { + p!(" -> ", print(return_ty)); + } } - } - p!(write("{}", if paren_needed { ")" } else { "" })); + p!(write("{}", if paren_needed { ")" } else { "" })); - first = false; - } - // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the - // trait_refs we collected in the OpaqueFnEntry as normal trait refs. - _ => { - if entry.has_fn_once { - traits.entry(fn_once_trait_ref).or_default().extend( - // Group the return ty with its def id, if we had one. - entry - .return_ty - .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)), - ); - } - if let Some(trait_ref) = entry.fn_mut_trait_ref { - traits.entry(trait_ref).or_default(); + first = false; } - if let Some(trait_ref) = entry.fn_trait_ref { - traits.entry(trait_ref).or_default(); + // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the + // trait_refs we collected in the OpaqueFnEntry as normal trait refs. + _ => { + if entry.has_fn_once { + traits.entry(fn_once_trait_ref).or_default().extend( + // Group the return ty with its def id, if we had one. + entry + .return_ty + .map(|ty| (tcx.lang_items().fn_once_output().unwrap(), ty)), + ); + } + if let Some(trait_ref) = entry.fn_mut_trait_ref { + traits.entry(trait_ref).or_default(); + } + if let Some(trait_ref) = entry.fn_trait_ref { + traits.entry(trait_ref).or_default(); + } } } - } + + Ok(self_) + })?; } // Print the rest of the trait types (that aren't Fn* family of traits) for (trait_ref, assoc_items) in traits { - p!( - write("{}", if first { " " } else { " + " }), - print(trait_ref.skip_binder().print_only_trait_name()) - ); + { + define_scoped_cx!(self); + p!(write("{}", if first { "" } else { " + " })); + } - let generics = self.tcx().generics_of(trait_ref.def_id()); - let args = generics.own_substs_no_defaults(self.tcx(), trait_ref.skip_binder().substs); + self = self.wrap_binder(&trait_ref, |trait_ref, mut self_| { + define_scoped_cx!(self_); + p!(print(trait_ref.print_only_trait_name())); - if !args.is_empty() || !assoc_items.is_empty() { - let mut first = true; + let generics = tcx.generics_of(trait_ref.def_id); + let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); - for ty in args { - if first { - p!("<"); - first = false; - } else { - p!(", "); + if !args.is_empty() || !assoc_items.is_empty() { + let mut first = true; + + for ty in args { + if first { + p!("<"); + first = false; + } else { + p!(", "); + } + p!(print(ty)); } - p!(print(trait_ref.rebind(*ty))); - } - for (assoc_item_def_id, term) in assoc_items { - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, - // unless we can find out what generator return type it comes from. - let term = if let Some(ty) = term.skip_binder().ty() - && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind() - && Some(*item_def_id) == self.tcx().lang_items().generator_return() - { - if let ty::Generator(_, substs, _) = substs.type_at(0).kind() { - let return_ty = substs.as_generator().return_ty(); - if !return_ty.is_ty_infer() { - return_ty.into() + for (assoc_item_def_id, term) in assoc_items { + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, + // unless we can find out what generator return type it comes from. + let term = if let Some(ty) = term.skip_binder().ty() + && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind() + && Some(*item_def_id) == tcx.lang_items().generator_return() + { + if let ty::Generator(_, substs, _) = substs.type_at(0).kind() { + let return_ty = substs.as_generator().return_ty(); + if !return_ty.is_ty_infer() { + return_ty.into() + } else { + continue; + } } else { continue; } } else { - continue; - } - } else { - term.skip_binder() - }; + term.skip_binder() + }; - if first { - p!("<"); - first = false; - } else { - p!(", "); - } + if first { + p!("<"); + first = false; + } else { + p!(", "); + } - p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name)); + p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name)); - match term { - Term::Ty(ty) => { - p!(print(ty)) - } - Term::Const(c) => { - p!(print(c)); - } - }; - } + match term { + Term::Ty(ty) => { + p!(print(ty)) + } + Term::Const(c) => { + p!(print(c)); + } + }; + } - if !first { - p!(">"); + if !first { + p!(">"); + } } - } - first = false; + first = false; + Ok(self_) + })?; } + define_scoped_cx!(self); + if !is_sized { - p!(write("{}?Sized", if first { " " } else { " + " })); + p!(write("{}?Sized", if first { "" } else { " + " })); } else if first { - p!(" Sized"); + p!("Sized"); } Ok(self) @@ -1869,7 +1889,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self.pretty_in_binder(value) } - fn wrap_binder Result>( + fn wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: C, @@ -2256,7 +2276,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { Ok(inner) } - pub fn pretty_wrap_binder Result>( + pub fn pretty_wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: C, diff --git a/src/test/ui/impl-trait/printing-binder.rs b/src/test/ui/impl-trait/printing-binder.rs new file mode 100644 index 0000000000000..273b5dcdb0985 --- /dev/null +++ b/src/test/ui/impl-trait/printing-binder.rs @@ -0,0 +1,14 @@ +trait Trait<'a> {} +impl Trait<'_> for T {} +fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {} + +fn whatever2() -> impl for<'c> Fn(&'c ()) { + |_: &()| {} +} + +fn main() { + let x: u32 = whatever(); + //~^ ERROR mismatched types + let x2: u32 = whatever2(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/impl-trait/printing-binder.stderr b/src/test/ui/impl-trait/printing-binder.stderr new file mode 100644 index 0000000000000..5ffec8af10289 --- /dev/null +++ b/src/test/ui/impl-trait/printing-binder.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/printing-binder.rs:10:18 + | +LL | fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {} + | ------------------------------------------ the found opaque type +... +LL | let x: u32 = whatever(); + | --- ^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl for<'a> Trait<'a> + for<'b> Trait<'b>` + +error[E0308]: mismatched types + --> $DIR/printing-binder.rs:12:19 + | +LL | fn whatever2() -> impl for<'c> Fn(&'c ()) { + | ----------------------- the found opaque type +... +LL | let x2: u32 = whatever2(); + | --- ^^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl for<'c> Fn(&'c ())` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From e80ccedbaeeb5b97880d83ea95c79fc1d0dcf418 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Jun 2022 10:21:24 -0700 Subject: [PATCH 23/25] Use write! instead of p! to avoid having to use weird scoping --- compiler/rustc_middle/src/ty/print/pretty.rs | 37 ++++++------------- ...e-70935-complex-spans.drop_tracking.stderr | 2 +- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d0f53f8f74b26..c56909ba18b14 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -817,25 +817,18 @@ pub trait PrettyPrinter<'tcx>: } } - { - define_scoped_cx!(self); - p!("impl "); - } + write!(self, "impl ")?; let mut first = true; // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized; for (fn_once_trait_ref, entry) in fn_traits { - { - define_scoped_cx!(self); - p!( - write("{}", if first { "" } else { " + " }), - write("{}", if paren_needed { "(" } else { "" }) - ); - } + write!(self, "{}", if first { "" } else { " + " })?; + write!(self, "{}", if paren_needed { "(" } else { "" })?; - self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut self_| { + self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut cx| { + define_scoped_cx!(cx); // Get the (single) generic ty (the args) of this FnOnce trait ref. let generics = tcx.generics_of(trait_ref.def_id); let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); @@ -852,7 +845,6 @@ pub trait PrettyPrinter<'tcx>: "FnOnce" }; - define_scoped_cx!(self_); p!(write("{}(", name)); for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { @@ -892,19 +884,16 @@ pub trait PrettyPrinter<'tcx>: } } - Ok(self_) + Ok(cx) })?; } // Print the rest of the trait types (that aren't Fn* family of traits) for (trait_ref, assoc_items) in traits { - { - define_scoped_cx!(self); - p!(write("{}", if first { "" } else { " + " })); - } + write!(self, "{}", if first { "" } else { " + " })?; - self = self.wrap_binder(&trait_ref, |trait_ref, mut self_| { - define_scoped_cx!(self_); + self = self.wrap_binder(&trait_ref, |trait_ref, mut cx| { + define_scoped_cx!(cx); p!(print(trait_ref.print_only_trait_name())); let generics = tcx.generics_of(trait_ref.def_id); @@ -969,16 +958,14 @@ pub trait PrettyPrinter<'tcx>: } first = false; - Ok(self_) + Ok(cx) })?; } - define_scoped_cx!(self); - if !is_sized { - p!(write("{}?Sized", if first { "" } else { " + " })); + write!(self, "{}?Sized", if first { "" } else { " + " })?; } else if first { - p!("Sized"); + write!(self, "Sized")?; } Ok(self) diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 43b7cb8cece36..e9b76b19dc407 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -22,7 +22,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { LL | | LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't0> Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:23:16 | From c06d8f9255caa11a16f2a51d5ce7923642651560 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Jun 2022 20:49:07 -0700 Subject: [PATCH 24/25] Fix trait object reborrow suggestion --- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/traits/error_reporting/mod.rs | 7 +++---- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/select/confirmation.rs | 6 +++--- .../suggest-borrow-to-dyn-object.rs | 16 ++++++++++++++++ .../suggest-borrow-to-dyn-object.stderr | 19 +++++++++++++++++++ 6 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs create mode 100644 src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 5258d37a14c91..67b5e94c99451 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -253,7 +253,7 @@ pub enum ObligationCauseCode<'tcx> { ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>), /// Obligation incurred due to an object cast. - ObjectCastObligation(/* Object type */ Ty<'tcx>), + ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>), /// Obligation incurred due to a coercion. Coercion { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index af0803fbd5414..debb9e8295122 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -484,10 +484,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_label(span, explanation); } - if let ObligationCauseCode::ObjectCastObligation(obj_ty) = obligation.cause.code().peel_derives() && - let Some(self_ty) = trait_predicate.self_ty().no_bound_vars() && + if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() && Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { - self.suggest_borrowing_for_object_cast(&mut err, &obligation, self_ty, *obj_ty); + self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty); } if trait_predicate.is_const_if_const() && obligation.param_env.is_const() { @@ -1560,7 +1559,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { obligation.cause.code().peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ObjectCastObligation(_) + | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index fbe66d7dcdd2b..166c7a4110b6c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2217,7 +2217,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_note(tcx.def_span(item_def_id), &descr); } } - ObligationCauseCode::ObjectCastObligation(object_ty) => { + ObligationCauseCode::ObjectCastObligation(_, object_ty) => { err.note(&format!( "required for the cast to the object type `{}`", self.ty_to_string(object_ty) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 5942bb79d69e8..e1131140c39e8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -813,7 +813,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObjectCastObligation(target), + ObjectCastObligation(source, target), ); let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth( @@ -910,7 +910,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObjectCastObligation(target), + ObjectCastObligation(source, target), ); let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth( @@ -931,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObjectCastObligation(target), + ObjectCastObligation(source, target), ); let predicate_to_obligation = |predicate| { diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs new file mode 100644 index 0000000000000..120fc538307a7 --- /dev/null +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs @@ -0,0 +1,16 @@ +use std::ffi::{OsStr, OsString}; +use std::path::Path; + +fn check(p: &dyn AsRef) { + let m = std::fs::metadata(&p); + println!("{:?}", &m); +} + +fn main() { + let s: OsString = ".".into(); + let s: &OsStr = &s; + check(s); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]` + //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` +} diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr new file mode 100644 index 0000000000000..8961f4275a283 --- /dev/null +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow-to-dyn-object.rs:12:11 + | +LL | check(s); + | ----- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `OsStr` + = note: required for the cast to the object type `dyn AsRef` +help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` + | +LL | check(&s); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 25fe474c3be1fb1893e4d32d3e59781c01a9a875 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Jun 2022 21:04:06 -0700 Subject: [PATCH 25/25] Note concrete type being coerced into object --- .../src/traits/error_reporting/suggestions.rs | 5 +++-- .../assoc-type-eq-with-dyn-atb-fail.stderr | 2 +- .../ui/associated-types/associated-types-eq-3.stderr | 2 +- .../associated-types-overridden-binding-2.stderr | 2 +- src/test/ui/associated-types/issue-65774-1.stderr | 2 +- src/test/ui/associated-types/issue-65774-2.stderr | 2 +- .../async-block-control-flow-static-semantics.stderr | 4 ++-- src/test/ui/async-await/issue-86507.stderr | 2 +- .../coerce-issue-49593-box-never.nofallback.stderr | 4 ++-- .../defaults/trait_objects_fail.stderr | 4 ++-- src/test/ui/custom_test_frameworks/mismatch.stderr | 2 +- src/test/ui/dst/dst-bad-coerce1.stderr | 4 ++-- src/test/ui/dst/dst-object-from-unsized-type.stderr | 8 ++++---- .../issue-79422.extended.stderr | 2 +- src/test/ui/issues/issue-14366.stderr | 2 +- src/test/ui/issues/issue-22034.stderr | 2 +- src/test/ui/issues/issue-22872.stderr | 2 +- src/test/ui/issues/issue-7013.stderr | 2 +- src/test/ui/kindck/kindck-impl-type-params.stderr | 12 ++++++------ src/test/ui/mismatched_types/cast-rfc0401.stderr | 4 ++-- .../never_type/fallback-closure-wrap.fallback.stderr | 2 +- .../suggestions/derive-macro-missing-bounds.stderr | 8 ++++---- .../suggestions/suggest-borrow-to-dyn-object.stderr | 2 +- src/test/ui/traits/coercion-generic-bad.stderr | 2 +- src/test/ui/traits/map-types.stderr | 2 +- .../trait-upcasting/type-checking-test-1.stderr | 2 +- .../trait-upcasting/type-checking-test-2.stderr | 4 ++-- src/test/ui/unsized/unsized-fn-param.stderr | 8 ++++---- 28 files changed, 50 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 166c7a4110b6c..12858172ee554 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2217,9 +2217,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_note(tcx.def_span(item_def_id), &descr); } } - ObligationCauseCode::ObjectCastObligation(_, object_ty) => { + ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => { err.note(&format!( - "required for the cast to the object type `{}`", + "required for the cast from `{}` to the object type `{}`", + self.ty_to_string(concrete_ty), self.ty_to_string(object_ty) )); } diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index f1dcd34066dbc..f40e6585b38b1 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | Box::new(AssocNoCopy) | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | - = note: required for the cast to the object type `dyn Bar::Out::{opaque#0}>` + = note: required for the cast from `AssocNoCopy` to the object type `dyn Bar::Out::{opaque#0}>` error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 521907a60445c..bed63a5e6df03 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -41,7 +41,7 @@ note: expected this to be `Bar` | LL | type A = usize; | ^^^^^ - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `isize` to the object type `dyn Foo` error: aborting due to 3 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index 9f1abf2a6c4b6..dbd9a44ed9774 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving ` as Iterator>::It LL | let _: &dyn I32Iterator = &vec![42].into_iter(); | ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` | - = note: required for the cast to the object type `dyn Iterator` + = note: required for the cast from `std::vec::IntoIter` to the object type `dyn Iterator` error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index e468a1b3ba484..419de689c52da 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -23,7 +23,7 @@ note: required because of the requirements on the impl of `MyDisplay` for `&mut | LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } | ^^^^^^^^^ ^^^^^^^^^ - = note: required for the cast to the object type `dyn MyDisplay` + = note: required for the cast from `&mut T` to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr index 4cef4db4698a7..c22302cdc2626 100644 --- a/src/test/ui/associated-types/issue-65774-2.stderr +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -18,7 +18,7 @@ LL | writer.my_write(valref) | ^^^^^^ the trait `MyDisplay` is not implemented for `T` | = help: the trait `MyDisplay` is implemented for `&'a mut T` - = note: required for the cast to the object type `dyn MyDisplay` + = note: required for the cast from `T` to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index e0818337d2039..e5887689690e7 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -37,7 +37,7 @@ error[E0271]: type mismatch resolving ` as Future>::Out LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` | - = note: required for the cast to the object type `dyn Future` + = note: required for the cast from `impl Future` to the object type `dyn Future` error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:12:43 @@ -53,7 +53,7 @@ error[E0271]: type mismatch resolving ` as Future>::Out LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` | - = note: required for the cast to the object type `dyn Future` + = note: required for the cast from `impl Future` to the object type `dyn Future` error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:47:44 diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr index 5bbc20359c64a..0e21dba980deb 100644 --- a/src/test/ui/async-await/issue-86507.stderr +++ b/src/test/ui/async-await/issue-86507.stderr @@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless | LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast to the object type `dyn Future + Send` + = note: required for the cast from `impl Future` to the object type `dyn Future + Send` help: consider further restricting this bound | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index fcd2d7f78ff75..322681b97bccb 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | - = note: required for the cast to the object type `dyn std::error::Error` + = note: required for the cast from `()` to the object type `dyn std::error::Error` error[E0277]: the trait bound `(): std::error::Error` is not satisfied --> $DIR/coerce-issue-49593-box-never.rs:23:49 @@ -12,7 +12,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | - = note: required for the cast to the object type `(dyn std::error::Error + 'static)` + = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr index 60dc96f675a8b..da85b2059f0a3 100644 --- a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr @@ -7,7 +7,7 @@ LL | foo(&10_u32); | required by a bound introduced by this call | = help: the trait `Trait<2_u8>` is implemented for `u32` - = note: required for the cast to the object type `dyn Trait` + = note: required for the cast from `u32` to the object type `dyn Trait` error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied --> $DIR/trait_objects_fail.rs:28:9 @@ -18,7 +18,7 @@ LL | bar(&true); | required by a bound introduced by this call | = help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` - = note: required for the cast to the object type `dyn Traitor<{_: u8}>` + = note: required for the cast from `bool` to the object type `dyn Traitor<{_: u8}>` error: aborting due to 2 previous errors diff --git a/src/test/ui/custom_test_frameworks/mismatch.stderr b/src/test/ui/custom_test_frameworks/mismatch.stderr index e848ddc55b7df..61061ae529d12 100644 --- a/src/test/ui/custom_test_frameworks/mismatch.stderr +++ b/src/test/ui/custom_test_frameworks/mismatch.stderr @@ -6,7 +6,7 @@ LL | #[test] LL | fn wrong_kind(){} | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn` | - = note: required for the cast to the object type `dyn Testable` + = note: required for the cast from `TestDescAndFn` to the object type `dyn Testable` = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/dst/dst-bad-coerce1.stderr b/src/test/ui/dst/dst-bad-coerce1.stderr index 121c76a01a5de..594acff853a0e 100644 --- a/src/test/ui/dst/dst-bad-coerce1.stderr +++ b/src/test/ui/dst/dst-bad-coerce1.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied LL | let f3: &Fat = f2; | ^^ the trait `Bar` is not implemented for `Foo` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast from `Foo` to the object type `dyn Bar` error[E0308]: mismatched types --> $DIR/dst-bad-coerce1.rs:28:27 @@ -34,7 +34,7 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied LL | let f3: &(dyn Bar,) = f2; | ^^ the trait `Bar` is not implemented for `Foo` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast from `Foo` to the object type `dyn Bar` error: aborting due to 4 previous errors diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr index 5bd47736626da..e24c96ebed633 100644 --- a/src/test/ui/dst/dst-object-from-unsized-type.stderr +++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr @@ -6,7 +6,7 @@ LL | fn test1(t: &T) { LL | let u: &dyn Foo = t; | ^ doesn't have a size known at compile-time | - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `T` to the object type `dyn Foo` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn test1(t: &T) { @@ -21,7 +21,7 @@ LL | fn test2(t: &T) { LL | let v: &dyn Foo = t as &dyn Foo; | ^ doesn't have a size known at compile-time | - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `T` to the object type `dyn Foo` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn test2(t: &T) { @@ -35,7 +35,7 @@ LL | let _: &[&dyn Foo] = &["hi"]; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `str` to the object type `dyn Foo` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:23:23 @@ -44,7 +44,7 @@ LL | let _: &dyn Foo = x as &dyn Foo; | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `[u8]` to the object type `dyn Foo` error: aborting due to 4 previous errors diff --git a/src/test/ui/generic-associated-types/issue-79422.extended.stderr b/src/test/ui/generic-associated-types/issue-79422.extended.stderr index 9478fc8979211..9bcbd74716845 100644 --- a/src/test/ui/generic-associated-types/issue-79422.extended.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.extended.stderr @@ -27,7 +27,7 @@ LL | type VRefCont<'a> = &'a V where Self: 'a; | ^^^^^ = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` found reference `&u8` - = note: required for the cast to the object type `dyn MapLike + 'static)>` + = note: required for the cast from `BTreeMap` to the object type `dyn MapLike + 'static)>` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-14366.stderr b/src/test/ui/issues/issue-14366.stderr index b96b07c91a1fe..10a73b245ac57 100644 --- a/src/test/ui/issues/issue-14366.stderr +++ b/src/test/ui/issues/issue-14366.stderr @@ -5,7 +5,7 @@ LL | let _x = "test" as &dyn (::std::any::Any); | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn Any` + = note: required for the cast from `str` to the object type `dyn Any` help: consider borrowing the value, since `&str` can be coerced into `dyn Any` | LL | let _x = &"test" as &dyn (::std::any::Any); diff --git a/src/test/ui/issues/issue-22034.stderr b/src/test/ui/issues/issue-22034.stderr index edcd21ebd6b9b..b32de5b24b924 100644 --- a/src/test/ui/issues/issue-22034.stderr +++ b/src/test/ui/issues/issue-22034.stderr @@ -6,7 +6,7 @@ LL | &mut *(ptr as *mut dyn Fn()) | = help: the trait `Fn<()>` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` - = note: required for the cast to the object type `dyn Fn()` + = note: required for the cast from `()` to the object type `dyn Fn()` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index cd96646d751f2..a84cb7d8c5922 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -10,7 +10,7 @@ note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for | LL | impl<'b, P> Wrap<'b> for Wrapper

| ^^^^^^^^ ^^^^^^^^^^ - = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` + = note: required for the cast from `Wrapper

` to the object type `dyn for<'b> Wrap<'b>` help: consider further restricting the associated type | LL | fn push_process

(process: P) where P: Process<'static>,

>::Item: Iterator { diff --git a/src/test/ui/issues/issue-7013.stderr b/src/test/ui/issues/issue-7013.stderr index 98ed67507b1d8..f6cb1cbdc11c6 100644 --- a/src/test/ui/issues/issue-7013.stderr +++ b/src/test/ui/issues/issue-7013.stderr @@ -11,7 +11,7 @@ note: required because it appears within the type `B` | LL | struct B { | ^ - = note: required for the cast to the object type `dyn Foo + Send` + = note: required for the cast from `B` to the object type `dyn Foo + Send` error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index 32759d2fa0ebd..902349135c549 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr @@ -9,7 +9,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn f(val: T) { @@ -26,7 +26,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn f(val: T) { @@ -43,7 +43,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn g(val: T) { @@ -60,7 +60,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn g(val: T) { @@ -78,7 +78,7 @@ note: required because of the requirements on the impl of `Gettable` for | LL | impl Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` error[E0277]: the trait bound `Foo: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:43:37 @@ -92,7 +92,7 @@ note: required because of the requirements on the impl of `Gettable` for `S | LL | impl Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider annotating `Foo` with `#[derive(Copy)]` | LL | #[derive(Copy)] diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index e63ca6e11de59..eab8e8e80c424 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -220,7 +220,7 @@ LL | let _ = fat_v as *const dyn Foo; | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `[u8]` to the object type `dyn Foo` help: consider borrowing the value, since `&[u8]` can be coerced into `dyn Foo` | LL | let _ = &fat_v as *const dyn Foo; @@ -233,7 +233,7 @@ LL | let _ = a as *const dyn Foo; | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `str` to the object type `dyn Foo` help: consider borrowing the value, since `&str` can be coerced into `dyn Foo` | LL | let _ = &a as *const dyn Foo; diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 78d1a3caf4a30..6b9635d4a60bc 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -10,7 +10,7 @@ LL | | }) as Box); | = note: expected unit type `()` found type `!` - = note: required for the cast to the object type `dyn FnMut()` + = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6]` to the object type `dyn FnMut()` error: aborting due to previous error diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr index 501d083e2bc60..4186dc7cb35ae 100644 --- a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr @@ -33,7 +33,7 @@ LL | impl Debug for Inner { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&c::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&c::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -55,7 +55,7 @@ LL | impl Debug for Inner where T: Debug, T: Trait { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&d::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&d::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -77,7 +77,7 @@ LL | impl Debug for Inner where T: Debug + Trait { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&e::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&e::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -99,7 +99,7 @@ LL | impl Debug for Inner where T: Trait { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&f::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&f::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr index 8961f4275a283..6b6e406130ec2 100644 --- a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr @@ -8,7 +8,7 @@ LL | check(s); | = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]` = note: required because it appears within the type `OsStr` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `OsStr` to the object type `dyn AsRef` help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` | LL | check(&s); diff --git a/src/test/ui/traits/coercion-generic-bad.stderr b/src/test/ui/traits/coercion-generic-bad.stderr index b213ee635df59..93d6770eb47d1 100644 --- a/src/test/ui/traits/coercion-generic-bad.stderr +++ b/src/test/ui/traits/coercion-generic-bad.stderr @@ -5,7 +5,7 @@ LL | let s: Box> = Box::new(Struct { person: "Fred" }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Struct` | = help: the trait `Trait<&'static str>` is implemented for `Struct` - = note: required for the cast to the object type `dyn Trait` + = note: required for the cast from `Struct` to the object type `dyn Trait` error: aborting due to previous error diff --git a/src/test/ui/traits/map-types.stderr b/src/test/ui/traits/map-types.stderr index a4686edb71757..f685c50b07d5b 100644 --- a/src/test/ui/traits/map-types.stderr +++ b/src/test/ui/traits/map-types.stderr @@ -5,7 +5,7 @@ LL | let y: Box> = Box::new(x); | ^^^^^^^^^^^ the trait `Map` is not implemented for `Box>` | = help: the trait `Map` is implemented for `HashMap` - = note: required for the cast to the object type `dyn Map` + = note: required for the cast from `Box>` to the object type `dyn Map` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr index 44f32e0cec91c..3985372119e88 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` | - = note: required for the cast to the object type `dyn Bar<_>` + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr index 4ae4c8552c161..93c71f54eb53a 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar` is not satisfied LL | let _ = x as &dyn Bar; // Error | ^ the trait `Bar` is not implemented for `&dyn Foo` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar` error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` --> $DIR/type-checking-test-2.rs:26:13 @@ -34,7 +34,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied LL | let a = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` | - = note: required for the cast to the object type `dyn Bar<_>` + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` error: aborting due to 4 previous errors diff --git a/src/test/ui/unsized/unsized-fn-param.stderr b/src/test/ui/unsized/unsized-fn-param.stderr index 3eecca0fa09d9..b477260543258 100644 --- a/src/test/ui/unsized/unsized-fn-param.stderr +++ b/src/test/ui/unsized/unsized-fn-param.stderr @@ -5,7 +5,7 @@ LL | foo11("bar", &"baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo11(&"bar", &"baz"); @@ -18,7 +18,7 @@ LL | foo12(&"bar", "baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo12(&"bar", &"baz"); @@ -31,7 +31,7 @@ LL | foo21("bar", &"baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo21(&"bar", &"baz"); @@ -44,7 +44,7 @@ LL | foo22(&"bar", "baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo22(&"bar", &"baz");